author | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
commit | b9aad1f15dc600e4dbe4c62d3fcced6363188ba3 (patch) (side-by-side diff) | |
tree | 2c3d4004fb21c72cba65793859f9bcd8ffd3a49c | |
download | kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.zip kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.gz kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.bz2 |
Initial revision
1107 files changed, 222913 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d6d78bc --- a/dev/null +++ b/Makefile @@ -0,0 +1,75 @@ +DISTPATH = $(shell pwd) +DISTDIR = $(shell basename $(DISTPATH)) + +SUBDIRS = libical/src/libical libical/src/libicalss qtcompat microkde \ + libkcal libkdepim kabc \ + korganizer kalarmd kaddressbook +all: tmake + for i in $(SUBDIRS); do pushd $$i; \ + make -f Makefile$(PLATFORM) || exit 1; popd; \ + done + +objects: + for i in $(SUBDIRS); do mkdir -p $$i/obj/$(PLATFORM); done + for i in $(SUBDIRS); do mkdir -p $$i/moc/$(PLATFORM); done + +clean: + rm -f libical/lib/$(PLATFORM)/*; + for i in $(SUBDIRS); do pushd $$i; make clean; rm -f *~;\ + rm -f obj/$(PLATFORM)/*; rm -f moc/$(PLATFORM)/*; rm Makefile$(PLATFORM); popd; \ + done +install: + cd bin/kdepim; make install + cp korganizer/korganizer.desktop $(QPEDIR)/apps/Pim/korganizer.desktop + cp kaddressbook/kaddressbook.desktop $(QPEDIR)/apps/Pim/kaddressbook.desktop + +dist: + @echo Dont forget to do "make install" before "make dist" + rm -f *arm.ipk + rm -f *~ + cd ..; tar czf kdepim.src.tar.gz --exclude=obj --exclude=moc kdepim + mkipks kdepim.control + mkipks korganizer-alarm.control + +tmake: objects qtcompat/Makefile$(PLATFORM) microkde/Makefile$(PLATFORM) \ + libkcal/Makefile$(PLATFORM) \ + libkdepim/Makefile$(PLATFORM) korganizer/Makefile$(PLATFORM) \ + kalarmd/Makefile$(PLATFORM) \ + libical/src/libical/Makefile$(PLATFORM) \ + libical/src/libicalss/Makefile$(PLATFORM) \ + kabc/Makefile$(PLATFORM) \ + kaddressbook/Makefile$(PLATFORM) + + + +qtcompat/Makefile$(PLATFORM): qtcompat/qtcompat.pro + cd qtcompat; tmake "CONFIG+=$(RELEASE_DEBUG)" qtcompat.pro -o Makefile$(PLATFORM) + +microkde/Makefile$(PLATFORM): microkde/microkdeE.pro + cd microkde; tmake "CONFIG+=$(RELEASE_DEBUG)" microkdeE.pro -o Makefile$(PLATFORM) + +libkcal/Makefile$(PLATFORM): libkcal/libkcalE.pro + cd libkcal; tmake "CONFIG+=$(RELEASE_DEBUG)" libkcalE.pro -o Makefile$(PLATFORM) + + +libkdepim/Makefile$(PLATFORM): libkdepim/libkdepimE.pro + cd libkdepim; tmake "CONFIG+=$(RELEASE_DEBUG)" libkdepimE.pro -o Makefile$(PLATFORM) + +kalarmd/Makefile$(PLATFORM): kalarmd/kalarmdE.pro + cd kalarmd; tmake "CONFIG+=$(RELEASE_DEBUG)" kalarmdE.pro -o Makefile$(PLATFORM) + +korganizer/Makefile$(PLATFORM): korganizer/korganizerE.pro + cd korganizer; tmake "CONFIG+=$(RELEASE_DEBUG)" korganizerE.pro -o Makefile$(PLATFORM) + +libical/src/libical/Makefile$(PLATFORM): libical/src/libical/libicalE.pro + cd libical/src/libical; tmake "CONFIG+=$(RELEASE_DEBUG)" libicalE.pro -o Makefile$(PLATFORM) + +libical/src/libicalss/Makefile$(PLATFORM): libical/src/libicalss/libicalssE.pro + cd libical/src/libicalss; tmake "CONFIG+=$(RELEASE_DEBUG)" libicalssE.pro -o Makefile$(PLATFORM) + +kabc/Makefile$(PLATFORM): kabc/kabcE.pro + cd kabc; tmake "CONFIG+=$(RELEASE_DEBUG)" kabcE.pro -o Makefile$(PLATFORM) + +kaddressbook/Makefile$(PLATFORM): kaddressbook/kaddressbookE.pro + cd kaddressbook; tmake "CONFIG+=$(RELEASE_DEBUG)" kaddressbookE.pro -o Makefile$(PLATFORM) + diff --git a/Makefile.Embedded b/Makefile.Embedded new file mode 100644 index 0000000..d6d78bc --- a/dev/null +++ b/Makefile.Embedded @@ -0,0 +1,75 @@ +DISTPATH = $(shell pwd) +DISTDIR = $(shell basename $(DISTPATH)) + +SUBDIRS = libical/src/libical libical/src/libicalss qtcompat microkde \ + libkcal libkdepim kabc \ + korganizer kalarmd kaddressbook +all: tmake + for i in $(SUBDIRS); do pushd $$i; \ + make -f Makefile$(PLATFORM) || exit 1; popd; \ + done + +objects: + for i in $(SUBDIRS); do mkdir -p $$i/obj/$(PLATFORM); done + for i in $(SUBDIRS); do mkdir -p $$i/moc/$(PLATFORM); done + +clean: + rm -f libical/lib/$(PLATFORM)/*; + for i in $(SUBDIRS); do pushd $$i; make clean; rm -f *~;\ + rm -f obj/$(PLATFORM)/*; rm -f moc/$(PLATFORM)/*; rm Makefile$(PLATFORM); popd; \ + done +install: + cd bin/kdepim; make install + cp korganizer/korganizer.desktop $(QPEDIR)/apps/Pim/korganizer.desktop + cp kaddressbook/kaddressbook.desktop $(QPEDIR)/apps/Pim/kaddressbook.desktop + +dist: + @echo Dont forget to do "make install" before "make dist" + rm -f *arm.ipk + rm -f *~ + cd ..; tar czf kdepim.src.tar.gz --exclude=obj --exclude=moc kdepim + mkipks kdepim.control + mkipks korganizer-alarm.control + +tmake: objects qtcompat/Makefile$(PLATFORM) microkde/Makefile$(PLATFORM) \ + libkcal/Makefile$(PLATFORM) \ + libkdepim/Makefile$(PLATFORM) korganizer/Makefile$(PLATFORM) \ + kalarmd/Makefile$(PLATFORM) \ + libical/src/libical/Makefile$(PLATFORM) \ + libical/src/libicalss/Makefile$(PLATFORM) \ + kabc/Makefile$(PLATFORM) \ + kaddressbook/Makefile$(PLATFORM) + + + +qtcompat/Makefile$(PLATFORM): qtcompat/qtcompat.pro + cd qtcompat; tmake "CONFIG+=$(RELEASE_DEBUG)" qtcompat.pro -o Makefile$(PLATFORM) + +microkde/Makefile$(PLATFORM): microkde/microkdeE.pro + cd microkde; tmake "CONFIG+=$(RELEASE_DEBUG)" microkdeE.pro -o Makefile$(PLATFORM) + +libkcal/Makefile$(PLATFORM): libkcal/libkcalE.pro + cd libkcal; tmake "CONFIG+=$(RELEASE_DEBUG)" libkcalE.pro -o Makefile$(PLATFORM) + + +libkdepim/Makefile$(PLATFORM): libkdepim/libkdepimE.pro + cd libkdepim; tmake "CONFIG+=$(RELEASE_DEBUG)" libkdepimE.pro -o Makefile$(PLATFORM) + +kalarmd/Makefile$(PLATFORM): kalarmd/kalarmdE.pro + cd kalarmd; tmake "CONFIG+=$(RELEASE_DEBUG)" kalarmdE.pro -o Makefile$(PLATFORM) + +korganizer/Makefile$(PLATFORM): korganizer/korganizerE.pro + cd korganizer; tmake "CONFIG+=$(RELEASE_DEBUG)" korganizerE.pro -o Makefile$(PLATFORM) + +libical/src/libical/Makefile$(PLATFORM): libical/src/libical/libicalE.pro + cd libical/src/libical; tmake "CONFIG+=$(RELEASE_DEBUG)" libicalE.pro -o Makefile$(PLATFORM) + +libical/src/libicalss/Makefile$(PLATFORM): libical/src/libicalss/libicalssE.pro + cd libical/src/libicalss; tmake "CONFIG+=$(RELEASE_DEBUG)" libicalssE.pro -o Makefile$(PLATFORM) + +kabc/Makefile$(PLATFORM): kabc/kabcE.pro + cd kabc; tmake "CONFIG+=$(RELEASE_DEBUG)" kabcE.pro -o Makefile$(PLATFORM) + +kaddressbook/Makefile$(PLATFORM): kaddressbook/kaddressbookE.pro + cd kaddressbook; tmake "CONFIG+=$(RELEASE_DEBUG)" kaddressbookE.pro -o Makefile$(PLATFORM) + diff --git a/Makefile.EmbeddedAll b/Makefile.EmbeddedAll new file mode 100644 index 0000000..cc4b553 --- a/dev/null +++ b/Makefile.EmbeddedAll @@ -0,0 +1,85 @@ +DISTPATH = $(shell pwd) +DISTDIR = $(shell basename $(DISTPATH)) + +SUBDIRS = libical/src/libical libical/src/libicalss qtcompat microkde \ + libkcal libkdepim kabc libkabcwrap pluginqtopiakabc pluginopiekabc \ + korganizer kalarmd kaddressbook +all: tmake + for i in $(SUBDIRS); do pushd $$i; \ + make -f Makefile$(PLATFORM) || exit 1; popd; \ + done + +objects: + for i in $(SUBDIRS); do mkdir -p $$i/obj/$(PLATFORM); done + +clean: + for i in $(SUBDIRS); do pushd $$i; make clean; \ + rm -f obj/$(PLATFORM)/*; rm -f moc/*; rm Makefile$(PLATFORM); popd; \ + done + +install: + cd bin/kdepimpi; make install + cp korganizer/korganizer.desktop $(QPEDIR)/apps/Pim/korganizer.desktop + cp kaddressbook/kaddressbook.desktop $(QPEDIR)/apps/Pim/kaddressbook.desktop + +dist: + @echo Dont forget to do "make install" before "make dist" + cd ..; tar czf korge-dist.src.tgz --exclude=obj --exclude=moc $(DISTDIR) + tar czPf ../korge-dist.i386.tgz \ + /opt/Qtopia/bin/korganizer \ + /opt/Qtopia/apps/Applications/korganizer.desktop \ + /opt/Qtopia/pics/KOrganizer.png \ + /opt/Qtopia/pics/korganizer + +tmake: objects qtcompat/Makefile$(PLATFORM) microkde/Makefile$(PLATFORM) \ + libkcal/Makefile$(PLATFORM) \ + libkabcwrap/Makefile$(PLATFORM) \ + pluginqtopiakabc/Makefile$(PLATFORM) \ + pluginopiekabc/Makefile$(PLATFORM) \ + libkdepim/Makefile$(PLATFORM) korganizer/Makefile$(PLATFORM) \ + kalarmd/Makefile$(PLATFORM) \ + libical/src/libical/Makefile$(PLATFORM) \ + libical/src/libicalss/Makefile$(PLATFORM) \ + kabc/Makefile$(PLATFORM) \ + kaddressbook/Makefile$(PLATFORM) + +qtcompat/Makefile$(PLATFORM): qtcompat/qtcompat.pro + cd qtcompat; tmake qtcompat.pro -o Makefile$(PLATFORM) + +microkde/Makefile$(PLATFORM): microkde/microkdeE.pro + cd microkde; tmake microkdeE.pro -o Makefile$(PLATFORM) + +libkcal/Makefile$(PLATFORM): libkcal/libkcalE.pro + cd libkcal; tmake libkcalE.pro -o Makefile$(PLATFORM) + +libkabcwrap/Makefile$(PLATFORM): libkabcwrap/libkabcwrapE.pro + cd libkabcwrap; tmake libkabcwrapE.pro -o Makefile$(PLATFORM) + +pluginqtopiakabc/Makefile$(PLATFORM): pluginqtopiakabc/pluginqtopiakabcE.pro + cd pluginqtopiakabc; tmake pluginqtopiakabcE.pro -o Makefile$(PLATFORM) + +pluginopiekabc/Makefile$(PLATFORM): pluginopiekabc/pluginopiekabcE.pro + cd pluginopiekabc; tmake pluginopiekabcE.pro -o Makefile$(PLATFORM) + + +libkdepim/Makefile$(PLATFORM): libkdepim/libkdepimE.pro + cd libkdepim; tmake libkdepimE.pro -o Makefile$(PLATFORM) + +kalarmd/Makefile$(PLATFORM): kalarmd/kalarmdE.pro + cd kalarmd; tmake kalarmdE.pro -o Makefile$(PLATFORM) + +korganizer/Makefile$(PLATFORM): korganizer/korganizerE.pro + cd korganizer; tmake korganizerE.pro -o Makefile$(PLATFORM) + +libical/src/libical/Makefile$(PLATFORM): libical/src/libical/libicalE.pro + cd libical/src/libical; tmake libicalE.pro -o Makefile$(PLATFORM) + +libical/src/libicalss/Makefile$(PLATFORM): libical/src/libicalss/libicalssE.pro + cd libical/src/libicalss; tmake libicalssE.pro -o Makefile$(PLATFORM) + +kabc/Makefile$(PLATFORM): kabc/kabcE.pro + cd kabc; tmake kabcE.pro -o Makefile$(PLATFORM) + +kaddressbook/Makefile$(PLATFORM): kaddressbook/kaddressbookE.pro + cd kaddressbook; tmake kaddressbookE.pro -o Makefile$(PLATFORM) + @@ -0,0 +1,103 @@ + +Howto Compile KO/Pi for Qt-Embedded: + +Remove all Makefile files first! + +Please look at the files setQtopia and setZaurus in the same dir. + +You may have to +- create a softlink from + /opt/qtopia/include/qpe to /opt/qtopia/include/qtopia +- remove + -ljpeg in korganizer/Makefilezaurus +-create the directory + /opt/Qtopia/sharp/plugins + /opt/Qtopia/sharp/plugins/applets + +to get the sources compiled, depending on your Qtopia compiler setup. +The needed Makefile is Makefile.Embedded. +Copy it and rename it to Makefile. + +To build for the Zaurus: +Install Qtopia development environment and the cross-compiler. + +The file sharp.tmake.conf contains e DEFINE,which is needed to fix the QWhatsThis problem: +TMAKE_CXXFLAGS = blabla -DADD_TOOLTIP +Add this to your tmake.conf file for sharp. + +Now, you can do from command line a: +cz #comment: for setZaurus +make clean #comment: for removing old Makefiles - if there are any +make +make install +make clean +make dist + +to build a binary and source package. +The sources are ../kdepim.src.tar.gz +The binaries are +korganizer-alarm_1.9.0a_arm.ipk +and +kdepim_1.9.0a_arm.ipk +, depending on the version. + +========================================================= + +Howto Compile+Run KO/Pi Desktop for Linux Desktop: + +Remove all Makefile files first! + +Set the needed environment variables to compile a Qt program. +(e.g. QTDIR, ,... ) +Do a +qmake +make clean +make +in this directory. + +After compilation, you will find the binary and the libs in ./bin. + + +Goto ./bin in console and type type ./kopi + +Now kopi starts. + +========================================================= + +KOrganizer/Platform-independent (KO/Pi) + + +This is the platform-independend version of KOrganizer. It includes a replacement for the +KDE libraries called microkde, which provides the KDE specific functions +KOrganizer needs, but does not add the overhead of the complete implementation. +KOrganizer/Pi compiles with Qt/Embedded 2.3.2 and the corresponding QPE libs. + +It compiles with Qt 3.2.3 on the Linux or Windows desktop as well. + +KOrganizer/Pi is based on the unaltered original KOrganizer code from the KDE CVS +HEAD branch of spring 2003. + +Some functionality of the full KDE version of Korganizer is not present in the +platform-independend, because microkde is not yet complete. + +KOrganizer/Pi is licenced under the GPL, the microkde library is licenced under +the LGPL and the original KOrganizer code is licenced under GPL or LPGL. + +If you have questions or comments please contact Lutz Rogowski +<rogowski@kde.org>. + + +History +------- + +1.5 (January 2004) + - Korganizer/E has been renamed to Korganizer/Pi (platform-independend) + In this version, there are many bugfixes/enhancements. + +1.0 (April 2002): + + - First stable release as final submission to the Trolltech Qtopia contest. + +0.8 (beta1) (January 2002): + + - Initial release as entry to the Trolltech Qtopia contest. diff --git a/bin/.kdbgrc.kopi b/bin/.kdbgrc.kopi new file mode 100644 index 0000000..a48d84f --- a/dev/null +++ b/bin/.kdbgrc.kopi @@ -0,0 +1,28 @@ +[Breakpoint 0] +Enabled=true +File=mainwindow.cpp +Line=94 +Temporary=false + +[Breakpoint 1] +Enabled=true +File=mainwindow.cpp +Line=86 +Temporary=false + +[Breakpoint 2] +Enabled=true +File=koagenda.cpp +Line=1329 +Temporary=false + +[General] +DebuggerCmdStr= +FileVersion=1 +ProgramArgs= +TTYLevel=7 +WorkingDirectory= + +[Memory] +ColumnWidths=80,0 +NumExprs=0 diff --git a/bin/ReadMich.txt b/bin/ReadMich.txt new file mode 100644 index 0000000..cdd4bca --- a/dev/null +++ b/bin/ReadMich.txt @@ -0,0 +1,70 @@ +This is the Windows version of KO/Pi or KA/Pi. (www.pi-sync.net) +The same as mentioned for KO/Pi is valid for KA/Pi as well. +KO/Pi is the port (with many enhancements) of the KOrganizers from the KDE Desktop for Linux. +KA/Pi is the port of the KAddressbook from the KDE Desktop for Linux. + +Copy this directory (with all files )to a directory where you want. +NOTE: You do not need to copy it to C:/. +The need of fixed path of previous versions is removed. + +The calendar files and templates are stored in +(yourHomeDir)/kdepim/korganizer/mycalendar.ics. + +To run kopi you need the files kopi.exe +and the Qt 3.1 lib qt-mt331.dll. +(And msvcr71.dll, which is packed together with qt-mt331.dll) + +All files should be in the same path as kopi.exe. + +You can download kopi.exe from +http://sourceforge.net/projects/kdepimpi/ +section KO/Pi -Version 1.7x. +File kopi17x-exe.zip + +You can download qt-mt331.dll from +http://sourceforge.net/projects/kdepimpi/ +section KO/Pi - general files - Version 1.75. +File kopidll.zip + +This file will work with versions of kopi > 1.75. + +The link is + +http://sourceforge.net/project/showfiles.php?group_id=104103&package_id=116719 + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Das ist die Windows Version von KO/Pi oder KA/Pi. (www.pi-sync.net) +Dasselbe was für KO/Pi geschrieben wird ist auch für KA/Pi gültig. +KO/Pi ist die Portierung und Verbesserung des KOrganizers des KDE Desktops für Linux. +KA/Pi ist die Portierung des KAddressbook-Adressbuchs des KDE Desktops für Linux. + +Kopieren Sie dieses Verzeichnis (mit allen Dateien ) in ein Verzeichnis ihrer Wahl. +Anmerkung: Die Abhängigkeit von einem festen Pfad wie in früheren Versionen gibt es nicht mehr. + +Die Calender Datei und die Template Files werden im Verzeichnis +(Heimatverzeichnis)/kdepim/korganizer/mycalendar.ics gespeichert. + + +Um KO/Pi ausführen zu können brauchen Sie die Dateien kopi.exe +und die Qt 3.1 lib qt-mt331.dll. +(Und msvcr71.dll, welche es zusammen mit qt-mt331.dll gibt) + +Alle Dateien sollten im selben Pfad wie kopi.exe sein. + +Sie können kopi.exe runterladen von +http://sourceforge.net/projects/kdepimpi/ +section KO/Pi -Version 1.7x. +Datei kopi17x-exe.zip + +Sie können qt-mt331.dll runterladen von +http://sourceforge.net/projects/kdepimpi/ +section KO/Pi - general files - Version 1.75. +Datei kopidll.zip + +Diese Datei funktioniert auch mit Versionen von Kopi > 1.75. + +Der direkte Link ist + +http://sourceforge.net/project/showfiles.php?group_id=104103&package_id=116719 + diff --git a/bin/kdepim/Makefile b/bin/kdepim/Makefile new file mode 100644 index 0000000..50c3866 --- a/dev/null +++ b/bin/kdepim/Makefile @@ -0,0 +1,3 @@ +install: + cp -r . $(QPEDIR)/pics/kdepim + cp korganizer/ko*.png $(QPEDIR)/pics
\ No newline at end of file diff --git a/bin/kdepim/Makefile.bup b/bin/kdepim/Makefile.bup new file mode 100644 index 0000000..50c3866 --- a/dev/null +++ b/bin/kdepim/Makefile.bup @@ -0,0 +1,3 @@ +install: + cp -r . $(QPEDIR)/pics/kdepim + cp korganizer/ko*.png $(QPEDIR)/pics
\ No newline at end of file diff --git a/bin/kdepim/kaddressbook/icons16/1downarrow.png b/bin/kdepim/kaddressbook/icons16/1downarrow.png Binary files differnew file mode 100644 index 0000000..91ceba5 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/1downarrow.png diff --git a/bin/kdepim/kaddressbook/icons16/1leftarrow.png b/bin/kdepim/kaddressbook/icons16/1leftarrow.png Binary files differnew file mode 100644 index 0000000..610493d --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/1leftarrow.png diff --git a/bin/kdepim/kaddressbook/icons16/1leftarrowB.png b/bin/kdepim/kaddressbook/icons16/1leftarrowB.png Binary files differnew file mode 100644 index 0000000..7e3fda7 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/1leftarrowB.png diff --git a/bin/kdepim/kaddressbook/icons16/1rightarrow.png b/bin/kdepim/kaddressbook/icons16/1rightarrow.png Binary files differnew file mode 100644 index 0000000..3cee2d6 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/1rightarrow.png diff --git a/bin/kdepim/kaddressbook/icons16/1rightarrowB.png b/bin/kdepim/kaddressbook/icons16/1rightarrowB.png Binary files differnew file mode 100644 index 0000000..3264e13 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/1rightarrowB.png diff --git a/bin/kdepim/kaddressbook/icons16/1uparrow.png b/bin/kdepim/kaddressbook/icons16/1uparrow.png Binary files differnew file mode 100644 index 0000000..8283c1f --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/1uparrow.png diff --git a/bin/kdepim/kaddressbook/icons16/2downarrow.png b/bin/kdepim/kaddressbook/icons16/2downarrow.png Binary files differnew file mode 100644 index 0000000..47976d5 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/2downarrow.png diff --git a/bin/kdepim/kaddressbook/icons16/2leftarrow.png b/bin/kdepim/kaddressbook/icons16/2leftarrow.png Binary files differnew file mode 100644 index 0000000..118a111 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/2leftarrow.png diff --git a/bin/kdepim/kaddressbook/icons16/2leftarrowB.png b/bin/kdepim/kaddressbook/icons16/2leftarrowB.png Binary files differnew file mode 100644 index 0000000..4506c40 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/2leftarrowB.png diff --git a/bin/kdepim/kaddressbook/icons16/2rightarrow.png b/bin/kdepim/kaddressbook/icons16/2rightarrow.png Binary files differnew file mode 100644 index 0000000..a4169d2 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/2rightarrow.png diff --git a/bin/kdepim/kaddressbook/icons16/2rightarrowB.png b/bin/kdepim/kaddressbook/icons16/2rightarrowB.png Binary files differnew file mode 100644 index 0000000..7210438 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/2rightarrowB.png diff --git a/bin/kdepim/kaddressbook/icons16/2uparrow.png b/bin/kdepim/kaddressbook/icons16/2uparrow.png Binary files differnew file mode 100644 index 0000000..e4efd67 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/2uparrow.png diff --git a/bin/kdepim/kaddressbook/icons16/configure.png b/bin/kdepim/kaddressbook/icons16/configure.png Binary files differnew file mode 100644 index 0000000..0c95c52 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/configure.png diff --git a/bin/kdepim/kaddressbook/icons16/configure_resources.png b/bin/kdepim/kaddressbook/icons16/configure_resources.png Binary files differnew file mode 100644 index 0000000..0c95c52 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/configure_resources.png diff --git a/bin/kdepim/kaddressbook/icons16/configure_shortcuts.png b/bin/kdepim/kaddressbook/icons16/configure_shortcuts.png Binary files differnew file mode 100644 index 0000000..400f342 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/configure_shortcuts.png diff --git a/bin/kdepim/kaddressbook/icons16/edit.png b/bin/kdepim/kaddressbook/icons16/edit.png Binary files differnew file mode 100644 index 0000000..98713ac --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/edit.png diff --git a/bin/kdepim/kaddressbook/icons16/editcopy.png b/bin/kdepim/kaddressbook/icons16/editcopy.png Binary files differnew file mode 100644 index 0000000..c600e99 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/editcopy.png diff --git a/bin/kdepim/kaddressbook/icons16/editcut.png b/bin/kdepim/kaddressbook/icons16/editcut.png Binary files differnew file mode 100644 index 0000000..21c3673 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/editcut.png diff --git a/bin/kdepim/kaddressbook/icons16/editdelete.png b/bin/kdepim/kaddressbook/icons16/editdelete.png Binary files differnew file mode 100644 index 0000000..e94aa33 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/editdelete.png diff --git a/bin/kdepim/kaddressbook/icons16/editpaste.png b/bin/kdepim/kaddressbook/icons16/editpaste.png Binary files differnew file mode 100644 index 0000000..f6a1db8 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/editpaste.png diff --git a/bin/kdepim/kaddressbook/icons16/exit.png b/bin/kdepim/kaddressbook/icons16/exit.png Binary files differnew file mode 100644 index 0000000..3ce5300 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/exit.png diff --git a/bin/kdepim/kaddressbook/icons16/filenew.png b/bin/kdepim/kaddressbook/icons16/filenew.png Binary files differnew file mode 100644 index 0000000..3434c3d --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/filenew.png diff --git a/bin/kdepim/kaddressbook/icons16/fileopen.png b/bin/kdepim/kaddressbook/icons16/fileopen.png Binary files differnew file mode 100644 index 0000000..2d27efc --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/fileopen.png diff --git a/bin/kdepim/kaddressbook/icons16/fileprint.png b/bin/kdepim/kaddressbook/icons16/fileprint.png Binary files differnew file mode 100644 index 0000000..d01bc39 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/fileprint.png diff --git a/bin/kdepim/kaddressbook/icons16/filesave.png b/bin/kdepim/kaddressbook/icons16/filesave.png Binary files differnew file mode 100644 index 0000000..14d339d --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/filesave.png diff --git a/bin/kdepim/kaddressbook/icons16/filter.png b/bin/kdepim/kaddressbook/icons16/filter.png Binary files differnew file mode 100644 index 0000000..13c113b --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/filter.png diff --git a/bin/kdepim/kaddressbook/icons16/gohome.png b/bin/kdepim/kaddressbook/icons16/gohome.png Binary files differnew file mode 100644 index 0000000..af211a5 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/gohome.png diff --git a/bin/kdepim/kaddressbook/icons16/homepage.png b/bin/kdepim/kaddressbook/icons16/homepage.png Binary files differnew file mode 100644 index 0000000..6598c35 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/homepage.png diff --git a/bin/kdepim/kaddressbook/icons16/ka24.png b/bin/kdepim/kaddressbook/icons16/ka24.png Binary files differnew file mode 100644 index 0000000..738e939 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/ka24.png diff --git a/bin/kdepim/kaddressbook/icons16/kaddressbook.png b/bin/kdepim/kaddressbook/icons16/kaddressbook.png Binary files differnew file mode 100644 index 0000000..58ded80 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/kaddressbook.png diff --git a/bin/kdepim/kaddressbook/icons16/mail_post_to.png b/bin/kdepim/kaddressbook/icons16/mail_post_to.png Binary files differnew file mode 100644 index 0000000..a4ec85a --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/mail_post_to.png diff --git a/bin/kdepim/kaddressbook/icons16/mail_send.png b/bin/kdepim/kaddressbook/icons16/mail_send.png Binary files differnew file mode 100644 index 0000000..62b0534 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/mail_send.png diff --git a/bin/kdepim/kaddressbook/icons16/next.png b/bin/kdepim/kaddressbook/icons16/next.png Binary files differnew file mode 100644 index 0000000..f0b977b --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/next.png diff --git a/bin/kdepim/kaddressbook/icons16/package_network.png b/bin/kdepim/kaddressbook/icons16/package_network.png Binary files differnew file mode 100644 index 0000000..3f7323c --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/package_network.png diff --git a/bin/kdepim/kaddressbook/icons16/package_toys.png b/bin/kdepim/kaddressbook/icons16/package_toys.png Binary files differnew file mode 100644 index 0000000..eea4fc7 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/package_toys.png diff --git a/bin/kdepim/kaddressbook/icons16/redo.png b/bin/kdepim/kaddressbook/icons16/redo.png Binary files differnew file mode 100644 index 0000000..d6b3e8f --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/redo.png diff --git a/bin/kdepim/kaddressbook/icons16/reload.png b/bin/kdepim/kaddressbook/icons16/reload.png Binary files differnew file mode 100644 index 0000000..e7aeaac --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/reload.png diff --git a/bin/kdepim/kaddressbook/icons16/smallcal.png b/bin/kdepim/kaddressbook/icons16/smallcal.png Binary files differnew file mode 100644 index 0000000..f086a76 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/smallcal.png diff --git a/bin/kdepim/kaddressbook/icons16/undo.png b/bin/kdepim/kaddressbook/icons16/undo.png Binary files differnew file mode 100644 index 0000000..f5ad210 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/undo.png diff --git a/bin/kdepim/kaddressbook/icons16/vcard.png b/bin/kdepim/kaddressbook/icons16/vcard.png Binary files differnew file mode 100644 index 0000000..6c8bbee --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/vcard.png diff --git a/bin/kdepim/kaddressbook/icons16/view_detailed.png b/bin/kdepim/kaddressbook/icons16/view_detailed.png Binary files differnew file mode 100644 index 0000000..5665c74 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/view_detailed.png diff --git a/bin/kdepim/kaddressbook/icons16/view_remove.png b/bin/kdepim/kaddressbook/icons16/view_remove.png Binary files differnew file mode 100644 index 0000000..0780355 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/view_remove.png diff --git a/bin/kdepim/kaddressbook/icons16/window_new.png b/bin/kdepim/kaddressbook/icons16/window_new.png Binary files differnew file mode 100644 index 0000000..06cf3d1 --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/window_new.png diff --git a/bin/kdepim/kaddressbook/icons16/world.jpg b/bin/kdepim/kaddressbook/icons16/world.jpg Binary files differnew file mode 100644 index 0000000..1447b3d --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/world.jpg diff --git a/bin/kdepim/kaddressbook/icons16/world.png b/bin/kdepim/kaddressbook/icons16/world.png Binary files differnew file mode 100644 index 0000000..e515bdd --- a/dev/null +++ b/bin/kdepim/kaddressbook/icons16/world.png diff --git a/bin/kdepim/kaddressbook/kaddressbook.png b/bin/kdepim/kaddressbook/kaddressbook.png Binary files differnew file mode 100644 index 0000000..87f6aa6 --- a/dev/null +++ b/bin/kdepim/kaddressbook/kaddressbook.png diff --git a/bin/kdepim/kaddressbook/kaddressbook2.png b/bin/kdepim/kaddressbook/kaddressbook2.png Binary files differnew file mode 100644 index 0000000..6b0dec6 --- a/dev/null +++ b/bin/kdepim/kaddressbook/kaddressbook2.png diff --git a/bin/kdepim/kaddressbook/zone.tab b/bin/kdepim/kaddressbook/zone.tab new file mode 100644 index 0000000..0019165 --- a/dev/null +++ b/bin/kdepim/kaddressbook/zone.tab @@ -0,0 +1,371 @@ +# TZ zone descriptions +# +# From Paul Eggert <eggert@twinsun.com> (1996-08-05): +# +# This file contains a table with the following columns: +# 1. ISO 3166 2-character country code. See the file `iso3166.tab'. +# 2. Latitude and longitude of the zone's principal location +# in ISO 6709 sign-degrees-minutes-seconds format, +# either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS, +# first latitude (+ is north), then longitude (+ is east). +# 3. Zone name used in value of TZ environment variable. +# 4. Comments; present if and only if the country has multiple rows. +# +# Columns are separated by a single tab. +# The table is sorted first by country, then an order within the country that +# (1) makes some geographical sense, and +# (2) puts the most populous zones first, where that does not contradict (1). +# +# Lines beginning with `#' are comments. +# +#country- +#code coordinates TZ comments +AD +4230+00131 Europe/Andorra +AE +2518+05518 Asia/Dubai +AF +3431+06912 Asia/Kabul +AG +1703-06148 America/Antigua +AI +1812-06304 America/Anguilla +AL +4120+01950 Europe/Tirane +AM +4011+04430 Asia/Yerevan +AN +1211-06900 America/Curacao +AO -0848+01314 Africa/Luanda +AQ -7750+16636 Antarctica/McMurdo McMurdo Station, Ross Island +AQ -9000+00000 Antarctica/South_Pole Amundsen-Scott Station, South Pole +AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island +AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay +AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills +AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula +AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Base, Terre Adelie +AR -3436-05827 America/Buenos_Aires E Argentina (BA, DF, SC, TF) +AR -3257-06040 America/Rosario NE Argentina (SF, ER, CN, MN, CC, FM, LP, CH) +AR -3124-06411 America/Cordoba W Argentina (CB, SA, TM, LR, SJ, SL, NQ, RN) +AR -2411-06518 America/Jujuy Jujuy (JY) +AR -2828-06547 America/Catamarca Catamarca (CT) +AR -3253-06849 America/Mendoza Mendoza (MZ) +AS -1416-17042 Pacific/Pago_Pago +AT +4813+01620 Europe/Vienna +AU -3133+15905 Australia/Lord_Howe Lord Howe Island +AU -4253+14719 Australia/Hobart Tasmania +AU -3749+14458 Australia/Melbourne Victoria +AU -3352+15113 Australia/Sydney New South Wales - most locations +AU -3157+14127 Australia/Broken_Hill New South Wales - Broken Hill +AU -2728+15302 Australia/Brisbane Queensland - most locations +AU -2016+14900 Australia/Lindeman Queensland - Holiday Islands +AU -3455+13835 Australia/Adelaide South Australia +AU -1228+13050 Australia/Darwin Northern Territory +AU -3157+11551 Australia/Perth Western Australia +AW +1230-06858 America/Aruba +AZ +4023+04951 Asia/Baku +BA +4352+01825 Europe/Sarajevo +BB +1306-05937 America/Barbados +BD +2343+09025 Asia/Dacca +BE +5050+00420 Europe/Brussels +BF +1222-00131 Africa/Ouagadougou +BG +4241+02319 Europe/Sofia +BH +2623+05035 Asia/Bahrain +BI -0323+02922 Africa/Bujumbura +BJ +0629+00237 Africa/Porto-Novo +BM +3217-06446 Atlantic/Bermuda +BN +0456+11455 Asia/Brunei +BO -1630-06809 America/La_Paz +BR -0351-03225 America/Noronha Fernando de Noronha +BR -0343-03830 America/Fortaleza NE Brazil (AP, east PA, MA, PI, CE, RN, PR, PE) +BR -0940-03543 America/Maceio ENE Brazil (AL, SE, TO) +BR -2332-04637 America/Sao_Paulo S & SE Brazil (BA, GO, DF, MG, ES, RJ, SP, PR, SC, RS) +BR -1535-05605 America/Cuiaba SW Brazil (MT, MS) +BR -0308-06001 America/Manaus NW Brazil (RR, west PA, AM, RO) +BR -0934-06731 America/Porto_Acre Acre +BS +2505-07721 America/Nassau +BT +2728+08939 Asia/Thimbu +BW -2545+02555 Africa/Gaborone +BY +5354+02734 Europe/Minsk +BZ +1730-08812 America/Belize +CA +4734-05243 America/St_Johns Newfoundland Island +CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), NB, W Labrador, E Quebec & PEI +CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971 +CA +5320-06025 America/Goose_Bay Atlantic Time - E Labrador +CA +6608-06544 America/Pangnirtung Atlantic Time - Northwest Territories +CA +4531-07334 America/Montreal Eastern Time - Ontario & Quebec - most locations +CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973 +CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario +CA +6344-06828 America/Iqaluit Eastern Time - Northwest Territories +CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario +CA +4843-09429 America/Rainy_River Central Time - Rainy River & Fort Frances, Ontario +CA +6245-09210 America/Rankin_Inlet Central Time - Northwest Territories +CA +5024-10439 America/Regina Central Standard Time - Saskatchewan - most locations +CA +5017-10750 America/Swift_Current Central Standard Time - Saskatchewan - midwest +CA +5333-11328 America/Edmonton Mountain Time - Alberta, east British Columbia & west Saskatchewan +CA +6227-11421 America/Yellowknife Mountain Time - central Northwest Territories +CA +6825-11330 America/Inuvik Mountain Time - west Northwest Territories +CA +5946-12014 America/Dawson_Creek Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia +CA +4916-12307 America/Vancouver Pacific Time - west British Columbia +CA +6043-13503 America/Whitehorse Pacific Time - south Yukon +CA +6404-13925 America/Dawson Pacific Time - north Yukon +CC -1210+09655 Indian/Cocos +CD -0418+01518 Africa/Kinshasa west Dem. Rep. of Congo +CD -1140+02728 Africa/Lubumbashi east Dem. Rep. of Congo +CF +0422+01835 Africa/Bangui +CG -0416+01517 Africa/Brazzaville +CH +4723+00832 Europe/Zurich +CI +0519-00402 Africa/Abidjan +CK -2114-15946 Pacific/Rarotonga +CL -3327-07040 America/Santiago mainland +CL -2710-10927 Pacific/Easter Easter Island +CM +0403+00942 Africa/Douala +CN +4545+12641 Asia/Harbin north Manchuria +CN +3114+12128 Asia/Shanghai China coast +CN +2217+11409 Asia/Hong_Kong Hong Kong +CN +2934+10635 Asia/Chungking China mountains +CN +4348+08735 Asia/Urumqi Tibet & Xinjiang +CN +3929+07559 Asia/Kashgar Eastern Turkestan +CO +0436-07405 America/Bogota +CR +0956-08405 America/Costa_Rica +CU +2308-08222 America/Havana +CV +1455-02331 Atlantic/Cape_Verde +CX -1025+10543 Indian/Christmas +CY +3510+03322 Asia/Nicosia +CZ +5005+01426 Europe/Prague +DE +5230+01322 Europe/Berlin +DJ +1136+04309 Africa/Djibouti +DK +5540+01235 Europe/Copenhagen +DM +1518-06124 America/Dominica +DO +1828-06954 America/Santo_Domingo +DZ +3647+00303 Africa/Algiers +EC -0210-07950 America/Guayaquil mainland +EC -0054-08936 Pacific/Galapagos Galapagos Islands +EE +5925+02445 Europe/Tallinn +EG +3003+03115 Africa/Cairo +EH +2709-01312 Africa/El_Aaiun +ER +1520+03853 Africa/Asmera +ES +4024-00341 Europe/Madrid mainland +ES +3553-00519 Africa/Ceuta Ceuta & Melilla +ES +2806-01524 Atlantic/Canary Canary Islands +ET +0902+03842 Africa/Addis_Ababa +FI +6010+02458 Europe/Helsinki +FJ -1808+17825 Pacific/Fiji +FK -5142-05751 Atlantic/Stanley +FM +0931+13808 Pacific/Yap Yap +FM +0725+15147 Pacific/Truk Truk (Chuuk) +FM +0658+15813 Pacific/Ponape Ponape (Pohnpei) +FM +0519+16259 Pacific/Kosrae Kosrae +FO +6201-00646 Atlantic/Faeroe +FR +4852+00220 Europe/Paris +GA +0023+00927 Africa/Libreville +GB +512830-0001845 Europe/London Great Britain +GB +5435-00555 Europe/Belfast Northern Ireland +GD +1203-06145 America/Grenada +GE +4143+04449 Asia/Tbilisi +GF +0456-05220 America/Cayenne +GH +0533-00013 Africa/Accra +GI +3608-00521 Europe/Gibraltar +GL +7030-02215 America/Scoresbysund east Greenland +GL +6411-05144 America/Godthab southwest Greenland +GL +7634-06847 America/Thule northwest Greenland +GM +1328-01639 Africa/Banjul +GN +0931-01343 Africa/Conakry +GP +1614-06132 America/Guadeloupe +GQ +0345+00847 Africa/Malabo +GR +3758+02343 Europe/Athens +GS -5416-03632 Atlantic/South_Georgia +GT +1438-09031 America/Guatemala +GU +1328+14445 Pacific/Guam +GW +1151-01535 Africa/Bissau +GY +0648-05810 America/Guyana +HN +1406-08713 America/Tegucigalpa +HR +4548+01558 Europe/Zagreb +HT +1832-07220 America/Port-au-Prince +HU +4730+01905 Europe/Budapest +ID -0610+10648 Asia/Jakarta Java & Sumatra +ID -0507+11924 Asia/Ujung_Pandang Borneo & Celebes +ID -0232+14042 Asia/Jayapura Irian Jaya & the Moluccas +IE +5320-00615 Europe/Dublin +IL +3146+03514 Asia/Jerusalem +IN +2232+08822 Asia/Calcutta +IO -0720+07225 Indian/Chagos +IQ +3321+04425 Asia/Baghdad +IR +3540+05126 Asia/Tehran +IS +6409-02151 Atlantic/Reykjavik +IT +4154+01229 Europe/Rome +JM +1800-07648 America/Jamaica +JO +3157+03556 Asia/Amman +JP +3542+13946 Asia/Tokyo most locations +KE -0117+03649 Africa/Nairobi +KG +4254+07436 Asia/Bishkek +KH +1133+10455 Asia/Phnom_Penh +KI +0125+17300 Pacific/Tarawa Gilbert Islands +KI -0308-17105 Pacific/Enderbury Phoenix Islands +KI +0152-15720 Pacific/Kiritimati Line Islands +KM -1141+04316 Indian/Comoro +KN +1718-06243 America/St_Kitts +KP +3901+12545 Asia/Pyongyang +KR +3733+12658 Asia/Seoul +KW +2920+04759 Asia/Kuwait +KY +1918-08123 America/Cayman +KZ +4315+07657 Asia/Alma-Ata east Kazakhstan +KZ +5017+05710 Asia/Aqtobe central Kazakhstan +KZ +4431+05016 Asia/Aqtau west Kazakhstan +LA +1758+10236 Asia/Vientiane +LB +3353+03530 Asia/Beirut +LC +1401-06100 America/St_Lucia +LI +4709+00931 Europe/Vaduz +LK +0656+07951 Asia/Colombo +LR +0618-01047 Africa/Monrovia +LS -2928+02730 Africa/Maseru +LT +5441+02519 Europe/Vilnius +LU +4936+00609 Europe/Luxembourg +LV +5657+02406 Europe/Riga +LY +3254+01311 Africa/Tripoli +MA +3339-00735 Africa/Casablanca +MC +4342+00723 Europe/Monaco +MD +4700+02850 Europe/Chisinau +MG -1855+04731 Indian/Antananarivo +MH +0709+17112 Pacific/Majuro most locations +MH +0905+16720 Pacific/Kwajalein Kwajalein +MK +4159+02126 Europe/Skopje +ML +1239-00800 Africa/Bamako southwest Mali +ML +1446-00301 Africa/Timbuktu northeast Mali +MM +1647+09610 Asia/Rangoon +MN +4755+10653 Asia/Ulan_Bator +MO +2214+11335 Asia/Macao +MP +1512+14545 Pacific/Saipan +MQ +1436-06105 America/Martinique +MR +1806-01557 Africa/Nouakchott +MS +1644-06213 America/Montserrat +MT +3554+01431 Europe/Malta +MU -2010+05730 Indian/Mauritius +MV +0410+07330 Indian/Maldives +MW -1547+03500 Africa/Blantyre +MX +1924-09909 America/Mexico_City Central Time +MX +2313-10625 America/Mazatlan Mountain Time +MX +3152-11637 America/Ensenada Pacific Time - most locations +MX +3232-11701 America/Tijuana Pacific Time - north Baja California +MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia +MY +0133+11020 Asia/Kuching Sabah & Sarawak +MZ -2558+03235 Africa/Maputo +NA -2234+01706 Africa/Windhoek +NC -2216+16530 Pacific/Noumea +NE +1331+00207 Africa/Niamey +NF -2903+16758 Pacific/Norfolk +NG +0627+00324 Africa/Lagos +NI +1209-08617 America/Managua +NL +5222+00454 Europe/Amsterdam +NO +5955+01045 Europe/Oslo +NP +2743+08519 Asia/Katmandu +NR -0031+16655 Pacific/Nauru +NU -1901+16955 Pacific/Niue +NZ -3652+17446 Pacific/Auckland most locations +NZ -4355-17630 Pacific/Chatham Chatham Islands +OM +2336+05835 Asia/Muscat +PA +0858-07932 America/Panama +PE -1203-07703 America/Lima +PF -1732-14934 Pacific/Tahiti Society Islands +PF -0900-13930 Pacific/Marquesas Marquesas Islands +PF -2308-13457 Pacific/Gambier Gambier Islands +PG -0930+14710 Pacific/Port_Moresby +PH +1435+12100 Asia/Manila +PK +2452+06703 Asia/Karachi +PL +5215+02100 Europe/Warsaw +PM +4703-05620 America/Miquelon +PN -2504-13005 Pacific/Pitcairn +PR +182806-0660622 America/Puerto_Rico +PS +3130+03428 Asia/Gaza +PT +3843-00908 Europe/Lisbon mainland +PT +3238-01654 Atlantic/Madeira Madeira Islands +PT +3744-02540 Atlantic/Azores Azores +PW +0720+13429 Pacific/Palau +PY -2516-05740 America/Asuncion +QA +2517+05132 Asia/Qatar +RE -2052+05528 Indian/Reunion +RO +4426+02606 Europe/Bucharest +RU +5443+02030 Europe/Kaliningrad Moscow-01 - Kaliningrad +RU +5545+03735 Europe/Moscow Moscow+00 - west Russia +RU +5312+05009 Europe/Samara Moscow+01 - Caspian Sea +RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals +RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia +RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk +RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River +RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal +RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River +RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River +RU +5934+15048 Asia/Magadan Moscow+08 - Magadan & Sakhalin +RU +5301+15839 Asia/Kamchatka Moscow+09 - Kamchatka +RU +6445+17729 Asia/Anadyr Moscow+10 - Bering Sea +RW -0157+03004 Africa/Kigali +SA +2438+04643 Asia/Riyadh +SB -0932+16012 Pacific/Guadalcanal +SC -0440+05528 Indian/Mahe +SD +1536+03232 Africa/Khartoum +SE +5920+01803 Europe/Stockholm +SG +0117+10351 Asia/Singapore +SH -1555-00542 Atlantic/St_Helena +SI +4603+01431 Europe/Ljubljana +SJ +7800+01600 Arctic/Longyearbyen Svalbard +SJ +7059-00805 Atlantic/Jan_Mayen Jan Mayen +SK +4809+01707 Europe/Bratislava +SL +0830-01315 Africa/Freetown +SM +4355+01228 Europe/San_Marino +SN +1440-01726 Africa/Dakar +SO +0204+04522 Africa/Mogadishu +SR +0550-05510 America/Paramaribo +ST +0020+00644 Africa/Sao_Tome +SV +1342-08912 America/El_Salvador +SY +3330+03618 Asia/Damascus +SZ -2618+03106 Africa/Mbabane +TC +2128-07108 America/Grand_Turk +TD +1207+01503 Africa/Ndjamena +TF -492110+0701303 Indian/Kerguelen +TG +0608+00113 Africa/Lome +TH +1345+10031 Asia/Bangkok +TJ +3835+06848 Asia/Dushanbe +TK -0922-17114 Pacific/Fakaofo +TM +3757+05823 Asia/Ashkhabad +TN +3648+01011 Africa/Tunis +TO -2110+17510 Pacific/Tongatapu +TR +4101+02858 Europe/Istanbul +TT +1039-06131 America/Port_of_Spain +TV -0831+17913 Pacific/Funafuti +TW +2503+12130 Asia/Taipei +TZ -0648+03917 Africa/Dar_es_Salaam +UA +5026+03031 Europe/Kiev most locations +UA +4457+03406 Europe/Simferopol Crimea +UG +0019+03225 Africa/Kampala +UM +1700-16830 Pacific/Johnston Johnston Atoll +UM +2813-17722 Pacific/Midway Midway Islands +UM +1917+16637 Pacific/Wake Wake Island +US +404251-0740023 America/New_York Eastern Time +US +421953-0830245 America/Detroit Eastern Time - Michigan - most locations +US +381515-0854534 America/Louisville Eastern Time - Louisville, Kentucky +US +394606-0860929 America/Indianapolis Eastern Standard Time - Indiana - most locations +US +382232-0862041 America/Indiana/Marengo Eastern Standard Time - Indiana - Crawford County +US +411745-0863730 America/Indiana/Knox Eastern Standard Time - Indiana - Starke County +US +384452-0850402 America/Indiana/Vevay Eastern Standard Time - Indiana - Switzerland County +US +415100-0873900 America/Chicago Central Time +US +450628-0873651 America/Menominee Central Time - Michigan - Wisconsin border +US +394421-1045903 America/Denver Mountain Time +US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon +US +364708-1084111 America/Shiprock Mountain Time - Navajo +US +332654-1120424 America/Phoenix Mountain Standard Time - Arizona +US +340308-1181434 America/Los_Angeles Pacific Time +US +611305-1495401 America/Anchorage Alaska Time +US +581807-1342511 America/Juneau Alaska Time - Alaska panhandle +US +593249-1394338 America/Yakutat Alaska Time - Alaska panhandle neck +US +643004-1652423 America/Nome Alaska Time - west Alaska +US +515248-1763929 America/Adak Aleutian Islands +US +211825-1575130 Pacific/Honolulu Hawaii +UY -3453-05611 America/Montevideo +UZ +4120+06918 Asia/Tashkent +VA +4154+01227 Europe/Vatican +VC +1309-06114 America/St_Vincent +VE +1030-06656 America/Caracas +VG +1827-06437 America/Tortola +VI +1821-06456 America/St_Thomas +VN +1045+10640 Asia/Saigon +VU -1740+16825 Pacific/Efate +WF -1318-17610 Pacific/Wallis +WS -1350-17144 Pacific/Apia +YE +1245+04512 Asia/Aden +YT -1247+04514 Indian/Mayotte +YU +4450+02030 Europe/Belgrade +ZA -2615+02800 Africa/Johannesburg +ZM -1525+02817 Africa/Lusaka +ZW -1750+03103 Africa/Harare diff --git a/bin/kdepim/korganizer/.xvpics/ko16.png b/bin/kdepim/korganizer/.xvpics/ko16.png new file mode 100644 index 0000000..1245dde --- a/dev/null +++ b/bin/kdepim/korganizer/.xvpics/ko16.png @@ -0,0 +1,5 @@ +P7 332 +#IMGINFO:16x16 RGB (969 bytes) +#END_OF_COMMENTS +16 16 255 +Ö·µ»¶Ö»¶Õ°ùøùô·¶Û¶¶¶¶²¶–ûµøõøÔ׺ÛÚ¶ÿÛúßÿÖûøôØÌ»¶ÛÚÛöÚÿÛúõøÕðlÛ¶ÛÚÒÑÉÒÚÕÌØð´¬I)EÛÚÒÑÒÅßÚ¤µŒ±’DI)ÛÚÖÉÖÍûÛÈÎÑ×$I(¶ÛÚÿÍÉßÿ¤ÅÀ¨×$II’ÚÛÿ¤öÛÿ¤Ä©ò߶¶·m’ÛÚÉûÑÖûÖÑÎÿ–ÖºI$·þ ŤÍûßÖöÛÚ¶»I$Iÿ©Òõ×Ûþ·±r±»ÖÛ¶¶¶ÿÛþ·‘mII²Mÿ$Û¶¶¶¶¶Û‘I%m¶¶’D)Û¶¶¶Im–Ö’¶Ú·$IH%Û¶¶¶I$I¶’Ú·¶$IIH
\ No newline at end of file diff --git a/bin/kdepim/korganizer/.xvpics/playsound.png b/bin/kdepim/korganizer/.xvpics/playsound.png new file mode 100644 index 0000000..bea63d0 --- a/dev/null +++ b/bin/kdepim/korganizer/.xvpics/playsound.png @@ -0,0 +1,5 @@ +P7 332 +#IMGINFO:16x16 RGB (1166 bytes) +#END_OF_COMMENTS +16 16 255 +I$IIÛ¶¶&HII¶Û¶¶I$IIÛ¶¶&%HIÛ¶¶ÛI$IIÛ¶¶&HIÛÚI$IIÛ¶¶&&'mIÛÛ¶¶¶I$I&mImHÛ¶¶¶I$IJ¶&IH%Û¶¶¶I$I&ÚÛ¶$II%Û¶¶¶I$IJ¶Û¶$II$I$IIÛ¶¶&HII¶Û¶¶I$IIÛ¶¶&H%IÛ¶Ú¶I$IIÛ&I$IÛ¶¶ÛI$'HI%Ú·Ú¶Û&¶Ú·$IHIÛÚ¶¶·H%HIÛ¶I¶Û¶¶$IIIÛ¶H%Ú·Ú¶$III
\ No newline at end of file diff --git a/bin/kdepim/korganizer/1downarrow.png b/bin/kdepim/korganizer/1downarrow.png Binary files differnew file mode 100644 index 0000000..5cc773c --- a/dev/null +++ b/bin/kdepim/korganizer/1downarrow.png diff --git a/bin/kdepim/korganizer/1leftarrow.png b/bin/kdepim/korganizer/1leftarrow.png Binary files differnew file mode 100644 index 0000000..e048219 --- a/dev/null +++ b/bin/kdepim/korganizer/1leftarrow.png diff --git a/bin/kdepim/korganizer/1leftarrowB.png b/bin/kdepim/korganizer/1leftarrowB.png Binary files differnew file mode 100644 index 0000000..7e3fda7 --- a/dev/null +++ b/bin/kdepim/korganizer/1leftarrowB.png diff --git a/bin/kdepim/korganizer/1rightarrow.png b/bin/kdepim/korganizer/1rightarrow.png Binary files differnew file mode 100644 index 0000000..2af0402 --- a/dev/null +++ b/bin/kdepim/korganizer/1rightarrow.png diff --git a/bin/kdepim/korganizer/1rightarrowB.png b/bin/kdepim/korganizer/1rightarrowB.png Binary files differnew file mode 100644 index 0000000..3264e13 --- a/dev/null +++ b/bin/kdepim/korganizer/1rightarrowB.png diff --git a/bin/kdepim/korganizer/1uparrow.png b/bin/kdepim/korganizer/1uparrow.png Binary files differnew file mode 100644 index 0000000..6a14bda --- a/dev/null +++ b/bin/kdepim/korganizer/1uparrow.png diff --git a/bin/kdepim/korganizer/2leftarrow.png b/bin/kdepim/korganizer/2leftarrow.png Binary files differnew file mode 100644 index 0000000..42de616 --- a/dev/null +++ b/bin/kdepim/korganizer/2leftarrow.png diff --git a/bin/kdepim/korganizer/2leftarrowB.png b/bin/kdepim/korganizer/2leftarrowB.png Binary files differnew file mode 100644 index 0000000..4506c40 --- a/dev/null +++ b/bin/kdepim/korganizer/2leftarrowB.png diff --git a/bin/kdepim/korganizer/2rightarrow.png b/bin/kdepim/korganizer/2rightarrow.png Binary files differnew file mode 100644 index 0000000..1a7fd0c --- a/dev/null +++ b/bin/kdepim/korganizer/2rightarrow.png diff --git a/bin/kdepim/korganizer/2rightarrowB.png b/bin/kdepim/korganizer/2rightarrowB.png Binary files differnew file mode 100644 index 0000000..7210438 --- a/dev/null +++ b/bin/kdepim/korganizer/2rightarrowB.png diff --git a/bin/kdepim/korganizer/alarmdaemon.png b/bin/kdepim/korganizer/alarmdaemon.png Binary files differnew file mode 100644 index 0000000..48d4810 --- a/dev/null +++ b/bin/kdepim/korganizer/alarmdaemon.png diff --git a/bin/kdepim/korganizer/bell.png b/bin/kdepim/korganizer/bell.png Binary files differnew file mode 100644 index 0000000..8d2415b --- a/dev/null +++ b/bin/kdepim/korganizer/bell.png diff --git a/bin/kdepim/korganizer/configure.png b/bin/kdepim/korganizer/configure.png Binary files differnew file mode 100644 index 0000000..d294fa9 --- a/dev/null +++ b/bin/kdepim/korganizer/configure.png diff --git a/bin/kdepim/korganizer/day.png b/bin/kdepim/korganizer/day.png Binary files differnew file mode 100644 index 0000000..c03a73e --- a/dev/null +++ b/bin/kdepim/korganizer/day.png diff --git a/bin/kdepim/korganizer/exit.png b/bin/kdepim/korganizer/exit.png Binary files differnew file mode 100644 index 0000000..3ce5300 --- a/dev/null +++ b/bin/kdepim/korganizer/exit.png diff --git a/bin/kdepim/korganizer/featuresKOPI.txt b/bin/kdepim/korganizer/featuresKOPI.txt new file mode 100644 index 0000000..4649efd --- a/dev/null +++ b/bin/kdepim/korganizer/featuresKOPI.txt @@ -0,0 +1,91 @@ +Features of KO/Pi and hints for usage of KO/Pi +(www.pi-sync.net) + +Features of KO/Pi 1.9.1: +0) +Main features: +With KO/Pi you can manage your events/todos/journals. +Todos may have subtodos. +A subtodo can be changed to a parent root todo. +KO/Pi has a monthview, a What's Next view, an event list view, a small and big todo-view and an agenda view to display 1-42 days. +KO/Pi is Qt-only based and runs on Sharp Zaurus PDA, Linux and Windows. +1) +Import - export - connection - syncing: +KO/Pi can import/export ics and vcs files. +KO/Pi can save/load ics backup files. +KO/Pi can send ics and vcs files via infrared, with and without timezone settings.( Zaurus only ) + Via the search function you can send any number/selection of events/tasks/journal via infrared. +Via the search function you can export and save any number/selection of events/tasks/journal to an ics file. +Via the search function you can export and save any number/selection of journals and descriptions of events/todos to a plain text file. +KO/Pi can import xml calendar/todo data from Opie/old Qtopia environment. +KO/Pi can sync calendar/todo data with new Sharp Rom DTM model PIM applications, found on Zaurus 7x0/860 and Sharp Rom 3.1 (and above) for 5x00 series. +(Hint: Rename /home/QtPalmtop/bin/datebook to e.g. /home/QtPalmtop/bin/datebookwech +to prevent alarm notification by the Sharp calendar app) +KO/Pi can sync calendar/todo/journal data with any local ics file. +In KO/Pi you can create a specific profile for each device to sync with. + KO/Pi can automatically down/upload a remote ics file to a temp file via user specified system command (e.g. ssh/scp, ftp, ...) to sync with. + KO/Pi can ask you, if a conflict while syncing is detected and displays a detailed view of both events/todos. + Multiple sync with many profiles at once is supported. + If KO/Pi detects that the saved file on disk has changed,(e.g. a remote sync from somewhere has happened), + it asks you, if you want to overwrite the file or if you want to sync with the file. Such that no data is lost. +KO/Pi can save/load templates for events/todos. +2) +Filter: +You can define filters for displaying/not displaying specified categories. +Quick access to the first 20 filters via hotkeys 1-0 and <crtr>1-0 +3) +Managing categories: +After importing/loading/syncing there may be new categories in events or todos which are not in the category list. + You can choose what to do with these categories: + -Add to category list + -Or remove them from events/todos +In the list view/search dialog you can quickly assign categories to all selected items. + You can choose + -to add a selection of categories to the list of categories + -to set a selection of categories as the new list of categories +You can specify a color to every categorie. + The events/tasks of this categorie are displayed with this color in the agenda view. + You can configure, if the events/tasks categorie color is shown in todo view/month view as well. +4) +Cancelling of items: +You can cancel an event/todo without deleting them. +The cancelled event/todo is then displayed stricked out. +5) +Addressbook access: +There are plugins avaialable to access Opie/old Qtopia/Sharp DTM addressbook data when adding an attendee to an event. +6) +Quick editing: +You can quickly clone, move, cancel, beam events/todos. +When dragging a recurrent event in agenda view, this recurrence is automatically added to the list of recurrence exceptions and a non-recurring clone is created. +If you click on a day number in month view, a new edit event dialog pops up. +7) +Fast navigation: +There are many shortcuts for fast changing the view. Please refer to shortcut-key description. +If you click on the week number in month view, this week is shown in agenda view. +8) +Printing: +On the desktop version, you can print out a vertical range of the agenda view "as you see it". +And you can print on the desktop version a day view, three kinds of a week view and a month view. +You can print the todo list as well. +9) +Configuration: +There are many advanced configuration possibilities. +You can configure for every item in the toolbar, whether it should be shown or not. +There are two item sizes for toolbar icons available. (Useful for 5x00 user and small display). +10) +Language: +KO/Pi is available in English and German. +11) +Alarm: +For Zaurus there is an alarm applet available with additional timer functionality. +This alarm applet will make the Zaurus wake up, if the device is in suspend mode. +You can enable in KO/Pi the internal alarm notification, such that you are informed about an alarm, if the program is running. +12) +What'sThis Help: +To use the What'sThis Help, you have to enable the What'sThis icon in the toolbar. +(Choose menu: ME-Toolbar or Action-Configure Toolbar ). +(You have to restart to reload the changed toolbar config). +Now click on the QWhat'sThis Icon +in the top right corner of KO/Pi. +Then click now after that on an item in the Agenda View or in the month view +you will get a detailed display of the items content. diff --git a/bin/kdepim/korganizer/fileexport.png b/bin/kdepim/korganizer/fileexport.png Binary files differnew file mode 100644 index 0000000..f5b348d --- a/dev/null +++ b/bin/kdepim/korganizer/fileexport.png diff --git a/bin/kdepim/korganizer/fileexport16.png b/bin/kdepim/korganizer/fileexport16.png Binary files differnew file mode 100644 index 0000000..141f560 --- a/dev/null +++ b/bin/kdepim/korganizer/fileexport16.png diff --git a/bin/kdepim/korganizer/fileimport.png b/bin/kdepim/korganizer/fileimport.png Binary files differnew file mode 100644 index 0000000..fbb9a50 --- a/dev/null +++ b/bin/kdepim/korganizer/fileimport.png diff --git a/bin/kdepim/korganizer/fileimport16.png b/bin/kdepim/korganizer/fileimport16.png Binary files differnew file mode 100644 index 0000000..8e0493e --- a/dev/null +++ b/bin/kdepim/korganizer/fileimport16.png diff --git a/bin/kdepim/korganizer/filter.png b/bin/kdepim/korganizer/filter.png Binary files differnew file mode 100644 index 0000000..13c113b --- a/dev/null +++ b/bin/kdepim/korganizer/filter.png diff --git a/bin/kdepim/korganizer/greenhook16.png b/bin/kdepim/korganizer/greenhook16.png Binary files differnew file mode 100644 index 0000000..be6b620 --- a/dev/null +++ b/bin/kdepim/korganizer/greenhook16.png diff --git a/bin/kdepim/korganizer/howtoSYNC.txt b/bin/kdepim/korganizer/howtoSYNC.txt new file mode 100644 index 0000000..e73709b --- a/dev/null +++ b/bin/kdepim/korganizer/howtoSYNC.txt @@ -0,0 +1,197 @@ +NOTE: +YOU MAY GET UNEXSPECTED (I.E. WRONG) SYNCHRONIZATION RESULTS, +IF YOU CHANGE AN EVENT ON THE FIRST DEVICE AND SYNC IMMEDIATELY FROM +THE OTHER DEVICE WITH THIS DEVICE, IF THE CLOCKS OF THE TWO DEVICES +HAVE TOO MUCH DIFFERENCE. + + +CONTENT: + +0) How syncing works +1) Qick overview of settings +2) Sync settings in sync dialog +3) Syncing background +4) Sync preferences + +************************************************************************* +0) How syncing works +************************************************************************* + +In KO/Pi you can synchronize ( sync ) your calendar +with another calendar, by syncing your (local) calendar with a +(remote) file. This remote file may on your local filesystem +or on another (remote) device. +If it is on another device, you have to specify a +command line download/upload command ( like scp, ftp, ...) to +a) download the remote file to your local machine to a temp file +b) sync with this temp file +c) upload the synced file to the remote device + +You should create for every device, to sync with, a sync profile. + +NOTE: +Before syncing, it is recommended to close +a running KO/Pi on the remote device. +(Note: KO/Pi running on Zaurus with +FastLoad enabled will never be closed!) +After syncing with a running KO/Pi on the remote device, +a "save" on the remote device will tell you that it needs to merge (sync). +After merging (just a syncing with the changed file) +you will get the new data showing in remote KO/Pi. + +************************************************************************* +1) Qick overview of settings +************************************************************************* + +a) Open sync settings dialog +b) Give your device a unique name. + (unique in the set of all devices you want to sync with). + If you have already configured another devive and created + there a sync profile to sync with this device, give your device + the same name as this sync profile! The same name is important! +c) Create a new sync profile and give it a unique name. + (unique in the set of all sync profiles on this device). + If you want to sync with a device, where KO/Pi is already installed + and which has a given unique device name, use this device name as + your profile name. +d) Coose the profile kind of your syncing method: + (i) Local file or + (ii) Remote file +c) If you did choose (i), + specify the file name you want to sync with. + If you did choose (ii), + specify the system (command line) + download/upload command of the remote file. +d) Choose the other profile options. + Detailed explanation in 2.) +e) Close sync dialog with OK. +f) Sync. + +NOTE: +AFTER SYNCING THERE ARE "SYNC EVENTS" CREATED +(OR UPDATED, IF IT ALREADY EXITS) FOR EACH SYNC PROFILE. +YOU MAY NOT DELETE OR CHANGE THESE EVENTS. + +************************************************************************* +2) Sync settings in sync dialog +************************************************************************* + +a) Local device name: + -> 1) b) +b) Profile: + -> 1) c) +c) Include in multiple sync: + In the Synchronize menu, there is a multiple sync menu entry. + If you choose this menu entry, all user defined profiles with this + 'Include in multiple sync' option enabled will be synced + one after another. And this twice. This will take some time. + After that sync, on all devices should be the same data. +d) Ask for preferences before sync: + Check this to be asked for sync settings before each sync. +e) Sync preferences: + Choose here your sync preferences. + Details -> 4) +f) Show summary after sync: + Check this to get a small summary dialog after sync + about number of added/changed/deleted events on local/remote. +g) Write back existing entries only: + Check this to update the remote calendar only. + I.e. no event/todo from yor local calendar is added to the + remote calendar. You may use this option to + sync against some kind of "public calendar" without + writing back your personal data. +h) Write back file: + Check this to update the local calendar only. + I.e. your local calendar is synced with the remote calendar + but nothing on the remote calendar is changed. +i) Profile kind: + -> 1) d) + +************************************************************************* +3) Syncing background +************************************************************************* + +Synchronizing calendars ( i.e. files ) means, +to merge two calendars in a useful way. +If the two calendars are completely different, +there is no problem, the resulting calendar contains +all data from the local and from the remote calendar. + +Problems will occur, if you have edited items +from the local calendar on the remote machine. +Then it could be, that items are in conflict. +Two items are "in conflict", if they have the +same unique ID (which get an item at time of +creation and owns it until it is deleted ) +and they both are modified after the last +synchronization. + +At first sync of two calendars there is no item deleted. +If the calendars are synced before and there is an item, +which is not edited after the last sync and is only +available in one calendar, then this item is deleted +in this calendar. + +But when was the last synchronization between two calendars? + +To know that, KO/Pi creates at first syncing +of two files an unique event "<profile name> - sync Event" +on the remote and the local calendar. +After syncing, the start time of this event is set +to the time of syncing. +The event is read only and the user may not change it. + +If two such files are synced, that both have an event +"<profile name> - sync Event" and the events have +the same start time, then deleted items on the one calendar +are deleted on the other as well. + + +************************************************************************* +4) Sync preferences +************************************************************************* + +Two items are "in conflict", if they have the same unique ID +and they both are modified after the last synchronization. +(Details -> 3) ). + +If an item is not modified after the last sync and +it is not found in the other calendar, it is deleted. + +On the first sync, there is no item deleted. + +SYNC PREFERENCES: + -Take local entry on conflict: + Takes the local entry on conflict. + If it is the first sync, + "Ask for every entry" + is chosen automatically, + if this is selected. + + -Take remote entry on conflict: + Takes the remote entry on conflict. + If it is the first sync, + "Ask for every entry" + is chosen automatically, + if this is selected. + + -Take newest entry on conflict: + This takes the newest entry on conflict. + May be the most useful syncing mode. + + -Ask for every entry on conflict: + Pops up an event viewer dialog and + shows the two conflicting entries there. + The user can chose, which entry he would like to take. + The button for the newest entry + is automatically set as default button. + The color for the newest entry is green. + + -Force: Take local entry always: + Even if the calendars are already synced + there is no item deleted on local. + + -Force: Take remote entry always: + Analogous to + "Force: Take local entry always" + diff --git a/bin/kdepim/korganizer/icons16/.xvpics/journal.png b/bin/kdepim/korganizer/icons16/.xvpics/journal.png Binary files differnew file mode 100644 index 0000000..d329e75 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/.xvpics/journal.png diff --git a/bin/kdepim/korganizer/icons16/.xvpics/newtodo.png b/bin/kdepim/korganizer/icons16/.xvpics/newtodo.png Binary files differnew file mode 100644 index 0000000..1c96a63 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/.xvpics/newtodo.png diff --git a/bin/kdepim/korganizer/icons16/.xvpics/xdays.png b/bin/kdepim/korganizer/icons16/.xvpics/xdays.png Binary files differnew file mode 100644 index 0000000..58a90fd --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/.xvpics/xdays.png diff --git a/bin/kdepim/korganizer/icons16/1leftarrowB.png b/bin/kdepim/korganizer/icons16/1leftarrowB.png Binary files differnew file mode 100644 index 0000000..7e3fda7 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/1leftarrowB.png diff --git a/bin/kdepim/korganizer/icons16/1rightarrowB.png b/bin/kdepim/korganizer/icons16/1rightarrowB.png Binary files differnew file mode 100644 index 0000000..3264e13 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/1rightarrowB.png diff --git a/bin/kdepim/korganizer/icons16/2leftarrowB.png b/bin/kdepim/korganizer/icons16/2leftarrowB.png Binary files differnew file mode 100644 index 0000000..4506c40 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/2leftarrowB.png diff --git a/bin/kdepim/korganizer/icons16/2rightarrowB.png b/bin/kdepim/korganizer/icons16/2rightarrowB.png Binary files differnew file mode 100644 index 0000000..7210438 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/2rightarrowB.png diff --git a/bin/kdepim/korganizer/icons16/bell.png b/bin/kdepim/korganizer/icons16/bell.png Binary files differnew file mode 100644 index 0000000..46ab9e3 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/bell.png diff --git a/bin/kdepim/korganizer/icons16/configure.png b/bin/kdepim/korganizer/icons16/configure.png Binary files differnew file mode 100644 index 0000000..8f258ce --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/configure.png diff --git a/bin/kdepim/korganizer/icons16/day.png b/bin/kdepim/korganizer/icons16/day.png Binary files differnew file mode 100644 index 0000000..bd16fcf --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/day.png diff --git a/bin/kdepim/korganizer/icons16/findf.png b/bin/kdepim/korganizer/icons16/findf.png Binary files differnew file mode 100644 index 0000000..5e47966 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/findf.png diff --git a/bin/kdepim/korganizer/icons16/journal.png b/bin/kdepim/korganizer/icons16/journal.png Binary files differnew file mode 100644 index 0000000..2127254 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/journal.png diff --git a/bin/kdepim/korganizer/icons16/list.png b/bin/kdepim/korganizer/icons16/list.png Binary files differnew file mode 100644 index 0000000..5598634 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/list.png diff --git a/bin/kdepim/korganizer/icons16/month.png b/bin/kdepim/korganizer/icons16/month.png Binary files differnew file mode 100644 index 0000000..d96caa1 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/month.png diff --git a/bin/kdepim/korganizer/icons16/newevent.png b/bin/kdepim/korganizer/icons16/newevent.png Binary files differnew file mode 100644 index 0000000..9a2b86a --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/newevent.png diff --git a/bin/kdepim/korganizer/icons16/newtodo.png b/bin/kdepim/korganizer/icons16/newtodo.png Binary files differnew file mode 100644 index 0000000..f357bc5 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/newtodo.png diff --git a/bin/kdepim/korganizer/icons16/picker.png b/bin/kdepim/korganizer/icons16/picker.png Binary files differnew file mode 100644 index 0000000..f086a76 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/picker.png diff --git a/bin/kdepim/korganizer/icons16/readonlyevent.png b/bin/kdepim/korganizer/icons16/readonlyevent.png Binary files differnew file mode 100644 index 0000000..0d3ddc6 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/readonlyevent.png diff --git a/bin/kdepim/korganizer/icons16/recur.png b/bin/kdepim/korganizer/icons16/recur.png Binary files differnew file mode 100644 index 0000000..6f565cc --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/recur.png diff --git a/bin/kdepim/korganizer/icons16/search.png b/bin/kdepim/korganizer/icons16/search.png Binary files differnew file mode 100644 index 0000000..6868ef5 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/search.png diff --git a/bin/kdepim/korganizer/icons16/today.png b/bin/kdepim/korganizer/icons16/today.png Binary files differnew file mode 100644 index 0000000..98c3118 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/today.png diff --git a/bin/kdepim/korganizer/icons16/todo.png b/bin/kdepim/korganizer/icons16/todo.png Binary files differnew file mode 100644 index 0000000..4e75d82 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/todo.png diff --git a/bin/kdepim/korganizer/icons16/week.png b/bin/kdepim/korganizer/icons16/week.png Binary files differnew file mode 100644 index 0000000..78c1bf4 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/week.png diff --git a/bin/kdepim/korganizer/icons16/whatsnext.png b/bin/kdepim/korganizer/icons16/whatsnext.png Binary files differnew file mode 100644 index 0000000..c37698e --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/whatsnext.png diff --git a/bin/kdepim/korganizer/icons16/workweek.png b/bin/kdepim/korganizer/icons16/workweek.png Binary files differnew file mode 100644 index 0000000..35f7779 --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/workweek.png diff --git a/bin/kdepim/korganizer/icons16/xdays.png b/bin/kdepim/korganizer/icons16/xdays.png Binary files differnew file mode 100644 index 0000000..8a1beec --- a/dev/null +++ b/bin/kdepim/korganizer/icons16/xdays.png diff --git a/bin/kdepim/korganizer/iconsmini/1leftarrowB.png b/bin/kdepim/korganizer/iconsmini/1leftarrowB.png Binary files differnew file mode 100644 index 0000000..960b40a --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/1leftarrowB.png diff --git a/bin/kdepim/korganizer/iconsmini/1rightarrowB.png b/bin/kdepim/korganizer/iconsmini/1rightarrowB.png Binary files differnew file mode 100644 index 0000000..b47678d --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/1rightarrowB.png diff --git a/bin/kdepim/korganizer/iconsmini/2leftarrowB.png b/bin/kdepim/korganizer/iconsmini/2leftarrowB.png Binary files differnew file mode 100644 index 0000000..dc66208 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/2leftarrowB.png diff --git a/bin/kdepim/korganizer/iconsmini/2rightarrowB.png b/bin/kdepim/korganizer/iconsmini/2rightarrowB.png Binary files differnew file mode 100644 index 0000000..3a312f4 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/2rightarrowB.png diff --git a/bin/kdepim/korganizer/iconsmini/bell.png b/bin/kdepim/korganizer/iconsmini/bell.png Binary files differnew file mode 100644 index 0000000..46ab9e3 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/bell.png diff --git a/bin/kdepim/korganizer/iconsmini/day.png b/bin/kdepim/korganizer/iconsmini/day.png Binary files differnew file mode 100644 index 0000000..b8d05e3 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/day.png diff --git a/bin/kdepim/korganizer/iconsmini/findf.png b/bin/kdepim/korganizer/iconsmini/findf.png Binary files differnew file mode 100644 index 0000000..5e47966 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/findf.png diff --git a/bin/kdepim/korganizer/iconsmini/journal.png b/bin/kdepim/korganizer/iconsmini/journal.png Binary files differnew file mode 100644 index 0000000..5ee7587 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/journal.png diff --git a/bin/kdepim/korganizer/iconsmini/list.png b/bin/kdepim/korganizer/iconsmini/list.png Binary files differnew file mode 100644 index 0000000..9625a95 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/list.png diff --git a/bin/kdepim/korganizer/iconsmini/month.png b/bin/kdepim/korganizer/iconsmini/month.png Binary files differnew file mode 100644 index 0000000..c0757f4 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/month.png diff --git a/bin/kdepim/korganizer/iconsmini/newevent.png b/bin/kdepim/korganizer/iconsmini/newevent.png Binary files differnew file mode 100644 index 0000000..665894c --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/newevent.png diff --git a/bin/kdepim/korganizer/iconsmini/newtodo.png b/bin/kdepim/korganizer/iconsmini/newtodo.png Binary files differnew file mode 100644 index 0000000..420ecc9 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/newtodo.png diff --git a/bin/kdepim/korganizer/iconsmini/picker.png b/bin/kdepim/korganizer/iconsmini/picker.png Binary files differnew file mode 100644 index 0000000..0daa0cd --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/picker.png diff --git a/bin/kdepim/korganizer/iconsmini/readonlyevent.png b/bin/kdepim/korganizer/iconsmini/readonlyevent.png Binary files differnew file mode 100644 index 0000000..0d3ddc6 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/readonlyevent.png diff --git a/bin/kdepim/korganizer/iconsmini/recur.png b/bin/kdepim/korganizer/iconsmini/recur.png Binary files differnew file mode 100644 index 0000000..6f565cc --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/recur.png diff --git a/bin/kdepim/korganizer/iconsmini/search.png b/bin/kdepim/korganizer/iconsmini/search.png Binary files differnew file mode 100644 index 0000000..c0254a2 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/search.png diff --git a/bin/kdepim/korganizer/iconsmini/today.png b/bin/kdepim/korganizer/iconsmini/today.png Binary files differnew file mode 100644 index 0000000..480b4c8 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/today.png diff --git a/bin/kdepim/korganizer/iconsmini/todo.png b/bin/kdepim/korganizer/iconsmini/todo.png Binary files differnew file mode 100644 index 0000000..bf7d685 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/todo.png diff --git a/bin/kdepim/korganizer/iconsmini/week.png b/bin/kdepim/korganizer/iconsmini/week.png Binary files differnew file mode 100644 index 0000000..2fb6172 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/week.png diff --git a/bin/kdepim/korganizer/iconsmini/whatsnext.png b/bin/kdepim/korganizer/iconsmini/whatsnext.png Binary files differnew file mode 100644 index 0000000..71f3b4d --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/whatsnext.png diff --git a/bin/kdepim/korganizer/iconsmini/workweek.png b/bin/kdepim/korganizer/iconsmini/workweek.png Binary files differnew file mode 100644 index 0000000..a2e13d2 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/workweek.png diff --git a/bin/kdepim/korganizer/iconsmini/xdays.png b/bin/kdepim/korganizer/iconsmini/xdays.png Binary files differnew file mode 100644 index 0000000..47bdef8 --- a/dev/null +++ b/bin/kdepim/korganizer/iconsmini/xdays.png diff --git a/bin/kdepim/korganizer/journal.png b/bin/kdepim/korganizer/journal.png Binary files differnew file mode 100644 index 0000000..bf83a61 --- a/dev/null +++ b/bin/kdepim/korganizer/journal.png diff --git a/bin/kdepim/korganizer/ko16.png b/bin/kdepim/korganizer/ko16.png Binary files differnew file mode 100644 index 0000000..378cc9c --- a/dev/null +++ b/bin/kdepim/korganizer/ko16.png diff --git a/bin/kdepim/korganizer/ko16old.png b/bin/kdepim/korganizer/ko16old.png Binary files differnew file mode 100644 index 0000000..97b12ab --- a/dev/null +++ b/bin/kdepim/korganizer/ko16old.png diff --git a/bin/kdepim/korganizer/ko24.png b/bin/kdepim/korganizer/ko24.png Binary files differnew file mode 100644 index 0000000..9759533 --- a/dev/null +++ b/bin/kdepim/korganizer/ko24.png diff --git a/bin/kdepim/korganizer/ko24old.png b/bin/kdepim/korganizer/ko24old.png Binary files differnew file mode 100644 index 0000000..76742f4 --- a/dev/null +++ b/bin/kdepim/korganizer/ko24old.png diff --git a/bin/kdepim/korganizer/koalarm.wav b/bin/kdepim/korganizer/koalarm.wav Binary files differnew file mode 100644 index 0000000..c5ff79d --- a/dev/null +++ b/bin/kdepim/korganizer/koalarm.wav diff --git a/bin/kdepim/korganizer/kopiFAQ.txt b/bin/kdepim/korganizer/kopiFAQ.txt new file mode 100644 index 0000000..885d352 --- a/dev/null +++ b/bin/kdepim/korganizer/kopiFAQ.txt @@ -0,0 +1,266 @@ +************************************************************************* +Q: +For which platform KO/Pi is available? +A: +KO/Pi is the platform-independend version of KOrganizer and it +includes a replacement for the KDE libraries called microkde. +It can be compiled to any platform, where Qt is available. +The source code compiles without modifications on Windows, +Linux Desktop and Sharp Zaurus PDA. Precompiled versions are available +on www.pi-sync.net for Windows and Sharp Zaurus PDA. +************************************************************************* +Q: +What files/data can KO/Pi import or export? +A: +KO/Pi saves its data in iCalandar format (*.ics) +You can import .ics (used by KDE KOrganizer/Mozillas/Appli iCal) or .vcs files. +You can import xml based PIMs (Opie, old Sharp and old TKC). +You can sync with the newer Sharp DTM PIMs directly. +You can sync with any local .ics file or remote with a .ics file via ssh. +************************************************************************* +Q: +How can I sync via ssh? +A: +You must have installed a ssh client on the machine KO/Pi is running. +You must have a ssh server running on the remote machine. +You must have configured your access to the server such that you can +log in from console on the server without a password. +For that reason you have to put some keys on the servers home dir. +Please read docu of ssh how to do that. +************************************************************************* +Q: +How can I get my data from Outlook? +A: +Well you can sync Outlook with Sharp-DTM Pims +and then sync KO/Pi with Sharp-DTM. +Voila - you have your Outlook data in KO/Pi. +It is planned that KO/Pi windows version syncs directly with Outlook. +************************************************************************* +Q: +I sync with Outlook via the Sharp DTM. +But, now, whenever I get an alarm I get notified by both KO/Pi +and the Sharp Calendar app. +How could I disable Sharp Calendar app? +A: +You have to rename datebook (the Sharp Calendar app) +such that it cannot be automatically started by the system alarm daemon. +If you rename it and you do not delete it, +you can do revert your changes easily. +For example, rename +/home/QtPalmtop/bin/datebook +to +/home/QtPalmtop/bin/datebookwech +Then you can sync KO/Pi with the database +and then the database with outlook without problems. +An event( with alarm ) created on outlook make KO/Pi alarm goes off, +but there will be no datebook alarm :-) +************************************************************************* +Q: +I cannot sync Outlook with Sharp-DTM. How can I get my data from Outlook? +A: +There is a tool called Outport. +With that tool you can export your Outlook data to many small .ics files. +To get one big .ics file to able to import the data quickly in KO/Pi +you can do the following on Linux: +cat *.ics > mycalendar +mv mycalendar mycalendar.ics +Now you have one file, but kopi cannot read it. +You have to remove all lines in the file +(take a texteditor where search and replace is done quickly ) which are: +BEGIN:VCALENDAR +END:VCALENDAR +Only the very first +BEGIN:VCALENDAR and the very last +END:VCALENDAR may remain in the file. +Now KO/Pi can read the modified file. +************************************************************************* +Q: +Why does not KO/Pi import several .isc files at once? +A: +Because it is not yet implemented. +************************************************************************* +Q: +Why does not KO/Pi sync directly with Outlook? +A: +Because it is not yet implemented. +But it is planned to be implemented. +************************************************************************* +Q: +Why does KO/Pi start up on restarts? +A: +Fastload causes KO/Pi to startup when Qtopia starts. +************************************************************************* +Q: +Do I have to deinstall the KO/Pi alarm applet, when I update KO/Pi? +A: +No, the KO/Pi alarm applet runs completely independend of KO/Pi. +That means, it does not need KO/Pi or libraries of KO/Pi for being +executed. But the applet itself is not very useful without KO/Pi. +It notifies KO/Pi to start via system calls. +It needs KO/Pi to get the next alarm from the system alarm daemon. +Such that the KO/Pi alarm alone may be used only as a timer application. +Files of KO/Pi are ( with /home/QtPalmtop as base dir): +bin/kopi bin/db2file apps/Pim/korganizer.desktop pics/korganizer/* lib/libmicro* +************************************************************************* +Q: +I have problems updating KO/Pi. Any hints? +A: +When deinstalling KO/Pi alarm applet, Qtopia reboots. +Please do not deinstall KO/Pi alarm applet and KO/Pi together. +It may be that because of the reboot KO/Pi itself is not deinstalled properly. +************************************************************************* +Q: +I installed the qtopiaKABC plugin, +but I can't access the addressbook when adding attendees. +A: +The qtopiaKABC plug-in is for old non DTM Qtopia Pims only. +This plug-in works with xml based addressbooks. +There is no solution currently for the DTM addressbook. +On a newer Sharp Rom (using DTM), you can install +Opie(for Sharp Rom) libs+adressbook and the opieKABC plug-in. +That works with KO/Pi. +************************************************************************* +Q: +Why do I have two pim tabs? +A: +The original tab has the 'PIM' tab and kopi is installed in the 'Pim' tab. +The difference in capitalization keeps them separate. +That is no packaging bug. +This is a feature. +The author of KO/pi has a Tab 'Pim'. +************************************************************************* +************************************************************************* +************************************************************************* + +Q: +How do I change the timezone? All my appointments do show 6 hours ahead. +A: +The default timezone in KO/Pi is CET. +CET is (GMT +01:00) or (UTC +01:00), i.e GMT=UTC . +To adjust the time of your appointments, +you have to change the timezone and reload your calendar without closing +the application and without saving the data. +"Without saving the data" is very important. +Note that KO/Pi has build in auto saving. +If auto saving is performed after changing the timezone and before +reloading your calendar no times will be changed. +Example: +Selected timezone in KO/Pi is (+01:00 Oslo). +You have an appointment shown at 8:00. But it should be at 14:00. +Your timezone is -05:00 US/Eastern. +You have to do: +Select timezone +07:00 Asia/Bangok in config dialog. +Close dialog with ok button. +Choose menu: File-Load Calendar Backup. +Choose file: (your home path)/Applications/korganizer/mycalendar.ics +(on Windows: file: (your home path)/korganizer/mycalendar.ics). +Load file. +Now your appointment is at 14:00. +Select timezone -05:00 US/Eastern in config dialog. +Close KO/Pi (file is saved when closing and changes are not yet saved). +Restart KO/Pi. +Your timezone is -05:00 US/Eastern. +Your appointment is at 14:00. +Everything is ok. +************************************************************************* +Q: +I want to send appointments via Infrared (IR) to a mobile device. +What format I have to choose? +A: +You can send data as vcs (vCalendar) or as ics (iCalendar) files. +With and without timezone settings( Local time ). +Usually small mobile devices like mobile phones do not know anything about timezones. +Choosing vcs and Local time should work with most mobile phones. +Most mobile devices should be able to recieve vcs files. +If it is a smartphone or pda, the device may be able to handle timezones. +Try vcs and with timezones. +If you send the data to a laptop it depends on the application. +If you have a windows laptop and want to get data into an +installed KO/Pi on windows, you should choose ics and with timezone. +Simply try it out, what data the device does understand. +************************************************************************* +Q: +I want to send a friend all the public holidays in my calendar. Can I do that? +A: +Yes. +Choose search dialog. +Serach there after the events you want to send. +Make sure, you get all wanted events and maybe some more. +Maybe sort the items and select all items you want to send. +With a 'right' mouse click +(hold pen down for a while and then relase) you get a popup menu. +Choose there 'Save selected to file'. +Now all selected entries are saved. +Send the file to your friend, he can import them in his calendar now. +************************************************************************* +Q: +I want to get another alarm sound than the default. What I have to change? +A: +The default alarm sound is a wav file: +It is (QPEDIR)/pics/korganizer/koalarm.wav. +(Usually QPEDIR=/home(QtPalmtop). +Just replace this file by another one und do a +'simulate alarm' to ckeck, if it works. +Wav files can have different sampling data. +(e.g. 16/8bit, stereo/mono, 22kHz/11kHz/...) +Note: It seems to be that there are problems with particular +combination of these settings. +If one file is not replayed properly, +just try another file/ another sampling data. +************************************************************************* +Q: +Is there a solution to get an alarm on Windows? +A: +No, not yet. +************************************************************************* +Q: +I have Zaurus 5600 and I want to get wav alarm instead of the buzzer. +Is that possible? +A: +Yes. +The default alarm kind is determined from the screen resolution. +For all 320x240 displays the buzzer alarm is the default. +To change this, set in the alarm applet popup menu +Play beeps- Replay-*.wav-file +Note: +If a 5500 user will choose this, +he will get no alarm sound from the speaker. +He will get only the wav sound from the headphone connector. +************************************************************************* +Q: +In the alarm applet settings "auto suspend" seems not to work. +Am I doing something wrong? +A: +Probably! +The lenght of an alarm is determined from settings in +Play beeps and the interval of each beep. +E.g. Play beeps = 10 and interval = 10 means, +the alarm has a duration of 100 secs. +The "auto suspend" can only work, if the system is +not suspended itself when playing back the alarm. +E.g. if you have set your system suspend time to 1 min (= 60 sec) +the system is suspended during playback of alarm and +there is no new "suspend alarm notification" stored in the system. +Solution: +Make sure your alarm duration is less then your +system suspend time. +************************************************************************* +Q: +I can not install the KO/Pi on the SD card (ext2 formated), +it can be installed only in the internal memory. +Is there any reason for that ? +A: +Yes. +I tried it once to make kopi installable on the sd, +but the howto I found did not work. +If anybody send me a hint how to make KO/Pi installable on SD, +I would implement it. + + + + + + + + +
\ No newline at end of file diff --git a/bin/kdepim/korganizer/kopiWhatsNew.txt b/bin/kdepim/korganizer/kopiWhatsNew.txt new file mode 100644 index 0000000..08d561a --- a/dev/null +++ b/bin/kdepim/korganizer/kopiWhatsNew.txt @@ -0,0 +1,111 @@ +Info about the changes in new versions of KO/Pi + +********** VERSION 1.9.1 ************ +1) + +++ IMPORTANT 1 +++ + +The storing place of the default calendar +file has changed! +The default calendar file was +Applications/korganizer/mycalendar.ics +on Zaurus and +(yourHomeDir)/korganizer/mycalendar.ics +on Windows/Linux desktop. Now it is +(yourHomeDir)/kdepim/korganizer/mycalendar.ics +on Zaurus, Windows and Linux. +To load the old file, choose menu +File-Load calendar backup. +(It should be loaded automatically +at startup with a warning message displayed). +The place of the configuration file has changed too. +If you want to use your old KO/Pi config, +copy it to +(yourHomeDir)/kdepim/config/korganizerrc +Please read VERSION 1.9.0 - topic 3) as well! + + +++ IMPORTANT 2 +++ + +Because of the new paths, you will need +a new version of the KO/Pi alarm applet +for Zaurus. +Use version >= 1.9.1 + +2) +Now the QWhat'sThis Icon works for items +in the month view as well. +(See VERSION 1.7.8 Topic 1) ). +3) +You can import birtsdays/anniversaries +from KA/Pi into KO/Pi. +Choose menu File-Import birthdays. +If you import twice, already imported items +will not be imported again, if they +have not been changed in KO/Pi. +4) +When syncing with sharp DTM, now a progress +is shown, when the data is written back. +If there is much data in KO/Pi and no data +in DTM, that can take a long time. +(But only for the first time ). +5) +In the search dialog, you can search +now for the name/email of an attendee +of an event/todo. +To get more space for displaying +search results, the buttons +for "search" and "close" on the +bottom are removed in the PDA version. +You have to click OK in the top right +corner to do a search. +6) +Now it is possible to disable the displaying +of todo items in the Allday part of the Agenda. +Choose Menu Action-Configure, +TAB Todo View, checkbox +"Allday Agenda view shows todos" +7) +If FastLoad is enabled, now the settings and the +calendar data are saved, when KO/Pi is closed. +(If no Fastload is enabled, KO/Pi saves +the data as well, of course) +8) +The Agenda View has a minimize-splitter now, +such that the height of the allday part can be +changed quickly. + +********** VERSION 1.9.0 ************ +1) +KO/Pi is now merged with the new microKDE from KA/Pi. +KO/Pi accesses now KA/Pi as the addressbook. +The other ddressbook-plugins are not working any longer. +(It is planned, that later KA/Pi itself uses these plugins) +New versions of KO/Pi are only available +together with KA/Pi as the KDE-Pim/Pi package. +2) +If you click on an attendee of a meeting in the +event viewer, a detailed summary of the +attendee is shown. +3) +The place of the configuration file has changed. +If you want to use your old KO/Pi config, copy +Applications/korganizer/config_korganizerrc +to +Applications/korganizer/config/korganizerrc + +********** VERSION 1.7.8 ************ +1) +Now the QWhat'sThis ist working. +Enable the QWhat'sThis icon in the toolbar. +(You have to restart to reload the changed toolbar config). +Now click on the QWhat'sThis Icon +in the top right corner of KO/Pi. +Then click on an item in the Agenda View: +You will get a detailed display of the items content. +2) +Some other very minor changes. +But I have forgotten the details ... +For that reason I start this log here: +To document my changes, when I am doing it. + +********** VERSION 1.7.7 ************ +Stable Version of KO/Pi
\ No newline at end of file diff --git a/bin/kdepim/korganizer/korganizer.png b/bin/kdepim/korganizer/korganizer.png Binary files differnew file mode 100644 index 0000000..9eef711 --- a/dev/null +++ b/bin/kdepim/korganizer/korganizer.png diff --git a/bin/kdepim/korganizer/korganizer2.png b/bin/kdepim/korganizer/korganizer2.png Binary files differnew file mode 100644 index 0000000..29bfd4d --- a/dev/null +++ b/bin/kdepim/korganizer/korganizer2.png diff --git a/bin/kdepim/korganizer/korganizer3.png b/bin/kdepim/korganizer/korganizer3.png Binary files differnew file mode 100644 index 0000000..0e9caef --- a/dev/null +++ b/bin/kdepim/korganizer/korganizer3.png diff --git a/bin/kdepim/korganizer/list.png b/bin/kdepim/korganizer/list.png Binary files differnew file mode 100644 index 0000000..1e05a1e --- a/dev/null +++ b/bin/kdepim/korganizer/list.png diff --git a/bin/kdepim/korganizer/mailappt.png b/bin/kdepim/korganizer/mailappt.png Binary files differnew file mode 100644 index 0000000..39d0cb3 --- a/dev/null +++ b/bin/kdepim/korganizer/mailappt.png diff --git a/bin/kdepim/korganizer/month.png b/bin/kdepim/korganizer/month.png Binary files differnew file mode 100644 index 0000000..d2c75a0 --- a/dev/null +++ b/bin/kdepim/korganizer/month.png diff --git a/bin/kdepim/korganizer/navi.png b/bin/kdepim/korganizer/navi.png Binary files differnew file mode 100644 index 0000000..9cb0fab --- a/dev/null +++ b/bin/kdepim/korganizer/navi.png diff --git a/bin/kdepim/korganizer/newevent.png b/bin/kdepim/korganizer/newevent.png Binary files differnew file mode 100644 index 0000000..9bae717 --- a/dev/null +++ b/bin/kdepim/korganizer/newevent.png diff --git a/bin/kdepim/korganizer/newtodo.png b/bin/kdepim/korganizer/newtodo.png Binary files differnew file mode 100644 index 0000000..41a9b4d --- a/dev/null +++ b/bin/kdepim/korganizer/newtodo.png diff --git a/bin/kdepim/korganizer/nomailappt.png b/bin/kdepim/korganizer/nomailappt.png Binary files differnew file mode 100644 index 0000000..417c519 --- a/dev/null +++ b/bin/kdepim/korganizer/nomailappt.png diff --git a/bin/kdepim/korganizer/package_toys.png b/bin/kdepim/korganizer/package_toys.png Binary files differnew file mode 100644 index 0000000..eea4fc7 --- a/dev/null +++ b/bin/kdepim/korganizer/package_toys.png diff --git a/bin/kdepim/korganizer/picker.png b/bin/kdepim/korganizer/picker.png Binary files differnew file mode 100644 index 0000000..ea7af8e --- a/dev/null +++ b/bin/kdepim/korganizer/picker.png diff --git a/bin/kdepim/korganizer/playsound.png b/bin/kdepim/korganizer/playsound.png Binary files differnew file mode 100644 index 0000000..9ec338d --- a/dev/null +++ b/bin/kdepim/korganizer/playsound.png diff --git a/bin/kdepim/korganizer/print.png b/bin/kdepim/korganizer/print.png Binary files differnew file mode 100644 index 0000000..1076668 --- a/dev/null +++ b/bin/kdepim/korganizer/print.png diff --git a/bin/kdepim/korganizer/redcross16.png b/bin/kdepim/korganizer/redcross16.png Binary files differnew file mode 100644 index 0000000..b75d06e --- a/dev/null +++ b/bin/kdepim/korganizer/redcross16.png diff --git a/bin/kdepim/korganizer/run.png b/bin/kdepim/korganizer/run.png Binary files differnew file mode 100644 index 0000000..2206448 --- a/dev/null +++ b/bin/kdepim/korganizer/run.png diff --git a/bin/kdepim/korganizer/runprog.png b/bin/kdepim/korganizer/runprog.png Binary files differnew file mode 100644 index 0000000..97af911 --- a/dev/null +++ b/bin/kdepim/korganizer/runprog.png diff --git a/bin/kdepim/korganizer/search.png b/bin/kdepim/korganizer/search.png Binary files differnew file mode 100644 index 0000000..3d5ceb2 --- a/dev/null +++ b/bin/kdepim/korganizer/search.png diff --git a/bin/kdepim/korganizer/smallcal.png b/bin/kdepim/korganizer/smallcal.png Binary files differnew file mode 100644 index 0000000..f9239d0 --- a/dev/null +++ b/bin/kdepim/korganizer/smallcal.png diff --git a/bin/kdepim/korganizer/today.png b/bin/kdepim/korganizer/today.png Binary files differnew file mode 100644 index 0000000..b15c792 --- a/dev/null +++ b/bin/kdepim/korganizer/today.png diff --git a/bin/kdepim/korganizer/todo.png b/bin/kdepim/korganizer/todo.png Binary files differnew file mode 100644 index 0000000..0906514 --- a/dev/null +++ b/bin/kdepim/korganizer/todo.png diff --git a/bin/kdepim/korganizer/todo16.png b/bin/kdepim/korganizer/todo16.png Binary files differnew file mode 100644 index 0000000..2d6a3eb --- a/dev/null +++ b/bin/kdepim/korganizer/todo16.png diff --git a/bin/kdepim/korganizer/usertranslation.txt b/bin/kdepim/korganizer/usertranslation.txt new file mode 100644 index 0000000..4c6414b --- a/dev/null +++ b/bin/kdepim/korganizer/usertranslation.txt @@ -0,0 +1,831 @@ +{ "10 minutes","10 Minuten", }, +{ "10th","10." }, +{ "11th","11." }, +{ "12 pm Format","12 AM/PM Format" }, +{ "12th","12." }, +{ "13th","13." }, +{ "14th","14." }, +{ "15th","15." }, +{ "16th","16." }, +{ "17th","17." }, +{ "18th","18." }, +{ "19th","19." }, +{ "1 Day","1 Tag" }, +{ "1 h","1 Std" }, +{ "1 (high)","1 (hoch)" }, +{ "5 (low)","5" }, +{ "1st","1." }, +{ "20th","20." }, +{ "21st","21." }, +{ "22nd","22." }, +{ "23rd","23." }, +{ "24:00 Hour Format","24:00 Stunden Format" }, +{ "24th","24." }, +{ "25th","25." }, +{ "26th","26." }, +{ "27th","27." }, +{ "28th","28." }, +{ "29th","29." }, +{ "2nd","2." }, +{ "30 minutes","30 Minuten" }, +{ "30th","30." }, +{ "31st","31." }, +{ "3rd","3." }, +{ "4th","4." }, +{ "5 (lowest)","5 (Niedrigster)" }, +{ "5th","5." }, +{ "6th","6." }, +{ "7th","7." }, +{ "8th","8." }, +{ "9th","9." }, +{ "About...","Über..." }, +{ "&Accept","&Akzeptieren" }, +{ "Accept","Akzeptieren" }, +{ "Accept A&ll","A&lles Akzepieren" }, +{ "Access:","Zugriff:" }, +{ "A corresponding event is missing in your calendar!","Ein zugehöriger Termin fehlt in ihrem Kalender!" }, +{ "Actions","Aktionen" }, +{ "Add Filter","Filter Hinzufügen" }, +{ "&Add","Hinzufügen" }, +{ "Add","Hinzufügen" }, +{ "Additional email addresses:","Zusätzliche E-Mail Adressen:" }, +{ "Additional email address:","Zusätzliche E-Mail Adresse:" }, +{ "&Addressbook","&Adressbuch" }, +{ "Address &Book...","Adress&buch..." }, +{ "Agenda Size","Agende Größe" }, +{ "Agenda Size:","Größe der Agenda:" }, +{ "Agenda view:","Agenda Ansicht:" }, +{ "Agenda view background color:","Hintergrund der Agenda Ansicht:" }, +{ "All attendees","Alle Teilnehmer" }, +{ "AllDayAgenda Height:","Höhe Ganztages Agenda:" }, +{ "Allday","Ganztägig" }, +{ "Anonymous","Anonym" }, +{ "Apply","Anwenden" }, +{ "Apr","Apr" }, +{ "April","April" }, +{"Ask for every entry on conflict","Frage bei Konflikten nach"}, +{ "Ask for preferences before syncing","Vor dem Syncronisieren nachfragen" }, +{ "Ask for quit when closing KO/Pi","Vor dem Beenden von KO/Pi nachfragen" }, +{ "Attendees","Teilnehmer" }, +{ "Aug","Aug" }, +{ "August","August" }, +{ "Auto-Save","Automatisches Abspeichern" }, +{ "Auto save delay in minutes:","Verzög.autom.Speichern in Min" }, +{ "Auto saving...","Automatische Sicherung..." }, +{ "Begin on:","Starte mit:" }, +{ "Begins on: %1","Starte mit: %1" }, +{ "<b>From:</b> %1 <b>To:</b> %2","<b>Vom:</b> %1 <b>Zum:</b> %2" }, +{ "Bigger","Größer" }, +{ "Biggest","Riesig" }, +{ "Big","Groß" }, +{ "<b>On:</b> %1","<b>Am:</b> %1" }, +{ "<b>On:</b> %1 <b>From:S</b> %2 <b>To:</b> %3","<b>Am:</b> %1 <b>Vom:S</b> %2 <b>Zum:</b> %3" }, +{ "<b>Original event:</b><p>","<b>Original Termin:</b><p>" }, +{ " - both are modified after last sync"," - beide wurden nach der letzten Syncronisation verändert" }, +{ "Busy","Belegt" }, +{ "&Cancel","Abbre&chen" }, +{ "Cancel","Abbrechen" }, +{ "Cannot delete To-Do\nwhich has children.","Kann Todo nicht löschen,\n da noch Einträge vorhanden sind" }, +{ "Cannot delete To-Do which has children.","Kann Todo nicht löschen, da noch Einträge vorhanden sind" }, +{ "Can't generate mail:\nNo event selected.","Kann e-Mail nicht erstellen:\nKein Termin ausgewählt." }, +{ "Categories...","Kategorien..." }, +{ "Categories","Kategorien" }, +{ "Category","Kategorie" }, +{ "Center View","Zentriere Ansicht" }, +{ "Change","Ändere" }, +{ "Cinema","Kino" }, +{ "Click to add a new Todo","Hier klicken, um ein neues Todo anzulegen" }, +{ "Clone Item","Klone Eintrag" }, +{ "&Close","S&chließen" }, +{ "Close","Schließen" }, +{ "Close this dialog to abort deletion!","Zum Abbrechen des Löschvorganges Dialog schließen!" }, +{ "Colors","Farben" }, +{ "completed","erledigt" }, +{ "completed on %1","erledigt am %1" }, +{ "Complete","Erledigt" }, +{ "Confidential","Vertraulich" }, +{ "Configure...","Einstellungen..." }, +{ "Confirm &deletes","Löschvogang bestätigen" }, +{ "Couldn't load calendar\n '%1'.","Kann Kalender\n '%1' nicht laden." }, +{ "Counter-event Viewer","Terminzähler Ansicht" }, +{ "Daily ending hour:","Feierabend:" }, +{ "Daily starting hour:","Anfangszeit:" }, +{ "Daily","Täglich" }, +{ "Date Format","Datums Format" }, +{ "Date Format:","Datums Format:" }, +{ "DateNavigator:(nr)","Datums Navigator" }, +{ "Dates: ","Datum: " }, +{ "Date && Time","Datum && Zeit" }, +{ "Day begins at:","Der Tag beginnt um:" }, +{ "Days in Next-X-Days:","Tage in Nächste-X-Tage:" }, +{ "Days in What's Next:","Tage in What's Next:" }, +{ "day(s)","Tag(e)" }, +{ "Days to show in Next-X-Days view:","Welche Tage in Nächste-X-Tagen anzeigen:" }, +{ "day","Tag" }, +{ "Dec","Dez" }, +{ "December","Dezember" }, +{ "Default alarm time:","Standard Alarmzeit:" }, +{ "Default appointment time:","Standard Termin Startzeit:" }, +{ "Default event color:","Standard Terminfarbe:" }, +{ "Default","Standard" }, +{ "Def. duration of new app.:","Standard Termin Länge:" }, +{ "Delete all completed To-Dos?","Alle bereits erledigten Todos löschen?" }, +{ "Delete All","Lösche alles" }, +{ "Delete all selected","Lösche alle Selektierten" }, +{ "Delete Current","Aktuellen löschen" }, +{ "Delete Event...","Lösche Termin..." }, +{ "Delete Event","Lösche Termin" }, +{ "&Delete","Löschen" }, +{ "Delete...","Löschen..." }, +{ "Delete","Löschen" }, +{ "Delete Todo...","Lösche Todo..." }, +{ "Delete To-Do","Lösche Todo" }, +{ "Deleting item %d ...","Lösche Eintrag %d..." }, +{ "Descriptions","Beschreibungen" }, +{ "Deselect All","Deselektiere Alle" }, +{ "Details","Details" }, +{ "Dinner","Abendessen" }, +{ "Do you really want\nto close KO/Pi?","Möchten Sie wirklich\nKO/PI verlassen?" }, +{ "Due Date","Fällig am" }, +{ "Due: ","Fällig: "}, +{ "Due Time","Fällig um" }, +{ "Due:","Fällig:"}, +{ "Duration: ","Dauer: " }, +{ "Edit...","Bearbeite..." }, +{ "Edit","Bearbeite" }, +{ "Edit Event...","Bearbeite Termin..." }, +{ "Edit Event","Bearbeite Termin" }, +{ "Edit exceptions","Bearbeite Ausnahmen" }, +{ "EditorBox:","Editor Fenster:" }, +{ "Edit Recurrence Range","Bearbeite Wiederholung" }, +{ "Edit Todo...","Berabeite Todo..." }, +{ "Edit To-Do","Todo bearbeiten" }, +{ "E&mail address:","E&mail Adresse:" }, +{ "(EmptyEmail)","(KeineEmail)" }, +{ "(EmptyName)","(KeinName)" }, +{ "Enable Recurrence","Wiederholender Termin" }, +{ "End after","Endet nach"}, +{ "End by:","Endet am"}, +{ "End Date","End Datum" }, +{ "End:","Ende:" }, +{ "End Time","End Zeit" }, +{ "English","Englisch" }, +{ "Event","Termin" }, +{ "Event list","Termin Liste" }, +{ "Events","Termine" }, +{ "Event Viewer:","Termin Übersicht:" }, +{ "every","jede" }, +{ "Exceptions...","Ausnahmen..." }, +{ "Exceptions","Ausnahmen" }, +{ "Exclude holidays","Ohne freie Tage" }, +{ "Exclude Saturdays","Ohne Samstage" }, +{ "Feb","Feb" }, +{ "February","Februar" }, +{ "&Find","Suche!" }, +{ "Fonts","Schriftart" }, +{ "Force take local entry always","Erzwinge:Nimm immer lokalen Eintrag" }, +{ "Force take remote entry always","Erzwinge:Nimm immer fernen Eintrag"}, +{ "Free","Frei" }, +{ "Friday","Freitag" }, +{ "Fri","Fr" }, +{ "From:","Vom:" }, +{ "Full &name:","Vor- und &Nachname:" }, +{ "General","Allgemein" }, +{ "German","Deutsch" }, +{ "Gifts","Geschenke" }, +{ "Go to Today","Heute anzeigen" }, +{ "Help","Hilfe" }, +{ "Hide Dates","Daten ausblenden" }, +{ "Highlight color:","Markierungen:" }, +{ "Holiday color:","Freie Tage:" }, +{ "hour(s)","Stunde(n)" }, +{ "In %1 days: ","In %1 Tagen: " }, +{ "Incomplete Todo:","Unerledigte Aufgaben:" }, +{ "Information","Information" }, +{ "Invalid search expression,\ncannot perform ","Kann Suche nicht ausführen" }, +{ "Jan","Jan" }, +{ "January","Januar" }, +{ "JournalView:","Journal Ansicht:" }, +{ "Journals","Journale" }, +{ "Jul","Jul" }, +{ "July","Juli" }, +{ "Jump to date","Springe zum Datum" }, +{ "June","Juni" }, +{ "Jun","Jun" }, +{ "Key Bindings...","Tastenzuordnung..." }, +{ "Kids","Kinder" }, +{ "Known Problems...","Bekannte Probleme..." }, +{ "KO/Pi Find ","KO/Pi Suchdialog " }, +{ "KO/Pi Find: ","KO/Pi Suchen: " }, +{ "KO/Pi is starting ... "," KO/Pi startet ... \n... Zeit für eine Kaffeepause ..." }, +{ "Language:(needs restart)","Sprache (Neustart!)" }, +{ "Language:","Sprache" }, +{ "Large","Etwas mehr" }, +{ "List View:","Listenansicht:" }, +{ "List View","Listenansicht" }, +{ "Load/Save","Laden/Speichern" }, +{ "Load Template","Lade Vorlage" }, +{ "Locale","Localisation" }, +{ "Local temp file:","Lokale temp. Datei:" }, +{ "Location: ","Ort: " }, +{ "Location:","Ort:" }, +{ "Mail client","Mail Programm" }, +{ "Mail Client","Mail Programm" }, +{ "March","März" }, +{ "Mar","Mär" }, +{ "May","Mai" }, +{ "M. Bains line:","M. Bains Linie:" }, +{ "Medium","Medium" }, +{ "Method","Methode" }, +{ "minute(s)","Minute(n)" }, +{ "Monday","Montag" }, +{ "Mon","Mo" }, +{ "Monthly","Monatlich" }, +{ "Month not long enough","Monat ist nicht lang genug" }, +{ "month(s)","Monat(e)" }, +{ "Month view:","Monatsansicht:" }, +{ "Month view uses category colors","Monatsansicht zeigt Kategorie Farben" }, +{ "Todo view uses category colors","To-Do Ansicht zeigt Kategorie Farben" }, +{ "Move &Down","Nach unten verschieben" }, +{ "Move &Up","Nach oben verschieben" }, +{ "Name:","Name:" }, +{ "Name","Name" }, +{ "\nAre you sure you want\nto delete this event?","\nSind Sie sicher, dass Sie\nden Termin löschen möchten?" }, +{ "%n Days","%n Tage" }, +{ "Never","Nie" }, +{ "New event...","Neuer Termin..." }, +{ "New event","Neuer Termin" }, +{ "New Event...","Neuer Termin..." }, +{ "New Events/Todos should","Neue Termine/Todos sollten" }, +{ "&New","&Neu" }, +{ "New","Neu", }, +{ "New Sub-Todo...","Neues Sub-Todo..." }, +{ "New Todo...","Neues Todo..." }, +{ "Next Alarm: ","Nächster Alarm: ", }, +{ "&Next Day","&Nächster Tag", }, +{ "Next days view uses full window","Nächste-X-Tage nutzt Vollbild" }, +{ "Next month","Nächster Monat" }, +{ "&Next Week","&Nächste Woche" }, +{ "Next year","Nächstes Jahr" }, +{ "Next Year","Nächstes Jahr" }, +{ "%n h","%n Std" }, +{ "No ending date","Kein End-Datum", }, +{ "No event, nothing to do.","Kein Termin, nichts zu tun.", }, +{ "No event selected.","Kein Termin selektiert" }, +{ "No","Nein" }, +{ "No program set","Kein Programm ausgewählt", }, +{ "Normal","Normal" }, +{ "[No selection]","Keine Selektion", }, +{ "No sound set","Kein Sound ausgewählt", }, +{ "no time ","keine Zeit ", }, +{ "no time","keine Zeit", }, +{ "No Time","Keine Zeit" }, +{ "November","November" }, +{ "Nov","Nov", }, +{ "\nThis event recurs\nover multiple dates.\n","\nDieser Termin wiederholt sich an mehreren Tagen.\n" }, +{ "occurrence(s)","Vorkommen" }, +{ "October","Oktober" }, +{ "Oct","Okt", }, +{ "O-due!","Ü-fällig! " }, +{ "&OK","&OK" }, +{ "Ok+Show!","Ok+Anzeigen" }, +{ "Organizer: %1","Organisator %1" }, +{ "Organizer","Organisator" }, +{ "Owner: ","Besitzer: " }, +{ "Owner:","Besitzer:" }, +{ "<p><b>Priority:</b> %2</p>","<p><b>Priorität:</b> %2</p>" }, +{ "Pick a date to display","Wähle einen Tag zum anzeigen aus" }, +{ "Please specify a valid due date.","Bitte gültiges Fälligkeitsdatum angeben."}, +{ "Please specify a valid end date, for example '%1'.","Bitte gültiges Enddatum angeben, z.B.'%1'." }, +{ "Please specify a valid start date.","Bitte gültiges Startdatum angeben." }, +{ "Please specify a valid start date, for example '%1'.","Bitte gültiges Startdatum angeben, z.B. '%1'." }, +{ "Please specify a valid start time.","Bitte gültige Startzeit angeben."}, +{ "Please specify a valid start time, for example '%1'.","Bitte gültige Startzeit angeben, z.B. '%1'." }, +{ "Preferences - some settings need a restart (nr)","Einstellungen - teilweise Neustart erforderlich (bn)" }, +{ "&Previous Day","Vorheriger Tag" }, +{ "Previous month","Vorheriger Monat" }, +{ "Previous Month","Vorheriger Monat" }, +{ "&Previous Week","Vorherige Woche" }, +{ "Previous year","Vorheriges Jahr" }, +{ "Previous Year","Vorheriges Jahr" }, +{ "Printing","Drucken" }, +{ "Priority:","Priorität:" }, +{ "Private","Privat" }, +{ "Proceed","Weiter" }, +{ "Public","Öffentlich" }, +{ "Purge","Entferne" }, +{ "Purge Completed","Entferne erledigte ToDos" }, +{ "Purge To-Dos","Todos bereinigen" }, +{ "read-only","schreibgeschützt" }, +{ "Recur every","Wiederh. alle" }, +{ "Recur in the month of","Wiederh. im Monat" }, +{ "Recur on the","Wiederh. am" }, +{ "Recur on this day","Wiederh. am diesen Tag" }, +{ "Recurrence Range...","Wiederholungs Zeitraum..." }, +{ "Recurrence Range","Wiederholungs Zeitraum" }, +{ "Recurrence Rule","Wiederholungs Regel" }, +{ "Recurrence","Wiederholung" }, +{ "Recurs","Wiederholung" }, +{"&Reject","Abweisen"}, +{ "Reminder:","Alarm:" }, +{ "Rem.:","Alarm:" }, +{ "Rem.","Alarm:" }, +{ "Remote file:","Remote Datei:"}, +{ "Remote IP:","Remote (ferne) IP:" }, +{ "Remote syncing (via ssh/scp) network settings ","Remote Sync (via ssh/scp) Netzwerk Einstellungen " }, +{ "Remote user:","Remote Benutzer"}, +{ "&Remove","Entfe&rnen" }, +{ "Remove","Entfernen" }, +{ "Request response","Bemerkung anfordern" }, +{ "Role:","Rolle:" }, +{ "Role","Rolle" }, +{ "Sat","Sa" }, +{ "Saturday","Samstag" }, +{ "Search for:","Suche nach:" }, +{ "Search In","Suche in" }, +{ "Search...","Suche..." }, +{ "Search","Suche" }, +{ "Select Addresses","Wähle Adressen" }, +{ "Select all","Selektiere Alle" }, +{ "Select a month","Wähle Monat" }, +{ "Select a week","Wähle Woche" }, +{ "Select a year","Wähle Jahr" }, +{ "Send directly","Sende direkt" }, +{ "&Send Messages","&Sende Nachrichten", }, +{ "Sep","Sep" }, +{ "September","September" }, +{ "Shopping","Einkaufen" }, +{ "Use short date in (WN/E) view","Kurzdatum in (WN/Termin) Ansicht" }, +{ "Show Dates","Zeige Daten" }, +{ "Show events that recur daily in date nav.","Zeige tägl.wiederh.Term.in Datums Nav." }, +{ "Show Event...","Zeige Termin..." }, +{ "Show ev. that recur weekly in date nav.","Zeige wöch.wiederh.Term.in Datums Nav." }, +{ "Show Marcus Bains line","Zeige Marcus Bains Linie" }, +{ "Show summary after syncing","Zeige Zusammenfassung nach Sync." }, +{ "Show time as:","Zeige Zeit als" }, +{ "Show Todo...","Zeige To-Do" }, +{ "Show topmost todo prios in What's N.:","Anz. höchster Prios in What's N.:"}, +{ "Show topmost todo prios in What's Next:","Anz. höchster Prios in What's Next:"}, +{ "Show vertical screen (Needs restart)","Vertikaler Bildschirm-Layout (Neustart!)" }, +{ "&Show","Zeige" }, +{ "Show...","Zeige..." }, +{ "Show","Zeige" }, +{ "Small","Klein" }, +{ "Sorry","Entschuldigung" }, +{"Sorry, the copy command failed!\nCommand was:\n","Der Kopierbefehl schlug fehl!\nBefehl war:\n"}, +{ "Start:","Start:" }, +{ "Start Date","Start Datum" }, +{ "Start date: %1","Start Datum: %1" }, +{ "Start Time","Start Zeit" }, +{ "Status:","Status:" }, +{ "Status","Status:" }, +{ "Summaries","Titel" }, +{ "Summary:","Titel:" }, +{ "Summary","Titel" }, +{ "Sunday","Sonntag" }, +{ "Sun","So" }, +{ "Sync preferences:","Sync Einstellungen" }, +{ "Sync Prefs","Sync Einstellungen" }, +{ "Syncronize","Daten abgleich" }, +{ "Take local entry on conflict","Nimm lokalen Eintrag beim Konflikt" }, +{ "Take newest entry on conflict","Nimm neuesten Eintrag beim Konflikt" }, +{ "Take remote entry on conflict","Nimm fernen Eintrag beim Konflikt" }, +{ "Template '%1' does not contain a valid Todo.","Template '%1' enthält kein gültiges To-Do" }, +{ "Template does not contain a valid Event.","Template '%1' enthält keinen gültigen Termin" }, +{ "Template...","Vorlage..." }, +{ "This day","Dieser Tag" }, +{ "This is an experimental feature. ","Dieses Feature ist experimentel" }, +{ "This item will be\npermanently deleted.","Dieser Eintrag wird\nkomplett gelöscht." }, +{ "This item will be permanently deleted.", "Dieser Eintrag wird komplett gelöscht." }, +{ "Thu","Do" }, +{ "Thursday","Donnerstag" }, +{ "Time associated","Mit Zeit" }, +{ "Time bar:","Uhrzeit Zeile:" }, +{ "Time && Date","Zeit und Datum" }, +{ "Time Format","Zeit Format" }, +{ "Time Format(nr):","Zeit Format(Neustart!)" }, +{ "Date Labels:","Datumsleiste:" }, +{ "Time: ","Zeit: " }, +{ "Timezone:","Zeitzone:" }, +{ "Tiny","Sehr klein" }, +{ "To: ","Bis: " }, +{ "To:","Bis:" }, +{ "Today: ","Heute: " }, +{ "Todo due today color:","Heute fällige To-Do's" }, +{ "To-do items:","To-Do items:" }, +{ "Todo overdue color:","Überfällige To-Do's" }, +{ "Todo","Todo" }, +{ "To-do view shows completed Todos","To-do Ansicht zeigt erledigte To-dos" }, +{ "ToDoView:","Todo Ansicht:" }, +{ "Toggle Alarm","Wechsle Alarm" }, +{ "Toggle Allday","Umschalten Ganztag" }, +{ "Tomorrow: ","Morgen: " }, +{ "Tue","Di" }, +{ "Tuesday","Dienstag" }, +{ "Two entries are in conflict, if: ","Zwei Einträge haben einen Konflikt, wenn:" }, +{ "Unable to find template '%1'.","Kann Vorlage '%1' nicht finden." }, +{ "Unknown","Unbekannt" }, +{ "Up","Hinauf" }, +{ "Use password (if not, ask when syncing)","Passwort: (sonst jedesmal anfragen)" }, +{ "User defined","Benutzerdefiniert" }, +{ "User long date:","Format langes Datum:" }, +{ "User short date:","Forma kurzes Datum:" }, +{ "View","Ansicht" }, +{ "View Fonts","Schriftarten Ansichten" }, +{ "Views","Ansichten" }, +{ "Wed","Mi" }, +{ "Wednesday","Mittwoch" }, +{ "Week %1","Woche %1" }, +{ "Weekly","Wöchentlich" }, +{ "Week starts on Sunday","Woche beginnt Sonntags" }, +{ "What's Next View:","What's Next Anz." }, +{ "What's next ?","Was kommt als nächstes?(What's Next)" }, +{ "Working Hours","Tägliche Arbeitszeit" }, +{ "Working hours color:","Arbeitszeit in der Agenda Ansicht:" }, +{ "Write back existing entries only","Nur exisitierende Einträge zurückschreiben" }, +{ "Write back synced file","Syncronisierte Datei zurückschreiben" }, +{ "Yearly","Jährlich" }, +{ "year(s)","Jahr(e)" }, +{ "Yes","Ja" }, +{ "You have %d item(s) selected.\n","Sie haben %d Einträge ausgewählt.\n" }, +{ "You have to restart KOrganizer for this setting to take effect.","Sie müssem Korganizer neu starten, damit diese Einstellung aktiviert wird." }, +{ "week(s) on:","Woche(n) am: " }, +{ "Full menu bar(nr)","Volle Menuleiste(bn)" }, +{ "Timezone has daylight saving","Zeitzone hat Sommerzeit" }, +{ "Actual start/end is the\nsunday before this date.","Tatsächlicher Beginn/Ende ist der Sonntag\nvor diesem Datum!" }, +{ "The year in the date is ignored.","Das Jahr vom Datum wird ignoriert." }, +{ "Daylight start:","Sommerzeit Beginn:" }, +{ "Daylight end:","Sommerzeit Ende:" }, +{ "Time Zone","Zeitzone" }, +{ "Monday 19 April 2004: %A %d %B %Y","Montag 19 April 2004: %A %d %B %Y" }, +{ "%A: Monday --- %a: Mon","%A: Montag --- %a: Mon" }, +{ "minutely","minütlich" }, +{ "hourly","stündlich" }, +{ "daily","täglich" }, +{ "weekly","wöchentlich" }, +{ "monthly","monatlich" }, +{ "day-monthly","tag-monatlich" }, +{ "month-yearly","monat-jährlich" }, +{ "day-yearly","tag-jährlich" }, +{ "position-yearly","pos-jährlich" }, +{ "Edit item on doubleclick (if not, show)","Editiere mit Doppelklick(wenn nicht, zeige)" }, +{ "Highlight current day in agenda","Hebe >>heute<< in Agenda hervor" }, +{ "Use light color for highlight current day","Helle Farbe für >>heute<< Hervorhebung" }, +{ "Highlight selection in Time Edit","Hebe Auswahl in Zeit Edit hervor" }, +{ "Hold fullscreen on view change","Behalte Vollbild bei Ansichswechsel" }, +{ "Hold non-fullscreen on view change","Behalte Nicht-Vollbild bei Ansichtsw." }, +{ "Event list view uses full window","Listenansicht nutzt Vollbild" }, +{ "Set agenda to DayBeginsAt on change","Setze Agenda auf TagBeginntUm bei Wechsel" }, +{ "Set agenda to current time on change","Setze Agenda auf gegenw.Zeit bei Wechsel" }, +{ "Listview uses monthly timespan","Listenansicht zeigt monatliche Zeitspanne" }, +{ "ViewChange","Ansichtswechsel" }, +{ "Default alarm *.wav file:","Standard Alarm *.wav Datei:" }, +{ "This setting is useless for 5500 user!","Diese Einst. ist nutzlos für 5500 Nutzer" }, +{ "File","Datei" }, +{ "Clone...","Dupliziere.." }, +{ "Move...","Bewege..." }, +{ "Beam...","Sende via IR..." }, +{ "&Clone...","Dupliziere.." }, +{ "&Move...","Bewege..." }, +{ "&Beam...","Sende via IR..." }, +{ "Show Completed","Zeige erledigte Todos" }, +{ "Show Quick Todo","Zeige Quick Todo" }, +{ "Unparent Todo","Un-sub Todo" }, +{ "Save selected to file...","Speichere Selektierte..." }, +{ "Add Categ. to selected...","Füge zu Selekt. Kateg. hinzu..." }, +{ "Set Categ. for selected...","Setze Kateg. für Selekt." }, +{ "Beam selected via IR","Sende Selekt. via IR..." }, +{ "Search","Suchen" }, +{ "Date Picker","Datum auswählen" }, +{ "Day View","Tagesansicht" }, +{ "Work Week","Arbeitswoche" }, +{ "Week","Wochenansicht" }, +{ "Month","Monatsansicht" }, +{ "Todo View","Todo Liste" }, +{ "Journal","Journal Ansicht" }, +{ "Next days","Nächste Tage" }, +{ "Print agenda selection...","Drucke Agendaselektion..." }, +{ "Toggle DateNavigator","Navigator umschalten" }, +{ "Toggle FilterView","Filteransicht umschalten" }, +{ "Prev. month","Vorheriger Monat" }, +{ "Go backward","Gehe zurück" }, +{ "Go forward","Gehe weiter" }, +{ "Synchronize","Synchronisieren" }, +{ "AgendaSize","Agendagröße" }, +{ "Import (*.ics/*.vcs) file","Importiere (*.ics/*.vcs) Datei" }, +{ "Import last file","Importiere letzte Datei" }, +{ "Import Opie/Qtopia Cal.","Importiere Opie/Qtopia Kal." }, +{ "Load Calendar Backup","Lade Kalender Backup" }, +{ "Save Calendar Backup","Speichere Kalender Backup" }, +{ "Export VCalendar","Exportiere VCalendar" }, +{ "Manage new categories...","Verwalte neue Kategorien..." }, +{ "Beam complete calendar...","Sende kompletten Kalender via IR" }, +{ "Beam filtered calendar...","Sende gefilterten Kalender via IR" }, +{ "Remote via ssh","Über Netzwerk via ssh" }, +{ "With local file","Mit lokaler Datei" }, +{ "With last file","Mit letzter Datei" }, +{ "KO/Pi: Ready for beaming","KO/Pi: Bereit zum Senden" }, +{ "KO/Pi:Beaming done","KO/Pi: Senden erfolgt" }, +{ "Save filename","Speichern: Dateinamen wählen" }, +{ "File already exists!\nOld file from:\n%1\nOverwrite?\n","Dateiname existiert bereits!\nAlte Datei vom:\n%1\nÜberschreiben?\n" }, +{ "KO/Pi: Warning!","KO/Pi: Warnung!" }, +{ "Overwrite!","Überschreibe!" }, +{ "KO/Pi:Saved %1","KO/Pi:Gespeichert %1" }, +{ "All selected items will be\npermanently deleted.\n(Deleting items will take\nsome time on a PDA)\n","Alle selektierten Einträge werden\nunwiederbringlich gelöscht.\n(Löschen kann auf dem\nPDA einige Zeit dauern)\n" }, +{ "KO/Pi Confirmation","KO/Pi Bestätigung" }, +{ "Close dialog to abort deletion!","Schließe Dialog um das Löschen abzubrechen!" }, +{ "Deleting item %d ...","Lösche Eintrag %d ..." }, +{ "%d items remaining in list.","%d Einträge sind in der Liste verblieben." }, +{ "Size","Größe" }, +{ "Date","Datum" }, +{ "Mime Type","Datei Typ" }, +{ "All Files","Alle Dateien" }, +{ "Files","Dateien" }, +{ "Documents","DoKumente" }, +{ "Select Categories","Selektiere Kategorien" }, +{ " &Deselect All "," Auswahl aufheben " }, +{ "A&dd","Hinzu" }, +{ "&Modify","Ändern" }, +{ "Edit Categories","Editiere Kategorien" }, +{ " &Edit Categories "," &Editiere Kategorien " }, +{ "Beam Options","Beam Einstellungen" }, +{ " With timezone "," Mit Zeitzone " }, +{ " Local time ", " Lokale Zeit " }, +{ "Manage new Categories","Verwalte neue Kategorien" }, +{ "Add to category list","Füge zur Kategorieliste hinzu" }, +{ "Remove from Events/Todos","Entferne von Terminen/Todos" }, +{ "After importing/loading/syncing\nthere may be new categories in\nevents or todos\nwhich are not in the category list.\nPlease choose what to do:\n ","Nach dem Importieren/Laden/Syncen\nkann es neue Kategorien in den \nTerminen oder Todos geben, die nicht\nin der Kategorieliste enthalten sind.\nBitte wählen Sie, was passieren soll:\n " }, +{ "New categories not in list:","Kategorien, die nicht in der Liste sind:" }, +{ "File format","Datei Format" }, +{ "Time format","Zeit Format" }, +{ "Delete all\ncompleted To-Dos?","Lösche alle\nerledigten To-Dos?" }, +{ "KO/Pi:Saving Data to File ...","KO/Pi: Speichere Kalender in Datei ..." }, +{ "KO/Pi:File Saved. Needed %d sec, %d ms","KO/Pi: Abgespeichert in %d sec, %d ms" }, +{ "h","Std" }, +{ "min","Min" }, +{ "hou","Std" }, +{ "day","Tag" }, +{ "French(nyi)","Französich (noch nicht implementiert)" }, +{ "Time","Zeit" }, +{ "Event Viewer","Termin Ansicht" }, +{ "Cancel Sync","Sync Abbrechen" }, +{ "Remote","Fern" }, +{ "Local","Lokal" }, +{ "Conflict! Please choose entry","Konflikt! Bitte Eintrag wählen" }, +{ "Local: ","Lokal: " }, +{ "Remote: ","Fern: " }, +{ "Last modified: ","Zuletzt geändert: " }, +{ "Location: ","Ort: " }, +{ "<p><b>From:</b> %1 </p><p><b>To:</b> %2</p>","<p><b>Von:</b> %1 </p><p><b>Bis:</b> %2</p>" }, +{ "<p><b>On:</b> %1</p>","<p><b>Am:</b> %1</p>" }, +{ "<p><b>From:</b> %1</p> ","<p><b>Von:</b> %1</p> " }, +{ "<p><b>To:</b> %1</p>","<p><b>Bis:</b> %1</p>" }, +{ "<p><b>On:</b> %1</p> ","<p><b>Am:</b> %1</p> " }, +{ "<p><b>From:</b> %1 <b>To:</b> %2</p>","<p><b>Von:</b> %1 <b>Bis:</b> %2</p>" }, +{ "This is a %1 recurring event.","Das ist ein %1 wiederholender Termin." }, +{ "<b>Next recurrence is on:</b>","<b>Nächste Wiederholung ist am:</b>" }, +{ "<b>Last recurrence was on:</b>","<b>Letzte Wiederholung war am:</b>" }, +{ "( %1 min before )","( %1 min vorher )" }, +{ "<b>Alarm on: ","<b>Alarm am: " }, +{ "<b>Details: </b>","<b>Details: </b>" }, +{ "<p><b>Priority:</b> %2</p>","<p><b>Priorität:</b> %2</p>" }, +{ "<p><i>%1 % completed</i></p>","<p><i>%1 % erledigt</i></p>" }, +{ "Organizer","Organisator" }, +{ "Save","Speichern" }, +{ "Exit (+save)","Beenden (+ speichern)" }, +{ "Home","Zuhause" }, +{ "Office","Büro" }, +{ "Libary","Bücherei" }, +{ "Doctor","Arzt" }, +{ "Beach","Strand" }, +{ "Conference room","Konferenzraum" }, +{ "Drive Home","Heimfahrt" }, +{ "Watch TV","Tv gucken" }, +{ "Phone call","Telefonanruf" }, +{ "Pay bill","Rechnung bezahlen" }, +{ "Read book","Buch lesen" }, +{ "Watering plants","Pflanzen giessen" }, +{"Appointment","Verabredung" }, +{"Birthday","Geburtstag" }, +{"Business","Geschäft" }, +{"Business Travel","Geschäftsreise" }, +{"Cinema","Kino" }, +{"Customer","Kunde" }, +{"Break","Pause" }, +{"Breakfast","Frühstück" }, +{"Competition","Wettkampf" }, +{"Dinner","Abendessen" }, +{"Education","Erziehung" }, +{"Family","Familie" }, +{"Favorites","Favoriten" }, +{"Festival","Festival" }, +{"Fishing","Angeln" }, +{"Flight","Flug" }, +{"Gifts","Geschenk" }, +{"Holiday","Feiertag" }, +{"Holiday Cards","Ansichtskarten" }, +{"Hot Contacts","Heisse Kontakte" }, +{"Hiking","Wandern" }, +{"Hunting","Jagen" }, +{"Key Customer","Wichtiger Kunde" }, +{"Kids","Kinder" }, +{"Lunch","Mittagessen" }, +{"Meeting","Treffen" }, +{"Miscellaneous","Verschiedenes" }, +{"Partner","Partner" }, +{"Party","Partie" }, +{"Personal","Privat" }, +{"Personal Travel","Privatreise"}, +{"PHB","PHB" }, +{"Phone Calls","Telefonanruf" }, +{"Projects","Projekt" }, +{"Recurring","Wiederholend" }, +{"School","Schule" }, +{"Shopping","Einkaufen" }, +{"Speach","Rede" }, +{"Special Occasion","Spez.Gelegenheit" }, +{"Sports","Sport" }, +{"Talk","Vortrag" }, +{"Travel","Reise" }, +{"TV","TV" }, +{"Germany","Deutschland" }, +{"Sweden","Schweden" }, +{"Forest","Wald" }, +{ "Desert","Wüste" }, +{ "Kitchen","Küche" }, +{ "Lake","See" }, +{"University","Universität"}, +{"Vacation","Urlaub" }, +{"VIP","VIP" }, +{ "Import Sharp Calendar","Importiere Sharp Kalender" }, +{ "This todo has been cancelled!","Dieses Todo wurde gecancelt!" }, +{ "This event has been cancelled!","Dieser Termin wurde gecancelt!" }, +{ "Cancelled","Gecancelt" }, +{ "Multiple sync","Mehrfach Sync" }, +{ "Local file","Lokale Datei" }, +{ "Last file","Letzte Datei" }, +{ "Keys + Colors...","Tasten + Farben..." }, +{ "Mini icons in toolbar(nr)","Mini Icons in ToolBar(bn)" }, +{ "Quick save(w/o Unicode)","Schnelles Speichern (o Unicode)" }, +{ "Choose...","Wähle..." }, +{ "Use colors for application:","Setze Farben für Programm:" }, +{ "Buttons, menus, etc.:","Knöpfe, Menu, etc.:" }, +{ "Frames, labels, etc.:","Rahmen, Label, etc.:" }, +{ "Show parent To-Do's in What's Next view","Zeige Ober-Todo in What's Next Anz." }, +{ "Show location in What's Next view","Zeige Ort in What's Next Anz." }, +{ "Show events that recur ","Zeige Termine, die sich wiederholen:" }, +{ "Show in every cell ","Zeige in jeder Zelle " }, +{ "short month","kurzen Monat" }, +{ "icons","Icons" }, +{ "Show Sat/Sun together","Zeige Sam/Son zusammen" }, +{ "Categorie colors are applied to text","Kategorie Farben färben Text" }, +{ "Month view uses day colors","Monatsansicht zeigt Tagesfarben" }, +{ "Day color odd months","Tagesfarbe ungerade Monate" }, +{ "Day color even months","Tagesfarbe gerade Monate" }, +{ "Color for Sundays + category \"Holiday\"","Farbe für Sonntag + Kateg.\" Feiertag\"" }, +{ "To-do view shows complete as 'xx %'","Zeige Prozent erledigt als 'xx %'" }, +{ "Small To-do view uses smaller font","Kleine To-do Ansicht nutzt kleineren Font" }, +{ "Colors are applied to text","Farben werden auf Text angewendet" }, +{ "Use internal alarm notification","Nutze interne Alarm Benachrichtigung" }, +{ "Note: KO/Pi must be running to notify you about an alarm. Recommended for use on Zaurus: Disable this option and install KO/Pi alarm applet.\n","Achtung: KO/Pi muß ausgeführt werden damit die Benachrichtigung funktioniert. Empfehlung für Zaurus: Diese Option nicht wählen und KO/Pi Alarm Applet installieren.\n" }, +{ "Play beeps count:","Anzahl der Alarmpiepse: " }, +{ "Beeps interval in sec:","Zeitintervall der Alarmpiepse: " }, +{ "Default suspend time in min:","Standard Supendierungs Zeit: " }, +{ "Auto suspend count:","Anzahl der auto Suspendierungen" }, +{ "Alarm *.wav file for newly created alarm:","Alarm *.wav Datei für neu angelegte Alarme:" }, +{ "New profile","Neues Profil" }, +{ "Clone profile","Klone Profil" }, +{ "Delete profile","Lösche Profil" }, +{ "Profile:","Profil:" }, +{ "Include in multiple sync","Beziehe Profil in mehrfach Sync mit ein" }, +{ "Force: Take local entry always","Erzwinge: Nimm immer lokalen Eintrag" }, +{ "Force: Take remote entry always","Erzwinge: Nimm immer fernen Eintrag" }, +{ "Show summary after sync","Zeige Zusammenfassung nach dem Synchronisieren" }, +{ "Write back file","Schreibe Datei zurück" }, +{ "Remote file (w down/upload command)","Entfernte Datei (via down/upload Kommando)" }, +{ "Pre sync (download) command:","Bevor Sync (download) Kommando:" }, +{ "Local device name:","Name dieses Gerätes:" }, +{ "Ask for preferences before sync","Frage nach Synchronisationseinstellungen vor dem Syncen" }, +{ "Sync preferences","Synchronisations Einstellungen" }, +{ "Profile kind","Profil Art" }, +{ "Local file","Lokale Datei" }, +{ "Local file:","Lokale Datei:" }, +{ "Post sync (upload) command:","Nach Sync (upload) Kommando:" }, +{ "Fill in default values for:","Setze Beispiel Werte ein für:" }, +{ "Hint: Use $PWD$ for placeholder of password!","Hinweis: Benutze $PWD$ als Platzhalter für ein Passwort!" }, +{ "Synchronization Preferences","Einstellungen der Synchronisationsprofile"}, +{ "Device","Gerät:" }, +{ "Sync with file \n...%1\nfrom:\n%2\n","Sync mit Datei \n...%1\nvom:\n%2\n" }, +{ "Synchronization summary:\n\n %d items added to local\n %d items added to remote\n %d items updated on local\n %d items updated on remote\n %d items deleted on local\n %d items deleted on remote\n","Synchronisationsübersicht:\n\n %d items lokal hinzugefügt\n %d items entfernt hinzugefügt\n %d items lokal geändert\n %d items entfernt geändert\n %d items lokal gelöscht\n %d items entfernt gelöscht\n" }, +{ "Synchronization successful","Synchronisation erfolgreich" }, +{ "Sync cancelled or failed. Nothing synced.","Sync abgebrochen oder fehlgeschlagen. Nichts wurde gesynced." }, +{ "Sync file \n...%1\ndoes not exist!\nNothing synced!\n","Sync Datei \n...%1\nexistiert nicht!\nNichts wurde gesynced!\n" }, +{ "Sync filename(*.ics/*.vcs)","Sync Dateiname(*.ics/*.vcs)" }, +{ "Enter password","Passwort eingeben" }, +{ "Do you really want\nto remote sync\nwith profile \n","Wollen Sie wirklich\nmit dem entfernten\nProfil syncen: \n" }, +{ "Copy remote file to local machine...","Kopiere entfernte Datei auf lokalen Rechner..." }, +{ "Sorry, the copy command failed!\nCommand was:\n%1\n \nTry command on console to get more\ndetailed info about the reason.\n","Sorry, das Kopierkommando schlug fehl!\nKommando war:\n%1\n \nVersuche Kommando von Kosole um\nDetails für das Fehlschlagen\nzu erfahren.\n" }, +{ "Writing back file result: ","Resultat des Dateizurückschreibens: " }, +{ "Syncronization sucessfully completed","Synchronisation erfolgreich abgeschlossen" }, +{ "Edit Calendar Filters","Editiere Kalendar Filter" }, +{ "Enter filter name:","Neuer Filter Name:" }, +{ "Add Filter","Filter hinzufügen" }, +{ "Question","Frage" }, +{ "Filter position: ","Filter Position: " }, +{ "Month View","Monatsansicht" }, +{ "This profil cannot be deleted!\n","Dieses Profil kann\nnicht gelöscht werden!" }, +{ "KO/Pi config error","KO/Pi Konfig. Fehler" }, +{ "Local device name undefined!\nPlease define device name!","Name dieses Gerätes undefiniert!\nBitte Namen angeben!" }, +{ "Multiple profiles with same name!\nPlease use unique profile names!","Mehrere Profile haben denselben Namen!\nBitte unterschiedliche Namen wählen!" }, +{ "Access: ","Zugriff: " }, +{ "Needs Action","Aktion notwendig" }, +{ "Accepted","Akzeptiert" }, +{ "Declined","Abgelehnt" }, +{ "Tentative","Vorläufig" }, +{ "Delegated","Beauftragt" }, +{ "Completed","Vollständig" }, +{ "In Process","In Bearbeitung" }, +{ "Participant","Teilnehmer" }, +{ "Optional Participant","Möglicher Teilnehmer" }, +{ "Observer","Beobachter" }, +{ "Chair","Vorsitzender" }, +{ "Not supported \non desktop!\n","" }, +{ "Nothing selected!\n\nThis prints the full width of the Agenda view as you see it!\n\nTo determine the vertical range of the printing, please select\na vertical range (with the left mouse button down) in one column. ","Es ist nichts selektiert!\nDieses druckt die volle Breite der Agenda View, so wie man sie sieht.\nUm die verticale Auswahl zum Drucken zu bestimmen,\nbitte einen verticalen Zeitraum (mit gedrückter linker Maustaste)\nin einer Spalte auswählen. " }, +{ "Date range: ","Datums Zeitspanne: " }, +{ "Not supported \non PDA!\n","Nicht verfügbar\nauf dem PDA. " }, +{ "Syncing - close to abort!","Syncing-schließe um abzubrechen." }, +{ "Add / remove events","Add./entferne Termine" }, +{ "File does not exist:\n '%1'.","Datei existiert nicht:\n '%1'." }, +{ "Couldn't load calendar\n '%1'.","Kann Kalender nicht laden:\n '%1'." }, +{ "\nThe file on disk has changed!\nFile size: %1 bytes.\nLast modified: %2\nDo you want to:\n\n - Save and overwrite file?\n - Sync with file, then save?\n - Cancel without saving? \n","\nDie gepeicherte Datei wurde verändert!\nDatei Grösse: %1 Bytes.\nZuletzt geändert: %2\nMöchten Sie:\n\n - Speichern und die Datei überschreiben?\n - Mit Datei Synchronisieren, dann speichern?\n - Abbrechen ohne zu speichern? \n" }, +{ "Overwrite","Überschreiben" }, +{ "Sync+save","Syncen+speichern" }, +{ "Default","Standard" }, +{ " Categories added to list! "," Kategorien zur Liste hinzugefügt! " }, +{ " %d items?"," %d Einträge?" }, +{ "\nThis event recurs\nover multiple dates.\nAre you sure you want\nto delete this event\nand all its recurrences?","\nDieses ist ein\nwiederholender Termin!.\nSind Sie sicher, dass Sie\ndiesen Termin und alle\nWiederholungen löschen möchten?" }, +{ " ?\n\nDelete:\n"," ?\n\nLösche:\n" }, +{ "Current","Aktuelle" }, +{ "\nThis event recurs\nover multiple dates.\nDo you want to delete\nall it's recurrences,\nor only the current one on:\n","\nDieses ist ein\nwiederholender Termin!\nMöchten sie alle Wiederholungen\nlöschen, oder nur die aktuelle am:\n" }, +{ "All","Alle" }, +{ "Data Loss Warning","Datenverlust Warnung" }, +{ "Proceed","Weitermachen" }, +{ "The journal entries can not be\nexported to a vCalendar file.","Die Journal Einträge können\nnicht in eine vCalendar\nDatei exportiert werden!" }, +{ "Filter disabled ","Filter abgeschaltet" }, +{ "Filter selected: ","Gewählter Filter: " }, +{ "Toggle Cancel","Gecancelt ändern" }, +{ "&Toggle Cancel","Gecancel&t ändern" }, +{ "Configure Toolbar","Konfiguriere Toolbar" }, +{ "Stretched TB","Gedehnte TB" }, +{ "Import file \n...%1\ndoes not exist!\nNothing imported!\n","Import Datei \n...%1\nexistiert nicht!\nNichts importiert!\n" }, +{ "Import filename(*.ics/*.vcs)","Import Dateiname(*.ics/*.vcs)" }, +{ "When importing a calendar twice\nduplicated events will be ignored!\nYou can create a backup file with\nFile - Save Calendar Backup\nto revert importing","Wenn ein Kalender doppelt importiert\nwird, werden doppelte Einträge ignoriert!\nSie können eine Backup Datei anlegen unter\nDatei - Speichere Kalender Backup\num den Import rückgängig machen zu können.\n" }, +{ "Not supported \non desktop!\n","Nur verfügbar auf PDA!" }, +{ "Imported file successfully","Datei erfolgreich importiert" }, +{ "Error importing file","Fehler beim Importieren der Datei" }, +{ "Export vcal filename(*.vcs)","Export vcal Dateiname(*.vcs)" }, +{ "Save file\nalready exists!\nOld save file from:\n%1\nOverwrite?\n","Zu speichernde Datei\existiert bereits!\nExist. Datei vom:\n%1\nÜberschreiben?\n" }, +{ "Overwrite!","Überschreiben!" }, +{ "Import file \n...%1\nfrom:\n%2\nDuplicated entries\nwill not be imported!\n","Import Datei \n...%1\nvom:\n%2\nDuplizierte Einträge\nwerden nicht importiert!\n" }, +{ "Load backup filename","Lade Backup Dateiname" }, +{ "Backup file\ndoes not exist!\nNothing loaded!","Backup Datei\nexistiert nicht!\nNichts geladen!" }, +{ "KO/Pi:Loaded %1","KO/Pi:Geladen %1" }, +{ "Save backup filename","Speichere Backup Dateiname" }, +{ "Backup file\nalready exists!\nOld backup file from:\n%1\nOverwrite?\n","Backup Datei\nexistiert bereits!\nAlte Backup Datei vom:\n%1\nÜberschreiben?\n" }, +{ "KO/Pi:Saved %1","KO/Pi:Gespeichert %1" }, +{ "Details of attendee","Teilnehmerdetails" }, +{ "Work phone:\n","Telefon Arbeit:\n" }, +{ "Work mobile phone:\n","Mobiltelefon Arbeit:\n" }, +{ "Home phone:\n","Telefon privat:\n" }, +{ "Mobile home phone:\n","Mobiltelefon privat:\n" }, +{ "Email:\n","Email:\n" }, +{ "Alarm disabled","Alarm deaktiviert" }, +{ "Audio.Al.: ","Audio Al.: " }, +{ "Proc.Al.: ","Proc.Al.: " }, +{ "No sound set","Kein Sound definiert" }, +{ "*.wav|Wav Files","*.wav|Wav Dateien" }, +{ "No program set","Kein Programm definiert" }, +{ "Running '%1'","Ausführen '%1'" }, +{ "Playing '%1'","Abspielen '%1'" }, +{ "Show Sync Events in WN/Agenda view","Zeige Sync Events in WN/Agenda Ansicht" }, +{ "User defined (usertranslation.txt)","Benutzerdefiniert (usertranslation.txt)" }, +{ "Load!","Laden!" }, +{ "Backup file from:\n%1\nLoading backup\nfile will delete\nyour current Data!\n","Backup Datei vom:\n%1\nDas Laden der Backup Datei\nlöscht die aktuellen Daten!\n" }, +{ "KO/Pi Features and hints","KO/Pi Eigenschaften und Tipps" }, +{ "KO/Pi User translation HowTo","KO/Pi Benutzer-Übersetzung HowTo" }, +{ "KO/Pi Synchronization HowTo","KO/Pi Synchronisation HowTo" }, +{ "Features + hints...","Eigenschaften + Tipps..." }, +{ "User translation...","Benutzer Übersetzung..." }, +{ "Sync HowTo...","Synchronisation HowTo..." }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, + diff --git a/bin/kdepim/korganizer/usertranslationHOWTO.txt b/bin/kdepim/korganizer/usertranslationHOWTO.txt new file mode 100644 index 0000000..6547697 --- a/dev/null +++ b/bin/kdepim/korganizer/usertranslationHOWTO.txt @@ -0,0 +1,63 @@ +Now it is possible, that you as a user can make a translation +and see the result immediately in KO/Pi. + +Choose menu Actions-Configure. There the TAB Locale. +Choose "User defined" as language and restart. +Now all the text is translated using the file usertranslation.txt. +This file is located on Zaurus in +/home/QtPalmtop/pics/korganizer/usertranslation.txt. +On Windows, it is in +C:\kopi\kdepim\usertranslation.txt +This file includes as a default the complete German translation of KO/Pi. +I.e. if you start KO/Pi for the first time with option +"User defined", you will get the German Version. +Just replace the German words in the file usertranslation.txt +by words of your own language. +You can check the results immedialtely by starting KO/Pi. +You can do the translation on Windows +with the Windows KO/Pi Version to test. +Or on the zaurus, if you have some spare time somewhere ... + +Howto translate: + +An entry is of the kind +{ "&Addressbook","&Adressbuch" }, +i.e. +{ "englishtext","translatettext" }, +Note, that the separation mark between the two texts MUST be "," , +not " ," or ", " or " , " or something other! + +The & in &Addressbook stands for an 'a' as keyboard shortcut. +Please place the & in front of the same char in your translation or leave it out. + +Note, that the text should fit on the small display of an 5500. +The given english text and german translation does fit. + +In messageboxes, there is sometimes long text used. +Do make text using a new line, you have to use '\n'. +Example: +{ "Backup file\nalready exists!\nOld backup file from:\n%1\nOverwrite?\n","Backup Datei\nexistiert bereits!\nAlte Backup Datei vom:\n%1\nÜberschreiben?\n" }, + +You can set the '\n' in the text where you want, +but you have to make shure, that the text does +fit on the small display of an 5500. + +Sometimes translation texts have a parameter or two, +where some text is inserted at runtime. +These parameters are %1, %2 and so on. +In the example above we have the parameter %1, +which stands for the file name. +You can place this parameter in the pext where you want. +But don't forget to use it. +And be aware, that the parameter text has some length +and the parameter text should fit on the small display of an 5500. +Sometimes only a number is filled in for a parameter. +In this case, the length of the parameter is not a big problem. + +To use a " itself as a char in the translated text, you have to put a \ in front of it, like in the example: +{ "Color for Sundays + category \"Holiday\"","Farbe für Sonntag + Kateg.\" Feiertag\"" }, + +Please send the translated text to +Lutz@pi-sync.net +such that I can add it to the program package and +other users can benefit from your translation work. diff --git a/bin/kdepim/korganizer/week.png b/bin/kdepim/korganizer/week.png Binary files differnew file mode 100644 index 0000000..5eb69ec --- a/dev/null +++ b/bin/kdepim/korganizer/week.png diff --git a/bin/kdepim/korganizer/whatsnext.png b/bin/kdepim/korganizer/whatsnext.png Binary files differnew file mode 100644 index 0000000..099599f --- a/dev/null +++ b/bin/kdepim/korganizer/whatsnext.png diff --git a/bin/kdepim/korganizer/workweek.png b/bin/kdepim/korganizer/workweek.png Binary files differnew file mode 100644 index 0000000..010e868 --- a/dev/null +++ b/bin/kdepim/korganizer/workweek.png diff --git a/bin/kdepim/korganizer/xdays.png b/bin/kdepim/korganizer/xdays.png Binary files differnew file mode 100644 index 0000000..bb7591e --- a/dev/null +++ b/bin/kdepim/korganizer/xdays.png diff --git a/copying.txt b/copying.txt new file mode 100644 index 0000000..4d564f3 --- a/dev/null +++ b/copying.txt @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + License is intended to guarantee your freedom to share and change free + software--to make sure the software is free for all its users. This + General Public License applies to most of the Free Software + Foundation's software and to any other program whose authors commit to + using it. (Some other Free Software Foundation software is covered by + the GNU Library General Public License instead.) You can apply it to + your programs, too. + + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get it + if you want it, that you can change the software or use pieces of it + in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the rights. + These restrictions translate to certain responsibilities for you if you + distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether + gratis or for a fee, you must give the recipients all the rights that + you have. You must make sure that they, too, receive or can get the + source code. And you must show them these terms so they know their + rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, we + want its recipients to know that what they have is not the original, so + that any problems introduced by others will not reflect on the original + authors' reputations. + + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that redistributors of a free + program will individually obtain patent licenses, in effect making the + program proprietary. To prevent this, we have made it clear that any + patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and + modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains + a notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", below, + refers to any such program or work, and a "work based on the Program" + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation in + the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running the Program is not restricted, and the output from the Program + is covered only if its contents constitute a work based on the + Program (independent of having been made by running the Program). + Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any warranty; + and give any other recipients of the Program a copy of this License + along with the Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Program, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source + code means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the executable. However, as a + special exception, the source code distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of the + operating system on which the executable runs, unless that component + itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program is + void, and will automatically terminate your rights under this License. + However, parties who have received copies, or rights, from you under + this License will not have their licenses terminated so long as such + parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties to + this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Program at all. For example, if a patent + license would not permit royalty-free redistribution of the Program by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License + may add an explicit geographical distribution limitation excluding + those countries, so that distribution is permitted only in or among + countries not thus excluded. In such case, this License incorporates + the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions + of the General Public License from time to time. Such new versions will + be similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", you have the option of following the terms and conditions + either of that version or of any later version published by the Free + Software Foundation. If the Program does not specify a version number of + this License, you may choose any version ever published by the Free Software + Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the author + to ask for permission. For software which is copyrighted by the Free + Software Foundation, write to the Free Software Foundation; we sometimes + make exceptions for this. Our decision will be guided by the two goals + of preserving the free status of all derivatives of our free software and + of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN + OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES + PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS + TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, + REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, + INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING + OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED + TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY + YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER + PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Also add information on how to contact you by electronic and paper mail. + + If the program is interactive, make it output a short notice like this + when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + + The hypothetical commands `show w' and `show c' should show the appropriate + parts of the General Public License. Of course, the commands you use may + be called something other than `show w' and `show c'; they could even be + mouse-clicks or menu items--whatever suits your program. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the program, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your program into + proprietary programs. If your program is a subroutine library, you may + consider it more useful to permit linking proprietary applications with the + library. If this is what you want to do, use the GNU Library General + Public License instead of this License. +
\ No newline at end of file diff --git a/db2file/db2file b/db2file/db2file Binary files differnew file mode 100644 index 0000000..6185930 --- a/dev/null +++ b/db2file/db2file diff --git a/db2file/zdbat_0.2.9-1_arm.ipk b/db2file/zdbat_0.2.9-1_arm.ipk Binary files differnew file mode 100644 index 0000000..d9dd4b4 --- a/dev/null +++ b/db2file/zdbat_0.2.9-1_arm.ipk diff --git a/db2file/zdbat_0.2.9_src.tar.gz b/db2file/zdbat_0.2.9_src.tar.gz Binary files differnew file mode 100644 index 0000000..674b92d --- a/dev/null +++ b/db2file/zdbat_0.2.9_src.tar.gz diff --git a/kabc/address.cpp b/kabc/address.cpp new file mode 100644 index 0000000..26e0b6a --- a/dev/null +++ b/kabc/address.cpp @@ -0,0 +1,630 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +//US added kglobal.h +#include <kglobal.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> + +#include <qfile.h> + +#include "address.h" + +using namespace KABC; + +QMap<QString, QString> Address::mISOMap; + +Address::Address() : + mEmpty( true ), mType( 0 ) +{ + mId = KApplication::randomString( 10 ); +} + +Address::Address( int type ) : + mEmpty( true ), mType( type ) +{ + mId = KApplication::randomString( 10 ); +} + +bool Address::operator==( const Address &a ) const +{ + if ( mPostOfficeBox != a.mPostOfficeBox ) return false; + if ( mExtended != a.mExtended ) return false; + if ( mStreet != a.mStreet ) return false; + if ( mLocality != a.mLocality ) return false; + if ( mRegion != a.mRegion ) return false; + if ( mPostalCode != a.mPostalCode ) return false; + if ( mCountry != a.mCountry ) return false; + if ( mLabel != a.mLabel ) return false; + + return true; +} + +bool Address::operator!=( const Address &a ) const +{ + return !( a == *this ); +} + +bool Address::isEmpty() const +{ + if ( mPostOfficeBox.isEmpty() && + mExtended.isEmpty() && + mStreet.isEmpty() && + mLocality.isEmpty() && + mRegion.isEmpty() && + mPostalCode.isEmpty() && + mCountry.isEmpty() && + mLabel.isEmpty() ) { + return true; + } + return false; +} + +void Address::clear() +{ + *this = Address(); +} + +void Address::setId( const QString &id ) +{ + mEmpty = false; + + mId = id; +} + +QString Address::id() const +{ + return mId; +} + +void Address::setType( int type ) +{ + mEmpty = false; + + mType = type; +} + +int Address::type() const +{ + return mType; +} + +QString Address::typeLabel() const +{ + QString label; + bool first = true; + + TypeList list = typeList(); + + TypeList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + if ( ( type() & (*it) ) && ( (*it) != Pref ) ) { + label.append( ( first ? "" : "/" ) + typeLabel( *it ) ); + if ( first ) + first = false; + } + } + + return label; +} + +void Address::setPostOfficeBox( const QString &s ) +{ + mEmpty = false; + + mPostOfficeBox = s; +} + +QString Address::postOfficeBox() const +{ + return mPostOfficeBox; +} + +QString Address::postOfficeBoxLabel() +{ + return i18n("Post Office Box"); +} + + +void Address::setExtended( const QString &s ) +{ + mEmpty = false; + + mExtended = s; +} + +QString Address::extended() const +{ + return mExtended; +} + +QString Address::extendedLabel() +{ + return i18n("Extended Address Information"); +} + + +void Address::setStreet( const QString &s ) +{ + mEmpty = false; + + mStreet = s; +} + +QString Address::street() const +{ + return mStreet; +} + +QString Address::streetLabel() +{ + return i18n("Street"); +} + + +void Address::setLocality( const QString &s ) +{ + mEmpty = false; + + mLocality = s; +} + +QString Address::locality() const +{ + return mLocality; +} + +QString Address::localityLabel() +{ + return i18n("Locality"); +} + + +void Address::setRegion( const QString &s ) +{ + mEmpty = false; + + mRegion = s; +} + +QString Address::region() const +{ + return mRegion; +} + +QString Address::regionLabel() +{ + return i18n("Region"); +} + + +void Address::setPostalCode( const QString &s ) +{ + mEmpty = false; + + mPostalCode = s; +} + +QString Address::postalCode() const +{ + return mPostalCode; +} + +QString Address::postalCodeLabel() +{ + return i18n("Postal Code"); +} + + +void Address::setCountry( const QString &s ) +{ + mEmpty = false; + + mCountry = s; +} + +QString Address::country() const +{ + return mCountry; +} + +QString Address::countryLabel() +{ + return i18n("Country"); +} + + +void Address::setLabel( const QString &s ) +{ + mEmpty = false; + + mLabel = s; +} + +QString Address::label() const +{ + return mLabel; +} + +QString Address::labelLabel() +{ + return i18n("Delivery Label"); +} + +Address::TypeList Address::typeList() +{ + TypeList list; + + list << Dom << Intl << Postal << Parcel << Home << Work << Pref; + + return list; +} + +QString Address::typeLabel( int type ) +{ + switch ( type ) { + case Dom: + return i18n("Domestic"); + break; + case Intl: + return i18n("International"); + break; + case Postal: + return i18n("Postal"); + break; + case Parcel: + return i18n("Parcel"); + break; + case Home: + return i18n("Home Address", "Home"); + break; + case Work: + return i18n("Work Address", "Work"); + break; + case Pref: + return i18n("Preferred Address"); + break; + default: + return i18n("Other"); + break; + } +} + +void Address::dump() const +{ + qDebug("Address::dump() +++++++++++++++++ "); +#if 0 + kdDebug(5700) << " Address {" << endl; + kdDebug(5700) << " Id: " << id() << endl; + kdDebug(5700) << " Extended: " << extended() << endl; + kdDebug(5700) << " Street: " << street() << endl; + kdDebug(5700) << " Postal Code: " << postalCode() << endl; + kdDebug(5700) << " Locality: " << locality() << endl; + kdDebug(5700) << " }" << endl; +#endif +} + + +QString Address::formattedAddress( const QString &realName + , const QString &orgaName ) const +{ + QString ciso; + QString addrTemplate; + QString ret; + + // ************************************************************** + // LR: currently we have no iso handling - we will format the address manually here + + QString text; + if ( !street().isEmpty() ) + text += street() + "\n"; + + if ( !postOfficeBox().isEmpty() ) + text += postOfficeBox() + "\n"; + + text += locality() + QString(" ") + region(); + + if ( !postalCode().isEmpty() ) + text += QString(", ") + postalCode(); + + text += "\n"; + + if ( !country().isEmpty() ) + text += country() + "\n"; + + text += extended(); + + + return text; + // ************************************************************** + + // FIXME: first check for iso-country-field and prefer that one + if ( !country().isEmpty() ) { + ciso = countryToISO( country() ); + } else { + // fall back to our own country + ciso = KGlobal::locale()->country(); + } + //qDebug("ciso %s ",ciso.latin1() ); + KSimpleConfig entry( locate( "locale", + QString( "l10n/" ) + ciso + QString( "/entry.desktop" ) ) ); + entry.setGroup( "KCM Locale" ); + + // decide whether this needs special business address formatting + if ( orgaName.isNull() ) { + addrTemplate = entry.readEntry( "AddressFormat" ); + } else { + addrTemplate = entry.readEntry( "BusinessAddressFormat" ); + if ( addrTemplate.isEmpty() ) + addrTemplate = entry.readEntry( "AddressFormat" ); + } + + // in the case there's no format found at all, default to what we've always + // used: + if ( addrTemplate.isEmpty() ) { + qDebug("address format database incomplete****************** "); + kdWarning(5700) << "address format database incomplete " + << "(no format for locale " << ciso + << " found). Using default address formatting." << endl; + addrTemplate = "%0(%n\\n)%0(%cm\\n)%0(%s\\n)%0(PO BOX %p\\n)%0(%l%w%r)%,%z"; + } + + // scan + parseAddressTemplateSection( addrTemplate, ret, realName, orgaName ); + + // now add the country line if needed (formatting this time according to + // the rules of our own system country ) + if ( !country().isEmpty() ) { + KSimpleConfig entry( locate( "locale", QString( "l10n/" ) + + KGlobal::locale()->country() + QString( "/entry.desktop" ) ) ); + entry.setGroup( "KCM Locale" ); + QString cpos = entry.readEntry( "AddressCountryPosition" ); + if ( "BELOW" == cpos || cpos.isEmpty() ) { + ret = ret + "\n\n" + country().upper(); + } else if ( "below" == cpos ) { + ret = ret + "\n\n" + country(); + } else if ( "ABOVE" == cpos ) { + ret = country().upper() + "\n\n" + ret; + } else if ( "above" == cpos ) { + ret = country() + "\n\n" + ret; + } + } + + return ret; +} + +bool Address::parseAddressTemplateSection( const QString &tsection, + QString &result, const QString &realName, const QString &orgaName ) const +{ + // This method first parses and substitutes any bracketed sections and + // after that replaces any tags with their values. If a bracketed section + // or a tag evaluate to zero, they are not just removed but replaced + // with a placeholder. This is because in the last step conditionals are + // resolved which depend on information about zero-evaluations. + result = tsection; + int stpos = 0; + bool ret = false; + + // first check for brackets that have to be evaluated first + int fpos = result.find( KABC_FMTTAG_purgeempty, stpos ); + while ( -1 != fpos ) { + int bpos1 = fpos + KABC_FMTTAG_purgeempty.length(); + int bpos2; + // expect opening bracket and find next balanced closing bracket. If + // next char is no opening bracket, continue parsing (no valid tag) + if ( '(' == result[bpos1] ) { + bpos2 = findBalancedBracket( result, bpos1 ); + if ( -1 != bpos2 ) { + // we have balanced brackets, recursively parse: + QString rplstr; + bool purge = !parseAddressTemplateSection( result.mid( bpos1+1, + bpos2-bpos1-1 ), rplstr, + realName, orgaName ); + if ( purge ) { + // purge -> remove all + // replace with !_P_!, so conditional tags work later + result.replace( fpos, bpos2 - fpos + 1, "!_P_!" ); + // leave stpos as it is + } else { + // no purge -> replace with recursively parsed string + result.replace( fpos, bpos2 - fpos + 1, rplstr ); + ret = true; + stpos = fpos + rplstr.length(); + } + } else { + // unbalanced brackets: keep on parsing (should not happen + // and will result in bad formatting) + stpos = bpos1; + } + } + fpos = result.find( KABC_FMTTAG_purgeempty, stpos ); + } + + // after sorting out all purge tags, we just search'n'replace the rest, + // keeping track of whether at least one tag evaluates to something. + // The following macro needs QString for R_FIELD + // It substitutes !_P_! for empty fields so conditional tags work later +#define REPLTAG(R_TAG,R_FIELD) \ + if ( result.contains(R_TAG, false) ) { \ + QString rpl = R_FIELD.isEmpty() ? QString("!_P_!") : R_FIELD; \ + result.replace( R_TAG, rpl ); \ + if ( !R_FIELD.isEmpty() ) { \ + ret = true; \ + } \ + } + REPLTAG( KABC_FMTTAG_realname, realName ); + REPLTAG( KABC_FMTTAG_REALNAME, realName.upper() ); + REPLTAG( KABC_FMTTAG_company, orgaName ); + REPLTAG( KABC_FMTTAG_COMPANY, orgaName.upper() ); + REPLTAG( KABC_FMTTAG_pobox, postOfficeBox() ); + REPLTAG( KABC_FMTTAG_street, street() ); + REPLTAG( KABC_FMTTAG_STREET, street().upper() ); + REPLTAG( KABC_FMTTAG_zipcode, postalCode() ); + REPLTAG( KABC_FMTTAG_location, locality() ); + REPLTAG( KABC_FMTTAG_LOCATION, locality().upper() ); + REPLTAG( KABC_FMTTAG_region, region() ); + REPLTAG( KABC_FMTTAG_REGION, region().upper() ); + result.replace( KABC_FMTTAG_newline, "\n" ); +#undef REPLTAG + + // conditional comma + fpos = result.find( KABC_FMTTAG_condcomma, 0 ); + while ( -1 != fpos ) { + QString str1 = result.mid( fpos - 5, 5 ); + QString str2 = result.mid( fpos + 2, 5 ); + if ( str1 != "!_P_!" && str2 != "!_P_!" ) { + result.replace( fpos, 2, ", " ); + } else { + result.remove( fpos, 2 ); + } + fpos = result.find( KABC_FMTTAG_condcomma, fpos ); + } + // conditional whitespace + fpos = result.find( KABC_FMTTAG_condwhite, 0 ); + while ( -1 != fpos ) { + QString str1 = result.mid( fpos - 5, 5 ); + QString str2 = result.mid( fpos + 2, 5 ); + if ( str1 != "!_P_!" && str2 != "!_P_!" ) { + result.replace( fpos, 2, " " ); + } else { + result.remove( fpos, 2 ); + } + fpos = result.find( KABC_FMTTAG_condwhite, fpos ); + } + + // remove purged: +//US my QT version does not support remove. So lets do it the old fashioned way. +//US result.remove( "!_P_!" ); + int n = result.find("!_P_!"); + if (n >= 0) + result.remove( n, 5 ); + + return ret; +} + +int Address::findBalancedBracket( const QString &tsection, int pos ) const +{ + int balancecounter = 0; + for( unsigned int i = pos + 1; i < tsection.length(); i++ ) { + if ( ')' == tsection.at(i) && 0 == balancecounter ) { + // found end of brackets + return i; + } else + if ( '(' == tsection.at(i) ) { + // nested brackets + balancecounter++; + } + } + return -1; +} + +QString Address::countryToISO( const QString &cname ) +{ + // we search a map file for translations from country names to + // iso codes, storing caching things in a QMap for faster future + // access. +/*US + + QString isoCode = mISOMap[ cname ]; + if ( !isoCode.isEmpty() ) + return isoCode; + + QString mapfile = KGlobal::dirs()->findResource( "data", + QString::fromLatin1( "kabc/countrytransl.map" ) ); + + QFile file( mapfile ); + if ( file.open( IO_ReadOnly ) ) { + QTextStream s( &file ); + QString strbuf = s.readLine(); + while( !strbuf.isNull() ) { + if ( strbuf.startsWith( cname ) ) { + int index = strbuf.findRev('\t'); + strbuf = strbuf.mid(index+1, 2); + file.close(); + mISOMap[ cname ] = strbuf; + return strbuf; + } + strbuf = s.readLine(); + } + file.close(); + } +*/ + // fall back to system country + mISOMap[ cname ] = KGlobal::locale()->country(); + return KGlobal::locale()->country(); +} + +QString Address::ISOtoCountry( const QString &ISOname ) +{ +/*US + // get country name from ISO country code (e.g. "no" -> i18n("Norway")) + QString mapfile = KGlobal::dirs()->findResource( "data", + QString::fromLatin1( "kabc/countrytransl.map" ) ); + +kdWarning() << "MAPFILE : " << mapfile << endl; + QFile file( mapfile ); + if ( file.open( IO_ReadOnly ) ) { + QTextStream s( &file ); + QString searchStr = "\t" + ISOname.simplifyWhiteSpace().lower(); +kdWarning() << "Suche : " << searchStr << endl; + QString strbuf = s.readLine(); + int pos; + while( !strbuf.isNull() ) { + if ( (pos=strbuf.find( searchStr )) != -1 ) { + file.close(); + return i18n(strbuf.left(pos).utf8()); + } + strbuf = s.readLine(); + } + file.close(); + } +*/ + return ISOname; +} + +QDataStream &KABC::operator<<( QDataStream &s, const Address &addr ) +{ + return s << addr.mId << addr.mType << addr.mPostOfficeBox << + addr.mExtended << addr.mStreet << addr.mLocality << + addr.mRegion << addr.mPostalCode << addr.mCountry << + addr.mLabel; +} + +QDataStream &KABC::operator>>( QDataStream &s, Address &addr ) +{ + s >> addr.mId >> addr.mType >> addr.mPostOfficeBox >> addr.mExtended >> + addr.mStreet >> addr.mLocality >> addr.mRegion >> + addr.mPostalCode >> addr.mCountry >> addr.mLabel; + + addr.mEmpty = false; + + return s; +} diff --git a/kabc/address.h b/kabc/address.h new file mode 100644 index 0000000..ad132a7 --- a/dev/null +++ b/kabc/address.h @@ -0,0 +1,346 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_ADDRESS_H +#define KABC_ADDRESS_H + +#include <qmap.h> +#include <qstring.h> +#include <qvaluelist.h> + +// template tags for address formatting localization +#define KABC_FMTTAG_realname QString("%n") +#define KABC_FMTTAG_REALNAME QString("%N") +#define KABC_FMTTAG_company QString("%cm") +#define KABC_FMTTAG_COMPANY QString("%CM") +#define KABC_FMTTAG_pobox QString("%p") +#define KABC_FMTTAG_street QString("%s") +#define KABC_FMTTAG_STREET QString("%S") +#define KABC_FMTTAG_zipcode QString("%z") +#define KABC_FMTTAG_location QString("%l") +#define KABC_FMTTAG_LOCATION QString("%L") +#define KABC_FMTTAG_region QString("%r") +#define KABC_FMTTAG_REGION QString("%R") +#define KABC_FMTTAG_newline QString("\\n") +#define KABC_FMTTAG_condcomma QString("%,") +#define KABC_FMTTAG_condwhite QString("%w") +#define KABC_FMTTAG_purgeempty QString("%0") + +namespace KABC { + +/** + @short Postal address information. + + This class represents information about a postal address. +*/ +class Address +{ + friend QDataStream &operator<<( QDataStream &, const Address & ); + friend QDataStream &operator>>( QDataStream &, Address & ); + + public: + /** + List of addresses. + */ + typedef QValueList<Address> List; + typedef QValueList<int> TypeList; + + /** + Address types: + + @li @p Dom - domestic + @li @p Intl - international + @li @p Postal - postal + @li @p Parcel - parcel + @li @p Home - home address + @li @p Work - address at work + @li @p Pref - preferred address + */ + enum Type { Dom = 1, Intl = 2, Postal = 4, Parcel = 8, Home = 16, Work = 32, + Pref = 64 }; + + /** + Constructor that creates an empty Address, which is initialized + with a unique id (see @ref id()). + */ + Address(); + + /** + This is like @ref Address() just above, with the difference + that you can specify the type. + */ + Address( int ); + + bool operator==( const Address & ) const; + bool operator!=( const Address & ) const; + + /** + Returns true, if the address is empty. + */ + bool isEmpty() const; + + /** + Clears all entries of the address. + */ + void clear(); + + /** + Sets the unique id. + */ + void setId( const QString & ); + + /* + Returns the unique id. + */ + QString id() const; + + /** + Sets the type of address. See enum for definiton of types. + + @param type type, can be a bitwise or of multiple types. + */ + void setType( int type ); + + /** + Returns the type of address. Can be a bitwise or of multiple types. + */ + int type() const; + + /** + Returns a translated string of all types the address has. + */ + QString typeLabel() const; + + /** + Sets the post office box. + */ + void setPostOfficeBox( const QString & ); + + /** + Returns the post office box. + */ + QString postOfficeBox() const; + + /** + Returns the translated label for post office box field. + */ + static QString postOfficeBoxLabel(); + + /** + Sets the extended address information. + */ + void setExtended( const QString & ); + + /** + Returns the extended address information. + */ + QString extended() const; + + /** + Returns the translated label for extended field. + */ + static QString extendedLabel(); + + /** + Sets the street (including number). + */ + void setStreet( const QString & ); + + /** + Returns the street. + */ + QString street() const; + + /** + Returns the translated label for street field. + */ + static QString streetLabel(); + + /** + Sets the locality, e.g. city. + */ + void setLocality( const QString & ); + + /** + Returns the locality. + */ + QString locality() const; + + /** + Returns the translated label for locality field. + */ + static QString localityLabel(); + + /** + Sets the region, e.g. state. + */ + void setRegion( const QString & ); + + /** + Returns the region. + */ + QString region() const; + + /** + Returns the translated label for region field. + */ + static QString regionLabel(); + + /** + Sets the postal code. + */ + void setPostalCode( const QString & ); + + /** + Returns the postal code. + */ + QString postalCode() const; + + /** + Returns the translated label for postal code field. + */ + static QString postalCodeLabel(); + + /** + Sets the country. + */ + void setCountry( const QString & ); + + /** + Returns the country. + */ + QString country() const; + + /** + Returns the translated label for country field. + */ + static QString countryLabel(); + + /** + Sets the delivery label. This is the literal text to be used as label. + */ + void setLabel( const QString & ); + + /** + Returns the delivery label. + */ + QString label() const; + + /** + Returns the translated label for delivery label field. + */ + static QString labelLabel(); + + /** + Returns the list of available types. + */ + static TypeList typeList(); + + /** + Returns the translated label for a special type. + */ + static QString typeLabel( int type ); + + /** + Used for debug output. + */ + void dump() const; + + /** + Returns this address formatted according to the country-specific + address formatting rules. The formatting rules applied depend on + either the addresses {@link #country country} field, or (if the + latter is empty) on the system country setting. If companyName is + provided, an available business address format will be preferred. + + @param realName the formatted name of the contact + @param orgaName the name of the organization or company + @return the formatted address (containing newline characters) + */ + QString formattedAddress( const QString &realName=QString::null + , const QString &orgaName=QString::null ) const; + + /** + Returns ISO code for a localized country name. Only localized country + names will be understood. This might be replaced by a KLocale method in + the future. + @param cname name of the country + @return two digit ISO code + */ + static QString countryToISO( const QString &cname ); + + /** + Returns a localized country name for a ISO code. + This might be replaced by a KLocale method in the future. + @param ISOname two digit ISO code + @return localized name of the country + @since 3.2 + */ + static QString ISOtoCountry( const QString &ISOname ); + + private: + /** + Parses a snippet of an address template + @param tsection the template string to be parsed + @param result QString reference in which the result will be stored + @return true if at least one tag evaluated positively, else false + */ + bool parseAddressTemplateSection( const QString &tsection + , QString &result + , const QString &realName + , const QString &orgaName ) const; + + /** + Finds the balanced closing bracket starting from the opening bracket at + pos in tsection. + @return position of closing bracket, -1 for unbalanced brackets + */ + int findBalancedBracket( const QString &tsection, int pos ) const; + + bool mEmpty; + + QString mId; + int mType; + + QString mPostOfficeBox; + QString mExtended; + QString mStreet; + QString mLocality; + QString mRegion; + QString mPostalCode; + QString mCountry; + QString mLabel; + + static QMap<QString, QString> mISOMap; +}; + +QDataStream &operator<<( QDataStream &, const Address & ); +QDataStream &operator>>( QDataStream &, Address & ); + +} + +#endif diff --git a/kabc/addressbook.cpp b/kabc/addressbook.cpp new file mode 100644 index 0000000..203efc2 --- a/dev/null +++ b/kabc/addressbook.cpp @@ -0,0 +1,655 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KAB_EMBEDDED + +#include <qfile.h> +#include <qregexp.h> +#include <qtimer.h> + +#include <kapplication.h> +#include <kinstance.h> +#include <kstandarddirs.h> + +#include "errorhandler.h" + +#else //KAB_EMBEDDED +#include <qptrlist.h> +#endif //KAB_EMBEDDED + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> +#include "addressbook.h" +#include "resource.h" + +#ifndef KAB_EMBEDDED +#include "addressbook.moc" +#endif //KAB_EMBEDDED + +using namespace KABC; + +struct AddressBook::AddressBookData +{ + Addressee::List mAddressees; + Addressee::List mRemovedAddressees; + Field::List mAllFields; + KConfig *mConfig; + KRES::Manager<Resource> *mManager; +#ifndef KAB_EMBEDDED + ErrorHandler *mErrorHandler; +#endif //KAB_EMBEDDED +}; + +struct AddressBook::Iterator::IteratorData +{ + Addressee::List::Iterator mIt; +}; + +struct AddressBook::ConstIterator::ConstIteratorData +{ + Addressee::List::ConstIterator mIt; +}; + +AddressBook::Iterator::Iterator() +{ + d = new IteratorData; +} + +AddressBook::Iterator::Iterator( const AddressBook::Iterator &i ) +{ + d = new IteratorData; + d->mIt = i.d->mIt; +} + +AddressBook::Iterator &AddressBook::Iterator::operator=( const AddressBook::Iterator &i ) +{ + if( this == &i ) return *this; // guard against self assignment + delete d; // delete the old data the Iterator was completely constructed before + d = new IteratorData; + d->mIt = i.d->mIt; + return *this; +} + +AddressBook::Iterator::~Iterator() +{ + delete d; +} + +const Addressee &AddressBook::Iterator::operator*() const +{ + return *(d->mIt); +} + +Addressee &AddressBook::Iterator::operator*() +{ + return *(d->mIt); +} + +Addressee *AddressBook::Iterator::operator->() +{ + return &(*(d->mIt)); +} + +AddressBook::Iterator &AddressBook::Iterator::operator++() +{ + (d->mIt)++; + return *this; +} + +AddressBook::Iterator &AddressBook::Iterator::operator++(int) +{ + (d->mIt)++; + return *this; +} + +AddressBook::Iterator &AddressBook::Iterator::operator--() +{ + (d->mIt)--; + return *this; +} + +AddressBook::Iterator &AddressBook::Iterator::operator--(int) +{ + (d->mIt)--; + return *this; +} + +bool AddressBook::Iterator::operator==( const Iterator &it ) +{ + return ( d->mIt == it.d->mIt ); +} + +bool AddressBook::Iterator::operator!=( const Iterator &it ) +{ + return ( d->mIt != it.d->mIt ); +} + + +AddressBook::ConstIterator::ConstIterator() +{ + d = new ConstIteratorData; +} + +AddressBook::ConstIterator::ConstIterator( const AddressBook::ConstIterator &i ) +{ + d = new ConstIteratorData; + d->mIt = i.d->mIt; +} + +AddressBook::ConstIterator &AddressBook::ConstIterator::operator=( const AddressBook::ConstIterator &i ) +{ + if( this == &i ) return *this; // guard for self assignment + delete d; // delete the old data because the Iterator was really constructed before + d = new ConstIteratorData; + d->mIt = i.d->mIt; + return *this; +} + +AddressBook::ConstIterator::~ConstIterator() +{ + delete d; +} + +const Addressee &AddressBook::ConstIterator::operator*() const +{ + return *(d->mIt); +} + +const Addressee* AddressBook::ConstIterator::operator->() const +{ + return &(*(d->mIt)); +} + +AddressBook::ConstIterator &AddressBook::ConstIterator::operator++() +{ + (d->mIt)++; + return *this; +} + +AddressBook::ConstIterator &AddressBook::ConstIterator::operator++(int) +{ + (d->mIt)++; + return *this; +} + +AddressBook::ConstIterator &AddressBook::ConstIterator::operator--() +{ + (d->mIt)--; + return *this; +} + +AddressBook::ConstIterator &AddressBook::ConstIterator::operator--(int) +{ + (d->mIt)--; + return *this; +} + +bool AddressBook::ConstIterator::operator==( const ConstIterator &it ) +{ + return ( d->mIt == it.d->mIt ); +} + +bool AddressBook::ConstIterator::operator!=( const ConstIterator &it ) +{ + return ( d->mIt != it.d->mIt ); +} + + +AddressBook::AddressBook() +{ + init(0); +} + +AddressBook::AddressBook( const QString &config ) +{ + init(config); +} + +void AddressBook::init(const QString &config) +{ + d = new AddressBookData; + if (config != 0) { + d->mConfig = new KConfig( config ); +// qDebug("AddressBook::init 1 config=%s",config.latin1() ); + } + else { + d->mConfig = 0; +// qDebug("AddressBook::init 1 config=0"); + } + +#ifndef KAB_EMBEDDED + d->mErrorHandler = 0; +#endif //KAB_EMBEDDED + d->mManager = new KRES::Manager<Resource>( "contact" ); + d->mManager->readConfig( d->mConfig ); +} + +AddressBook::~AddressBook() +{ + delete d->mConfig; d->mConfig = 0; + delete d->mManager; d->mManager = 0; +#ifndef KAB_EMBEDDED + delete d->mErrorHandler; d->mErrorHandler = 0; +#endif //KAB_EMBEDDED + delete d; d = 0; +} + +bool AddressBook::load() +{ + kdDebug(5700) << "AddressBook::load()" << endl; + + clear(); + + KRES::Manager<Resource>::ActiveIterator it; + bool ok = true; + for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) + if ( !(*it)->load() ) { + error( i18n("Unable to load resource '%1'").arg( (*it)->resourceName() ) ); + ok = false; + } + + // mark all addressees as unchanged + Addressee::List::Iterator addrIt; + for ( addrIt = d->mAddressees.begin(); addrIt != d->mAddressees.end(); ++addrIt ) + (*addrIt).setChanged( false ); + + return ok; +} + +bool AddressBook::save( Ticket *ticket ) +{ + kdDebug(5700) << "AddressBook::save()"<< endl; + + if ( ticket->resource() ) { + deleteRemovedAddressees(); + + return ticket->resource()->save( ticket ); + } + + return false; +} + +AddressBook::Iterator AddressBook::begin() +{ + Iterator it = Iterator(); + it.d->mIt = d->mAddressees.begin(); + return it; +} + +AddressBook::ConstIterator AddressBook::begin() const +{ + ConstIterator it = ConstIterator(); + it.d->mIt = d->mAddressees.begin(); + return it; +} + +AddressBook::Iterator AddressBook::end() +{ + Iterator it = Iterator(); + it.d->mIt = d->mAddressees.end(); + return it; +} + +AddressBook::ConstIterator AddressBook::end() const +{ + ConstIterator it = ConstIterator(); + it.d->mIt = d->mAddressees.end(); + return it; +} + +void AddressBook::clear() +{ + d->mAddressees.clear(); +} + +Ticket *AddressBook::requestSaveTicket( Resource *resource ) +{ + kdDebug(5700) << "AddressBook::requestSaveTicket()" << endl; + + if ( !resource ) + { + qDebug("AddressBook::requestSaveTicket no resource" ); + resource = standardResource(); + } + + KRES::Manager<Resource>::ActiveIterator it; + for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) { + if ( (*it) == resource ) { + if ( (*it)->readOnly() || !(*it)->isOpen() ) + return 0; + else + return (*it)->requestSaveTicket(); + } + } + + return 0; +} + +void AddressBook::insertAddressee( const Addressee &a ) +{ + Addressee::List::Iterator it; + for ( it = d->mAddressees.begin(); it != d->mAddressees.end(); ++it ) { + if ( a.uid() == (*it).uid() ) { + bool changed = false; + Addressee addr = a; + if ( addr != (*it) ) + changed = true; + + (*it) = a; + if ( (*it).resource() == 0 ) + (*it).setResource( standardResource() ); + + if ( changed ) { + (*it).setRevision( QDateTime::currentDateTime() ); + (*it).setChanged( true ); + } + + return; + } + } + d->mAddressees.append( a ); + Addressee& addr = d->mAddressees.last(); + if ( addr.resource() == 0 ) + addr.setResource( standardResource() ); + + addr.setChanged( true ); +} + +void AddressBook::removeAddressee( const Addressee &a ) +{ + Iterator it; + for ( it = begin(); it != end(); ++it ) { + if ( a.uid() == (*it).uid() ) { + removeAddressee( it ); + return; + } + } +} + +void AddressBook::removeAddressee( const Iterator &it ) +{ + d->mRemovedAddressees.append( (*it) ); + d->mAddressees.remove( it.d->mIt ); +} + +AddressBook::Iterator AddressBook::find( const Addressee &a ) +{ + Iterator it; + for ( it = begin(); it != end(); ++it ) { + if ( a.uid() == (*it).uid() ) { + return it; + } + } + return end(); +} + +Addressee AddressBook::findByUid( const QString &uid ) +{ + Iterator it; + for ( it = begin(); it != end(); ++it ) { + if ( uid == (*it).uid() ) { + return *it; + } + } + return Addressee(); +} + +Addressee::List AddressBook::allAddressees() +{ + return d->mAddressees; +} + +Addressee::List AddressBook::findByName( const QString &name ) +{ + Addressee::List results; + + Iterator it; + for ( it = begin(); it != end(); ++it ) { + if ( name == (*it).name() ) { + results.append( *it ); + } + } + + return results; +} + +Addressee::List AddressBook::findByEmail( const QString &email ) +{ + Addressee::List results; + QStringList mailList; + + Iterator it; + for ( it = begin(); it != end(); ++it ) { + mailList = (*it).emails(); + for ( QStringList::Iterator ite = mailList.begin(); ite != mailList.end(); ++ite ) { + if ( email == (*ite) ) { + results.append( *it ); + } + } + } + + return results; +} + +Addressee::List AddressBook::findByCategory( const QString &category ) +{ + Addressee::List results; + + Iterator it; + for ( it = begin(); it != end(); ++it ) { + if ( (*it).hasCategory( category) ) { + results.append( *it ); + } + } + + return results; +} + +void AddressBook::dump() const +{ + kdDebug(5700) << "AddressBook::dump() --- begin ---" << endl; + + ConstIterator it; + for( it = begin(); it != end(); ++it ) { + (*it).dump(); + } + + kdDebug(5700) << "AddressBook::dump() --- end ---" << endl; +} + +QString AddressBook::identifier() +{ + QStringList identifier; + + + KRES::Manager<Resource>::ActiveIterator it; + for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) { + if ( !(*it)->identifier().isEmpty() ) + identifier.append( (*it)->identifier() ); + } + + return identifier.join( ":" ); +} + +Field::List AddressBook::fields( int category ) +{ + if ( d->mAllFields.isEmpty() ) { + d->mAllFields = Field::allFields(); + } + + if ( category == Field::All ) return d->mAllFields; + + Field::List result; + Field::List::ConstIterator it; + for( it = d->mAllFields.begin(); it != d->mAllFields.end(); ++it ) { + if ( (*it)->category() & category ) result.append( *it ); + } + + return result; +} + +bool AddressBook::addCustomField( const QString &label, int category, + const QString &key, const QString &app ) +{ + if ( d->mAllFields.isEmpty() ) { + d->mAllFields = Field::allFields(); + } +#ifndef KAB_EMBEDDED + QString a = app.isNull() ? KGlobal::instance()->instanceName() : app; +#else //KAB_EMBEDDED + QString a = app.isNull() ? KGlobal::getAppName() : app; +#endif //KAB_EMBEDDED + + QString k = key.isNull() ? label : key; + + Field *field = Field::createCustomField( label, category, k, a ); + + if ( !field ) return false; + + d->mAllFields.append( field ); + + return true; +} + +QDataStream &KABC::operator<<( QDataStream &s, const AddressBook &ab ) +{ + if (!ab.d) return s; + + return s << ab.d->mAddressees; +} + +QDataStream &KABC::operator>>( QDataStream &s, AddressBook &ab ) +{ + if (!ab.d) return s; + + s >> ab.d->mAddressees; + + return s; +} + +bool AddressBook::addResource( Resource *resource ) +{ + qDebug("AddressBook::addResource 1"); + + if ( !resource->open() ) { + kdDebug(5700) << "AddressBook::addResource(): can't add resource" << endl; + return false; + } + + resource->setAddressBook( this ); + + d->mManager->add( resource ); + return true; +} + +bool AddressBook::removeResource( Resource *resource ) +{ + resource->close(); + + if ( resource == standardResource() ) + d->mManager->setStandardResource( 0 ); + + resource->setAddressBook( 0 ); + + d->mManager->remove( resource ); + return true; +} + +QPtrList<Resource> AddressBook::resources() +{ + QPtrList<Resource> list; + +// qDebug("AddressBook::resources() 1"); + + KRES::Manager<Resource>::ActiveIterator it; + for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) + list.append( *it ); + + return list; +} + +#ifndef KAB_EMBEDDED +void AddressBook::setErrorHandler( ErrorHandler *handler ) +{ + delete d->mErrorHandler; + d->mErrorHandler = handler; +} +#endif //KAB_EMBEDDED + +void AddressBook::error( const QString& msg ) +{ +#ifndef KAB_EMBEDDED + if ( !d->mErrorHandler ) // create default error handler + d->mErrorHandler = new ConsoleErrorHandler; + + if ( d->mErrorHandler ) + d->mErrorHandler->error( msg ); + else + kdError(5700) << "no error handler defined" << endl; +#else //KAB_EMBEDDED + kdDebug(5700) << "msg" << endl; + qDebug(msg); +#endif //KAB_EMBEDDED +} + +void AddressBook::deleteRemovedAddressees() +{ + Addressee::List::Iterator it; + for ( it = d->mRemovedAddressees.begin(); it != d->mRemovedAddressees.end(); ++it ) { + Resource *resource = (*it).resource(); + if ( resource && !resource->readOnly() && resource->isOpen() ) + resource->removeAddressee( *it ); + } + + d->mRemovedAddressees.clear(); +} + +void AddressBook::setStandardResource( Resource *resource ) +{ +// qDebug("AddressBook::setStandardResource 1"); + d->mManager->setStandardResource( resource ); +} + +Resource *AddressBook::standardResource() +{ + return d->mManager->standardResource(); +} + +KRES::Manager<Resource> *AddressBook::resourceManager() +{ + return d->mManager; +} + +void AddressBook::cleanUp() +{ + KRES::Manager<Resource>::ActiveIterator it; + for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) { + if ( !(*it)->readOnly() && (*it)->isOpen() ) + (*it)->cleanUp(); + } +} diff --git a/kabc/addressbook.h b/kabc/addressbook.h new file mode 100644 index 0000000..3383fc0 --- a/dev/null +++ b/kabc/addressbook.h @@ -0,0 +1,337 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_ADDRESSBOOK_H +#define KABC_ADDRESSBOOK_H + +#include <qobject.h> + +#include <kresources/manager.h> +#include <qptrlist.h> + +#ifndef KAB_EMBEDDED + +#else //KAB_EMBEDDED +#endif //KAB_EMBEDDED + + +#include "addressee.h" +#include "field.h" + +namespace KABC { + +class ErrorHandler; +class Resource; +class Ticket; + +/** + @short Address Book + + This class provides access to a collection of address book entries. +*/ +class AddressBook : public QObject +{ + Q_OBJECT + + friend QDataStream &operator<<( QDataStream &, const AddressBook & ); + friend QDataStream &operator>>( QDataStream &, AddressBook & ); + friend class StdAddressBook; + + public: + /** + @short Address Book Iterator + + This class provides an iterator for address book entries. + */ + class Iterator + { + public: + Iterator(); + Iterator( const Iterator & ); + ~Iterator(); + + Iterator &operator=( const Iterator & ); + const Addressee &operator*() const; + Addressee &operator*(); + Addressee* operator->(); + Iterator &operator++(); + Iterator &operator++(int); + Iterator &operator--(); + Iterator &operator--(int); + bool operator==( const Iterator &it ); + bool operator!=( const Iterator &it ); + + struct IteratorData; + IteratorData *d; + }; + + /** + @short Address Book Const Iterator + + This class provides a const iterator for address book entries. + */ + class ConstIterator + { + public: + ConstIterator(); + ConstIterator( const ConstIterator & ); + ~ConstIterator(); + + ConstIterator &operator=( const ConstIterator & ); + const Addressee &operator*() const; + const Addressee* operator->() const; + ConstIterator &operator++(); + ConstIterator &operator++(int); + ConstIterator &operator--(); + ConstIterator &operator--(int); + bool operator==( const ConstIterator &it ); + bool operator!=( const ConstIterator &it ); + + struct ConstIteratorData; + ConstIteratorData *d; + }; + + /** + Constructs a address book object. + + @param format File format class. + */ + AddressBook(); + AddressBook( const QString &config ); + virtual ~AddressBook(); + + /** + Requests a ticket for saving the addressbook. Calling this function locks + the addressbook for all other processes. If the address book is already + locked the function returns 0. You need the returned @ref Ticket object + for calling the @ref save() function. + + @see save() + */ + Ticket *requestSaveTicket( Resource *resource=0 ); + + /** + Load address book from file. + */ + bool load(); + + /** + Save address book. The address book is saved to the file, the Ticket + object has been requested for by @ref requestSaveTicket(). + + @param ticket a ticket object returned by @ref requestSaveTicket() + */ + bool save( Ticket *ticket ); + + /** + Returns a iterator for first entry of address book. + */ + Iterator begin(); + + /** + Returns a const iterator for first entry of address book. + */ + ConstIterator begin() const; + + /** + Returns a iterator for first entry of address book. + */ + Iterator end(); + + /** + Returns a const iterator for first entry of address book. + */ + ConstIterator end() const; + + /** + Removes all entries from address book. + */ + void clear(); + + /** + Insert an Addressee object into address book. If an object with the same + unique id already exists in the address book it it replaced by the new + one. If not the new object is appended to the address book. + */ + void insertAddressee( const Addressee & ); + + /** + Removes entry from the address book. + */ + void removeAddressee( const Addressee & ); + + /** + This is like @ref removeAddressee() just above, with the difference that + the first element is a iterator, returned by @ref begin(). + */ + void removeAddressee( const Iterator & ); + + /** + Find the specified entry in address book. Returns end(), if the entry + couldn't be found. + */ + Iterator find( const Addressee & ); + + /** + Find the entry specified by an unique id. Returns an empty Addressee + object, if the address book does not contain an entry with this id. + */ + Addressee findByUid( const QString & ); + + + /** + Returns a list of all addressees in the address book. This list can + be sorted with @ref KABC::AddresseeList for example. + */ + Addressee::List allAddressees(); + + /** + Find all entries with the specified name in the address book. Returns + an empty list, if no entries could be found. + */ + Addressee::List findByName( const QString & ); + + /** + Find all entries with the specified email address in the address book. + Returns an empty list, if no entries could be found. + */ + Addressee::List findByEmail( const QString & ); + + /** + Find all entries wich have the specified category in the address book. + Returns an empty list, if no entries could be found. + */ + Addressee::List findByCategory( const QString & ); + + /** + Return a string identifying this addressbook. + */ + virtual QString identifier(); + + /** + Used for debug output. + */ + void dump() const; + + void emitAddressBookLocked() { emit addressBookLocked( this ); } + void emitAddressBookUnlocked() { emit addressBookUnlocked( this ); } + void emitAddressBookChanged() { emit addressBookChanged( this ); } + + /** + Return list of all Fields known to the address book which are associated + with the given field category. + */ + Field::List fields( int category = Field::All ); + + /** + Add custom field to address book. + + @param label User visible label of the field. + @param category Ored list of field categories. + @param key Identifier used as key for reading and writing the field. + @param app String used as application key for reading and writing + the field. + */ + bool addCustomField( const QString &label, int category = Field::All, + const QString &key = QString::null, + const QString &app = QString::null ); + + + /** + Add address book resource. + */ + bool addResource( Resource * ); + + /** + Remove address book resource. + */ + bool removeResource( Resource * ); + + /** + Return pointer list of all resources. + */ + QPtrList<Resource> resources(); + + /** + Set the @p ErrorHandler, that is used by @ref error() to + provide gui-independend error messages. + */ + void setErrorHandler( ErrorHandler * ); + + /** + Shows gui independend error messages. + */ + void error( const QString& ); + + /** + Query all resources to clean up their lock files + */ + void cleanUp(); + + signals: + /** + Emitted, when the address book has changed on disk. + */ + void addressBookChanged( AddressBook * ); + + /** + Emitted, when the address book has been locked for writing. + */ + void addressBookLocked( AddressBook * ); + + /** + Emitted, when the address book has been unlocked. + */ + void addressBookUnlocked( AddressBook * ); + + protected: + void deleteRemovedAddressees(); + void setStandardResource( Resource * ); + Resource *standardResource(); + KRES::Manager<Resource> *resourceManager(); + + private: +#ifndef KAB_EMBEDDED + QPtrList<Resource> mDummy; // Remove in KDE 4 +#endif //KAB_EMBEDDED + +#ifdef KAB_EMBEDDED +//US optimization + void init(const QString &config); +#endif //KAB_EMBEDDED + + + struct AddressBookData; + AddressBookData *d; +}; + +QDataStream &operator<<( QDataStream &, const AddressBook & ); +QDataStream &operator>>( QDataStream &, AddressBook & ); + +} + +#endif diff --git a/kabc/addressee.cpp b/kabc/addressee.cpp new file mode 100644 index 0000000..5cb194a --- a/dev/null +++ b/kabc/addressee.cpp @@ -0,0 +1,1616 @@ +/*** Warning! This file has been generated by the script makeaddressee ***/ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <kconfig.h> + +#include <ksharedptr.h> +#include <kdebug.h> +#include <kapplication.h> +#include <klocale.h> +//US +#include <kstandarddirs.h> + +//US #include "resource.h" +#include "addressee.h" + +using namespace KABC; + +static bool matchBinaryPattern( int value, int pattern ); + +struct Addressee::AddresseeData : public KShared +{ + QString uid; + QString name; + QString formattedName; + QString familyName; + QString givenName; + QString additionalName; + QString prefix; + QString suffix; + QString nickName; + QDateTime birthday; + QString mailer; + TimeZone timeZone; + Geo geo; + QString title; + QString role; + QString organization; + QString note; + QString productId; + QDateTime revision; + QString sortString; + KURL url; + Secrecy secrecy; + Picture logo; + Picture photo; + Sound sound; + Agent agent; + + PhoneNumber::List phoneNumbers; + Address::List addresses; + Key::List keys; + QStringList emails; + QStringList categories; + QStringList custom; + + Resource *resource; + + bool empty :1; + bool changed :1; +}; + +Addressee::Addressee() +{ + mData = new AddresseeData; + mData->empty = true; + mData->changed = false; + mData->resource = 0; +} + +Addressee::~Addressee() +{ +} + +Addressee::Addressee( const Addressee &a ) +{ + mData = a.mData; +} + +Addressee &Addressee::operator=( const Addressee &a ) +{ + mData = a.mData; + return (*this); +} + +Addressee Addressee::copy() +{ + Addressee a; + *(a.mData) = *mData; + return a; +} + +void Addressee::detach() +{ + if ( mData.count() == 1 ) return; + *this = copy(); +} + +bool Addressee::operator==( const Addressee &a ) const +{ + if ( uid() != a.uid() ) return false; + if ( mData->name != a.mData->name ) return false; + if ( mData->formattedName != a.mData->formattedName ) return false; + if ( mData->familyName != a.mData->familyName ) return false; + if ( mData->givenName != a.mData->givenName ) return false; + if ( mData->additionalName != a.mData->additionalName ) return false; + if ( mData->prefix != a.mData->prefix ) return false; + if ( mData->suffix != a.mData->suffix ) return false; + if ( mData->nickName != a.mData->nickName ) return false; + if ( mData->birthday != a.mData->birthday ) return false; + if ( mData->mailer != a.mData->mailer ) return false; + if ( mData->timeZone != a.mData->timeZone ) return false; + if ( mData->geo != a.mData->geo ) return false; + if ( mData->title != a.mData->title ) return false; + if ( mData->role != a.mData->role ) return false; + if ( mData->organization != a.mData->organization ) return false; + if ( mData->note != a.mData->note ) return false; + if ( mData->productId != a.mData->productId ) return false; + if ( mData->revision != a.mData->revision ) return false; + if ( mData->sortString != a.mData->sortString ) return false; + if ( mData->secrecy != a.mData->secrecy ) return false; + if ( mData->logo != a.mData->logo ) return false; + if ( mData->photo != a.mData->photo ) return false; + if ( mData->sound != a.mData->sound ) return false; + if ( mData->agent != a.mData->agent ) return false; + if ( ( mData->url.isValid() || a.mData->url.isValid() ) && + ( mData->url != a.mData->url ) ) return false; + if ( mData->phoneNumbers != a.mData->phoneNumbers ) return false; + if ( mData->addresses != a.mData->addresses ) return false; + if ( mData->keys != a.mData->keys ) return false; + if ( mData->emails != a.mData->emails ) return false; + if ( mData->categories != a.mData->categories ) return false; + if ( mData->custom != a.mData->custom ) return false; + + return true; +} + +bool Addressee::operator!=( const Addressee &a ) const +{ + return !( a == *this ); +} + +bool Addressee::isEmpty() const +{ + return mData->empty; +} + +void Addressee::setUid( const QString &id ) +{ + if ( id == mData->uid ) return; + detach(); + mData->empty = false; + mData->uid = id; +} + +QString Addressee::uid() const +{ + if ( mData->uid.isEmpty() ) + mData->uid = KApplication::randomString( 10 ); + + return mData->uid; +} + +QString Addressee::uidLabel() +{ + return i18n("Unique Identifier"); +} + +void Addressee::setName( const QString &name ) +{ + if ( name == mData->name ) return; + detach(); + mData->empty = false; + mData->name = name; +} + +QString Addressee::name() const +{ + return mData->name; +} + +QString Addressee::nameLabel() +{ + return i18n("Name"); +} + + +void Addressee::setFormattedName( const QString &formattedName ) +{ + if ( formattedName == mData->formattedName ) return; + detach(); + mData->empty = false; + mData->formattedName = formattedName; +} + +QString Addressee::formattedName() const +{ + return mData->formattedName; +} + +QString Addressee::formattedNameLabel() +{ + return i18n("Formatted Name"); +} + + +void Addressee::setFamilyName( const QString &familyName ) +{ + if ( familyName == mData->familyName ) return; + detach(); + mData->empty = false; + mData->familyName = familyName; +} + +QString Addressee::familyName() const +{ + return mData->familyName; +} + +QString Addressee::familyNameLabel() +{ + return i18n("Family Name"); +} + + +void Addressee::setGivenName( const QString &givenName ) +{ + if ( givenName == mData->givenName ) return; + detach(); + mData->empty = false; + mData->givenName = givenName; +} + +QString Addressee::givenName() const +{ + return mData->givenName; +} + +QString Addressee::givenNameLabel() +{ + return i18n("Given Name"); +} + + +void Addressee::setAdditionalName( const QString &additionalName ) +{ + if ( additionalName == mData->additionalName ) return; + detach(); + mData->empty = false; + mData->additionalName = additionalName; +} + +QString Addressee::additionalName() const +{ + return mData->additionalName; +} + +QString Addressee::additionalNameLabel() +{ + return i18n("Additional Names"); +} + + +void Addressee::setPrefix( const QString &prefix ) +{ + if ( prefix == mData->prefix ) return; + detach(); + mData->empty = false; + mData->prefix = prefix; +} + +QString Addressee::prefix() const +{ + return mData->prefix; +} + +QString Addressee::prefixLabel() +{ + return i18n("Honorific Prefixes"); +} + + +void Addressee::setSuffix( const QString &suffix ) +{ + if ( suffix == mData->suffix ) return; + detach(); + mData->empty = false; + mData->suffix = suffix; +} + +QString Addressee::suffix() const +{ + return mData->suffix; +} + +QString Addressee::suffixLabel() +{ + return i18n("Honorific Suffixes"); +} + + +void Addressee::setNickName( const QString &nickName ) +{ + if ( nickName == mData->nickName ) return; + detach(); + mData->empty = false; + mData->nickName = nickName; +} + +QString Addressee::nickName() const +{ + return mData->nickName; +} + +QString Addressee::nickNameLabel() +{ + return i18n("Nick Name"); +} + + +void Addressee::setBirthday( const QDateTime &birthday ) +{ + if ( birthday == mData->birthday ) return; + detach(); + mData->empty = false; + mData->birthday = birthday; +} + +QDateTime Addressee::birthday() const +{ + return mData->birthday; +} + +QString Addressee::birthdayLabel() +{ + return i18n("Birthday"); +} + + +QString Addressee::homeAddressStreetLabel() +{ + return i18n("Home Address Street"); +} + + +QString Addressee::homeAddressLocalityLabel() +{ + return i18n("Home Address Locality"); +} + + +QString Addressee::homeAddressRegionLabel() +{ + return i18n("Home Address Region"); +} + + +QString Addressee::homeAddressPostalCodeLabel() +{ + return i18n("Home Address Postal Code"); +} + + +QString Addressee::homeAddressCountryLabel() +{ + return i18n("Home Address Country"); +} + + +QString Addressee::homeAddressLabelLabel() +{ + return i18n("Home Address Label"); +} + + +QString Addressee::businessAddressStreetLabel() +{ + return i18n("Business Address Street"); +} + + +QString Addressee::businessAddressLocalityLabel() +{ + return i18n("Business Address Locality"); +} + + +QString Addressee::businessAddressRegionLabel() +{ + return i18n("Business Address Region"); +} + + +QString Addressee::businessAddressPostalCodeLabel() +{ + return i18n("Business Address Postal Code"); +} + + +QString Addressee::businessAddressCountryLabel() +{ + return i18n("Business Address Country"); +} + + +QString Addressee::businessAddressLabelLabel() +{ + return i18n("Business Address Label"); +} + + +QString Addressee::homePhoneLabel() +{ + return i18n("Home Phone"); +} + + +QString Addressee::businessPhoneLabel() +{ + return i18n("Business Phone"); +} + + +QString Addressee::mobilePhoneLabel() +{ + return i18n("Mobile Phone"); +} + + +QString Addressee::homeFaxLabel() +{ + return i18n("Home Fax"); +} + + +QString Addressee::businessFaxLabel() +{ + return i18n("Business Fax"); +} + + +QString Addressee::carPhoneLabel() +{ + return i18n("Car Phone"); +} + + +QString Addressee::isdnLabel() +{ + return i18n("ISDN"); +} + + +QString Addressee::pagerLabel() +{ + return i18n("Pager"); +} + + +QString Addressee::emailLabel() +{ + return i18n("Email Address"); +} + + +void Addressee::setMailer( const QString &mailer ) +{ + if ( mailer == mData->mailer ) return; + detach(); + mData->empty = false; + mData->mailer = mailer; +} + +QString Addressee::mailer() const +{ + return mData->mailer; +} + +QString Addressee::mailerLabel() +{ + return i18n("Mail Client"); +} + + +void Addressee::setTimeZone( const TimeZone &timeZone ) +{ + if ( timeZone == mData->timeZone ) return; + detach(); + mData->empty = false; + mData->timeZone = timeZone; +} + +TimeZone Addressee::timeZone() const +{ + return mData->timeZone; +} + +QString Addressee::timeZoneLabel() +{ + return i18n("Time Zone"); +} + + +void Addressee::setGeo( const Geo &geo ) +{ + if ( geo == mData->geo ) return; + detach(); + mData->empty = false; + mData->geo = geo; +} + +Geo Addressee::geo() const +{ + return mData->geo; +} + +QString Addressee::geoLabel() +{ + return i18n("Geographic Position"); +} + + +void Addressee::setTitle( const QString &title ) +{ + if ( title == mData->title ) return; + detach(); + mData->empty = false; + mData->title = title; +} + +QString Addressee::title() const +{ + return mData->title; +} + +QString Addressee::titleLabel() +{ + return i18n("Title"); +} + + +void Addressee::setRole( const QString &role ) +{ + if ( role == mData->role ) return; + detach(); + mData->empty = false; + mData->role = role; +} + +QString Addressee::role() const +{ + return mData->role; +} + +QString Addressee::roleLabel() +{ + return i18n("Role"); +} + + +void Addressee::setOrganization( const QString &organization ) +{ + if ( organization == mData->organization ) return; + detach(); + mData->empty = false; + mData->organization = organization; +} + +QString Addressee::organization() const +{ + return mData->organization; +} + +QString Addressee::organizationLabel() +{ + return i18n("Organization"); +} + + +void Addressee::setNote( const QString ¬e ) +{ + if ( note == mData->note ) return; + detach(); + mData->empty = false; + mData->note = note; +} + +QString Addressee::note() const +{ + return mData->note; +} + +QString Addressee::noteLabel() +{ + return i18n("Note"); +} + + +void Addressee::setProductId( const QString &productId ) +{ + if ( productId == mData->productId ) return; + detach(); + mData->empty = false; + mData->productId = productId; +} + +QString Addressee::productId() const +{ + return mData->productId; +} + +QString Addressee::productIdLabel() +{ + return i18n("Product Identifier"); +} + + +void Addressee::setRevision( const QDateTime &revision ) +{ + if ( revision == mData->revision ) return; + detach(); + mData->empty = false; + mData->revision = revision; +} + +QDateTime Addressee::revision() const +{ + return mData->revision; +} + +QString Addressee::revisionLabel() +{ + return i18n("Revision Date"); +} + + +void Addressee::setSortString( const QString &sortString ) +{ + if ( sortString == mData->sortString ) return; + detach(); + mData->empty = false; + mData->sortString = sortString; +} + +QString Addressee::sortString() const +{ + return mData->sortString; +} + +QString Addressee::sortStringLabel() +{ + return i18n("Sort String"); +} + + +void Addressee::setUrl( const KURL &url ) +{ + if ( url == mData->url ) return; + detach(); + mData->empty = false; + mData->url = url; +} + +KURL Addressee::url() const +{ + return mData->url; +} + +QString Addressee::urlLabel() +{ + return i18n("URL"); +} + + +void Addressee::setSecrecy( const Secrecy &secrecy ) +{ + if ( secrecy == mData->secrecy ) return; + detach(); + mData->empty = false; + mData->secrecy = secrecy; +} + +Secrecy Addressee::secrecy() const +{ + return mData->secrecy; +} + +QString Addressee::secrecyLabel() +{ + return i18n("Security Class"); +} + + +void Addressee::setLogo( const Picture &logo ) +{ + if ( logo == mData->logo ) return; + detach(); + mData->empty = false; + mData->logo = logo; +} + +Picture Addressee::logo() const +{ + return mData->logo; +} + +QString Addressee::logoLabel() +{ + return i18n("Logo"); +} + + +void Addressee::setPhoto( const Picture &photo ) +{ + if ( photo == mData->photo ) return; + detach(); + mData->empty = false; + mData->photo = photo; +} + +Picture Addressee::photo() const +{ + return mData->photo; +} + +QString Addressee::photoLabel() +{ + return i18n("Photo"); +} + + +void Addressee::setSound( const Sound &sound ) +{ + if ( sound == mData->sound ) return; + detach(); + mData->empty = false; + mData->sound = sound; +} + +Sound Addressee::sound() const +{ + return mData->sound; +} + +QString Addressee::soundLabel() +{ + return i18n("Sound"); +} + + +void Addressee::setAgent( const Agent &agent ) +{ + if ( agent == mData->agent ) return; + detach(); + mData->empty = false; + mData->agent = agent; +} + +Agent Addressee::agent() const +{ + return mData->agent; +} + +QString Addressee::agentLabel() +{ + return i18n("Agent"); +} + + + +void Addressee::setNameFromString( const QString &str ) +{ + setFormattedName( str ); + setName( str ); + + QStringList titles; + titles += i18n( "Dr." ); + titles += i18n( "Miss" ); + titles += i18n( "Mr." ); + titles += i18n( "Mrs." ); + titles += i18n( "Ms." ); + titles += i18n( "Prof." ); + + QStringList suffixes; + suffixes += i18n( "I" ); + suffixes += i18n( "II" ); + suffixes += i18n( "III" ); + suffixes += i18n( "Jr." ); + suffixes += i18n( "Sr." ); + + QStringList prefixes; + prefixes += "van"; + prefixes += "von"; + prefixes += "de"; + +//US KConfig config( "kabcrc" ); + KConfig config( locateLocal( "config", "kabcrc") ); + config.setGroup( "General" ); + titles += config.readListEntry( "Prefixes" ); + titles.remove( "" ); + prefixes += config.readListEntry( "Inclusions" ); + prefixes.remove( "" ); + suffixes += config.readListEntry( "Suffixes" ); + suffixes.remove( "" ); + + // clear all name parts + setPrefix( "" ); + setGivenName( "" ); + setAdditionalName( "" ); + setFamilyName( "" ); + setSuffix( "" ); + + if ( str.isEmpty() ) + return; + + int i = str.find(','); + if( i < 0 ) { + QStringList parts = QStringList::split( " ", str ); + int leftOffset = 0; + int rightOffset = parts.count() - 1; + + QString suffix; + while ( rightOffset >= 0 ) { + if ( suffixes.contains( parts[ rightOffset ] ) ) { + suffix.prepend(parts[ rightOffset ] + (suffix.isEmpty() ? "" : " ")); + rightOffset--; + } else + break; + } + setSuffix( suffix ); + + if ( rightOffset < 0 ) + return; + + if ( rightOffset - 1 >= 0 && prefixes.contains( parts[ rightOffset - 1 ].lower() ) ) { + setFamilyName( parts[ rightOffset - 1 ] + " " + parts[ rightOffset ] ); + rightOffset--; + } else + setFamilyName( parts[ rightOffset ] ); + + QString prefix; + while ( leftOffset < rightOffset ) { + if ( titles.contains( parts[ leftOffset ] ) ) { + prefix.append( ( prefix.isEmpty() ? "" : " ") + parts[ leftOffset ] ); + leftOffset++; + } else + break; + } + setPrefix( prefix ); + + if ( leftOffset < rightOffset ) { + setGivenName( parts[ leftOffset ] ); + leftOffset++; + } + + QString additionalName; + while ( leftOffset < rightOffset ) { + additionalName.append( ( additionalName.isEmpty() ? "" : " ") + parts[ leftOffset ] ); + leftOffset++; + } + setAdditionalName( additionalName ); + } else { + QString part1 = str.left( i ); + QString part2 = str.mid( i + 1 ); + + QStringList parts = QStringList::split( " ", part1 ); + int leftOffset = 0; + int rightOffset = parts.count() - 1; + + QString suffix; + while ( rightOffset >= 0 ) { + if ( suffixes.contains( parts[ rightOffset ] ) ) { + suffix.prepend(parts[ rightOffset ] + (suffix.isEmpty() ? "" : " ")); + rightOffset--; + } else + break; + } + setSuffix( suffix ); + + if ( rightOffset - 1 >= 0 && prefixes.contains( parts[ rightOffset - 1 ].lower() ) ) { + setFamilyName( parts[ rightOffset - 1 ] + " " + parts[ rightOffset ] ); + rightOffset--; + } else + setFamilyName( parts[ rightOffset ] ); + + QString prefix; + while ( leftOffset < rightOffset ) { + if ( titles.contains( parts[ leftOffset ] ) ) { + prefix.append( ( prefix.isEmpty() ? "" : " ") + parts[ leftOffset ] ); + leftOffset++; + } else + break; + } + + parts = QStringList::split( " ", part2 ); + + leftOffset = 0; + rightOffset = parts.count(); + + while ( leftOffset < rightOffset ) { + if ( titles.contains( parts[ leftOffset ] ) ) { + prefix.append( ( prefix.isEmpty() ? "" : " ") + parts[ leftOffset ] ); + leftOffset++; + } else + break; + } + setPrefix( prefix ); + + if ( leftOffset < rightOffset ) { + setGivenName( parts[ leftOffset ] ); + leftOffset++; + } + + QString additionalName; + while ( leftOffset < rightOffset ) { + additionalName.append( ( additionalName.isEmpty() ? "" : " ") + parts[ leftOffset ] ); + leftOffset++; + } + setAdditionalName( additionalName ); + } +} + +QString Addressee::realName() const +{ + if ( !formattedName().isEmpty() ) + return formattedName(); + + QString n = assembledName(); + + if ( n.isEmpty() ) + n = name(); + + return n; +} + +QString Addressee::assembledName() const +{ + QString name = prefix() + " " + givenName() + " " + additionalName() + " " + + familyName() + " " + suffix(); + + return name.simplifyWhiteSpace(); +} + +QString Addressee::fullEmail( const QString &email ) const +{ + QString e; + if ( email.isNull() ) { + e = preferredEmail(); + } else { + e = email; + } + if ( e.isEmpty() ) return QString::null; + + QString text; + if ( realName().isEmpty() ) + text = e; + else + text = assembledName() + " <" + e + ">"; + + return text; +} + +void Addressee::insertEmail( const QString &email, bool preferred ) +{ + detach(); + + QStringList::Iterator it = mData->emails.find( email ); + + if ( it != mData->emails.end() ) { + if ( !preferred || it == mData->emails.begin() ) return; + mData->emails.remove( it ); + mData->emails.prepend( email ); + } else { + if ( preferred ) { + mData->emails.prepend( email ); + } else { + mData->emails.append( email ); + } + } +} + +void Addressee::removeEmail( const QString &email ) +{ + detach(); + + QStringList::Iterator it = mData->emails.find( email ); + if ( it == mData->emails.end() ) return; + + mData->emails.remove( it ); +} + +QString Addressee::preferredEmail() const +{ + if ( mData->emails.count() == 0 ) return QString::null; + else return mData->emails.first(); +} + +QStringList Addressee::emails() const +{ + return mData->emails; +} +void Addressee::setEmails( const QStringList& emails ) { + detach(); + mData->emails = emails; +} +void Addressee::insertPhoneNumber( const PhoneNumber &phoneNumber ) +{ + detach(); + mData->empty = false; + + PhoneNumber::List::Iterator it; + for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) { + if ( (*it).id() == phoneNumber.id() ) { + *it = phoneNumber; + return; + } + } + mData->phoneNumbers.append( phoneNumber ); +} + +void Addressee::removePhoneNumber( const PhoneNumber &phoneNumber ) +{ + detach(); + + PhoneNumber::List::Iterator it; + for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) { + if ( (*it).id() == phoneNumber.id() ) { + mData->phoneNumbers.remove( it ); + return; + } + } +} + +PhoneNumber Addressee::phoneNumber( int type ) const +{ + PhoneNumber phoneNumber( "", type ); + PhoneNumber::List::ConstIterator it; + for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) { + if ( matchBinaryPattern( (*it).type(), type ) ) { + if ( (*it).type() & PhoneNumber::Pref ) + return (*it); + else if ( phoneNumber.number().isEmpty() ) + phoneNumber = (*it); + } + } + + return phoneNumber; +} + +PhoneNumber::List Addressee::phoneNumbers() const +{ + return mData->phoneNumbers; +} + +PhoneNumber::List Addressee::phoneNumbers( int type ) const +{ + PhoneNumber::List list; + + PhoneNumber::List::ConstIterator it; + for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) { + if ( matchBinaryPattern( (*it).type(), type ) ) { + list.append( *it ); + } + } + return list; +} + +PhoneNumber Addressee::findPhoneNumber( const QString &id ) const +{ + PhoneNumber::List::ConstIterator it; + for( it = mData->phoneNumbers.begin(); it != mData->phoneNumbers.end(); ++it ) { + if ( (*it).id() == id ) { + return *it; + } + } + return PhoneNumber(); +} + +void Addressee::insertKey( const Key &key ) +{ + detach(); + mData->empty = false; + + Key::List::Iterator it; + for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) { + if ( (*it).id() == key.id() ) { + *it = key; + return; + } + } + mData->keys.append( key ); +} + +void Addressee::removeKey( const Key &key ) +{ + detach(); + + Key::List::Iterator it; + for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) { + if ( (*it).id() == key.id() ) { + mData->keys.remove( key ); + return; + } + } +} + +Key Addressee::key( int type, QString customTypeString ) const +{ + Key::List::ConstIterator it; + for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) { + if ( (*it).type() == type ) { + if ( type == Key::Custom ) { + if ( customTypeString.isEmpty() ) { + return *it; + } else { + if ( (*it).customTypeString() == customTypeString ) + return (*it); + } + } else { + return *it; + } + } + } + return Key( QString(), type ); +} +void Addressee::setKeys( const Key::List& list ) { + detach(); + mData->keys = list; +} + +Key::List Addressee::keys() const +{ + return mData->keys; +} + +Key::List Addressee::keys( int type, QString customTypeString ) const +{ + Key::List list; + + Key::List::ConstIterator it; + for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) { + if ( (*it).type() == type ) { + if ( type == Key::Custom ) { + if ( customTypeString.isEmpty() ) { + list.append(*it); + } else { + if ( (*it).customTypeString() == customTypeString ) + list.append(*it); + } + } else { + list.append(*it); + } + } + } + return list; +} + +Key Addressee::findKey( const QString &id ) const +{ + Key::List::ConstIterator it; + for( it = mData->keys.begin(); it != mData->keys.end(); ++it ) { + if ( (*it).id() == id ) { + return *it; + } + } + return Key(); +} + +QString Addressee::asString() const +{ + return "Smith, agent Smith..."; +} + +void Addressee::dump() const +{ + return; + kdDebug(5700) << "Addressee {" << endl; + + kdDebug(5700) << " Uid: '" << uid() << "'" << endl; + + kdDebug(5700) << " Name: '" << name() << "'" << endl; + kdDebug(5700) << " FormattedName: '" << formattedName() << "'" << endl; + kdDebug(5700) << " FamilyName: '" << familyName() << "'" << endl; + kdDebug(5700) << " GivenName: '" << givenName() << "'" << endl; + kdDebug(5700) << " AdditionalName: '" << additionalName() << "'" << endl; + kdDebug(5700) << " Prefix: '" << prefix() << "'" << endl; + kdDebug(5700) << " Suffix: '" << suffix() << "'" << endl; + kdDebug(5700) << " NickName: '" << nickName() << "'" << endl; + kdDebug(5700) << " Birthday: '" << birthday().toString() << "'" << endl; + kdDebug(5700) << " Mailer: '" << mailer() << "'" << endl; + kdDebug(5700) << " TimeZone: '" << timeZone().asString() << "'" << endl; + kdDebug(5700) << " Geo: '" << geo().asString() << "'" << endl; + kdDebug(5700) << " Title: '" << title() << "'" << endl; + kdDebug(5700) << " Role: '" << role() << "'" << endl; + kdDebug(5700) << " Organization: '" << organization() << "'" << endl; + kdDebug(5700) << " Note: '" << note() << "'" << endl; + kdDebug(5700) << " ProductId: '" << productId() << "'" << endl; + kdDebug(5700) << " Revision: '" << revision().toString() << "'" << endl; + kdDebug(5700) << " SortString: '" << sortString() << "'" << endl; + kdDebug(5700) << " Url: '" << url().url() << "'" << endl; + kdDebug(5700) << " Secrecy: '" << secrecy().asString() << "'" << endl; + kdDebug(5700) << " Logo: '" << logo().asString() << "'" << endl; + kdDebug(5700) << " Photo: '" << photo().asString() << "'" << endl; + kdDebug(5700) << " Sound: '" << sound().asString() << "'" << endl; + kdDebug(5700) << " Agent: '" << agent().asString() << "'" << endl; + + kdDebug(5700) << " Emails {" << endl; + QStringList e = emails(); + QStringList::ConstIterator it; + for( it = e.begin(); it != e.end(); ++it ) { + kdDebug(5700) << " " << (*it) << endl; + } + kdDebug(5700) << " }" << endl; + + kdDebug(5700) << " PhoneNumbers {" << endl; + PhoneNumber::List p = phoneNumbers(); + PhoneNumber::List::ConstIterator it2; + for( it2 = p.begin(); it2 != p.end(); ++it2 ) { + kdDebug(5700) << " Type: " << int((*it2).type()) << " Number: " << (*it2).number() << endl; + } + kdDebug(5700) << " }" << endl; + + Address::List a = addresses(); + Address::List::ConstIterator it3; + for( it3 = a.begin(); it3 != a.end(); ++it3 ) { + (*it3).dump(); + } + + kdDebug(5700) << " Keys {" << endl; + Key::List k = keys(); + Key::List::ConstIterator it4; + for( it4 = k.begin(); it4 != k.end(); ++it4 ) { + kdDebug(5700) << " Type: " << int((*it4).type()) << + " Key: " << (*it4).textData() << + " CustomString: " << (*it4).customTypeString() << endl; + } + kdDebug(5700) << " }" << endl; + + kdDebug(5700) << "}" << endl; +} + + +void Addressee::insertAddress( const Address &address ) +{ + detach(); + mData->empty = false; + + Address::List::Iterator it; + for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) { + if ( (*it).id() == address.id() ) { + *it = address; + return; + } + } + mData->addresses.append( address ); +} + +void Addressee::removeAddress( const Address &address ) +{ + detach(); + + Address::List::Iterator it; + for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) { + if ( (*it).id() == address.id() ) { + mData->addresses.remove( it ); + return; + } + } +} + +Address Addressee::address( int type ) const +{ + Address address( type ); + Address::List::ConstIterator it; + for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) { + if ( matchBinaryPattern( (*it).type(), type ) ) { + if ( (*it).type() & Address::Pref ) + return (*it); + else if ( address.isEmpty() ) + address = (*it); + } + } + + return address; +} + +Address::List Addressee::addresses() const +{ + return mData->addresses; +} + +Address::List Addressee::addresses( int type ) const +{ + Address::List list; + + Address::List::ConstIterator it; + for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) { + if ( matchBinaryPattern( (*it).type(), type ) ) { + list.append( *it ); + } + } + + return list; +} + +Address Addressee::findAddress( const QString &id ) const +{ + Address::List::ConstIterator it; + for( it = mData->addresses.begin(); it != mData->addresses.end(); ++it ) { + if ( (*it).id() == id ) { + return *it; + } + } + return Address(); +} + +void Addressee::insertCategory( const QString &c ) +{ + detach(); + mData->empty = false; + + if ( mData->categories.contains( c ) ) return; + + mData->categories.append( c ); +} + +void Addressee::removeCategory( const QString &c ) +{ + detach(); + + QStringList::Iterator it = mData->categories.find( c ); + if ( it == mData->categories.end() ) return; + + mData->categories.remove( it ); +} + +bool Addressee::hasCategory( const QString &c ) const +{ + return ( mData->categories.contains( c ) ); +} + +void Addressee::setCategories( const QStringList &c ) +{ + detach(); + mData->empty = false; + + mData->categories = c; +} + +QStringList Addressee::categories() const +{ + return mData->categories; +} + +void Addressee::insertCustom( const QString &app, const QString &name, + const QString &value ) +{ + if ( value.isNull() || name.isEmpty() || app.isEmpty() ) return; + + detach(); + mData->empty = false; + + QString qualifiedName = app + "-" + name + ":"; + + QStringList::Iterator it; + for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) { + if ( (*it).startsWith( qualifiedName ) ) { + (*it) = qualifiedName + value; + return; + } + } + + mData->custom.append( qualifiedName + value ); +} + +void Addressee::removeCustom( const QString &app, const QString &name) +{ + detach(); + + QString qualifiedName = app + "-" + name + ":"; + + QStringList::Iterator it; + for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) { + if ( (*it).startsWith( qualifiedName ) ) { + mData->custom.remove( it ); + return; + } + } +} + +QString Addressee::custom( const QString &app, const QString &name ) const +{ + QString qualifiedName = app + "-" + name + ":"; + QString value; + + QStringList::ConstIterator it; + for( it = mData->custom.begin(); it != mData->custom.end(); ++it ) { + if ( (*it).startsWith( qualifiedName ) ) { + value = (*it).mid( (*it).find( ":" ) + 1 ); + break; + } + } + + return value; +} + +void Addressee::setCustoms( const QStringList &l ) +{ + detach(); + mData->empty = false; + + mData->custom = l; +} + +QStringList Addressee::customs() const +{ + return mData->custom; +} + +void Addressee::parseEmailAddress( const QString &rawEmail, QString &fullName, + QString &email) +{ + int startPos, endPos, len; + QString partA, partB, result; + char endCh = '>'; + + startPos = rawEmail.find('<'); + if (startPos < 0) + { + startPos = rawEmail.find('('); + endCh = ')'; + } + if (startPos < 0) + { + // We couldn't find any separators, so we assume the whole string + // is the email address + email = rawEmail; + fullName = ""; + } + else + { + // We have a start position, try to find an end + endPos = rawEmail.find(endCh, startPos+1); + + if (endPos < 0) + { + // We couldn't find the end of the email address. We can only + // assume the entire string is the email address. + email = rawEmail; + fullName = ""; + } + else + { + // We have a start and end to the email address + + // Grab the name part + fullName = rawEmail.left(startPos).stripWhiteSpace(); + + // grab the email part + email = rawEmail.mid(startPos+1, endPos-startPos-1).stripWhiteSpace(); + + // Check that we do not have any extra characters on the end of the + // strings + len = fullName.length(); + if (fullName[0]=='"' && fullName[len-1]=='"') + fullName = fullName.mid(1, len-2); + else if (fullName[0]=='<' && fullName[len-1]=='>') + fullName = fullName.mid(1, len-2); + else if (fullName[0]=='(' && fullName[len-1]==')') + fullName = fullName.mid(1, len-2); + } + } +} + +void Addressee::setResource( Resource *resource ) +{ + detach(); + mData->resource = resource; +} + +Resource *Addressee::resource() const +{ + return mData->resource; +} + +void Addressee::setChanged( bool value ) +{ + detach(); + mData->changed = value; +} + +bool Addressee::changed() const +{ + return mData->changed; +} + +QDataStream &KABC::operator<<( QDataStream &s, const Addressee &a ) +{ + if (!a.mData) return s; + + s << a.uid(); + + s << a.mData->name; + s << a.mData->formattedName; + s << a.mData->familyName; + s << a.mData->givenName; + s << a.mData->additionalName; + s << a.mData->prefix; + s << a.mData->suffix; + s << a.mData->nickName; + s << a.mData->birthday; + s << a.mData->mailer; + s << a.mData->timeZone; + s << a.mData->geo; + s << a.mData->title; + s << a.mData->role; + s << a.mData->organization; + s << a.mData->note; + s << a.mData->productId; + s << a.mData->revision; + s << a.mData->sortString; + s << a.mData->url; + s << a.mData->secrecy; + s << a.mData->logo; + s << a.mData->photo; + s << a.mData->sound; + s << a.mData->agent; + s << a.mData->phoneNumbers; + s << a.mData->addresses; + s << a.mData->emails; + s << a.mData->categories; + s << a.mData->custom; + s << a.mData->keys; + return s; +} + +QDataStream &KABC::operator>>( QDataStream &s, Addressee &a ) +{ + if (!a.mData) return s; + + s >> a.mData->uid; + + s >> a.mData->name; + s >> a.mData->formattedName; + s >> a.mData->familyName; + s >> a.mData->givenName; + s >> a.mData->additionalName; + s >> a.mData->prefix; + s >> a.mData->suffix; + s >> a.mData->nickName; + s >> a.mData->birthday; + s >> a.mData->mailer; + s >> a.mData->timeZone; + s >> a.mData->geo; + s >> a.mData->title; + s >> a.mData->role; + s >> a.mData->organization; + s >> a.mData->note; + s >> a.mData->productId; + s >> a.mData->revision; + s >> a.mData->sortString; + s >> a.mData->url; + s >> a.mData->secrecy; + s >> a.mData->logo; + s >> a.mData->photo; + s >> a.mData->sound; + s >> a.mData->agent; + s >> a.mData->phoneNumbers; + s >> a.mData->addresses; + s >> a.mData->emails; + s >> a.mData->categories; + s >> a.mData->custom; + s >> a.mData->keys; + + a.mData->empty = false; + + return s; +} + +bool matchBinaryPattern( int value, int pattern ) +{ + /** + We want to match all telephonnumbers/addresses which have the bits in the + pattern set. More are allowed. + if pattern == 0 we have a special handling, then we want only those with + exactly no bit set. + */ + if ( pattern == 0 ) + return ( value == 0 ); + else + return ( pattern == ( pattern & value ) ); +} diff --git a/kabc/addressee.h b/kabc/addressee.h new file mode 100644 index 0000000..ee98e03 --- a/dev/null +++ b/kabc/addressee.h @@ -0,0 +1,817 @@ +/*** Warning! This file has been generated by the script makeaddressee ***/ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_ADDRESSEE_H +#define KABC_ADDRESSEE_H + +#include <qdatetime.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +#include <ksharedptr.h> +#include <kurl.h> + +#include "address.h" +#include "agent.h" +#include "geo.h" +#include "key.h" +#include "phonenumber.h" +#include "picture.h" +#include "secrecy.h" +#include "sound.h" +#include "timezone.h" + +namespace KABC { + +class Resource; + +/** + @short address book entry + + This class represents an entry in the address book. + + The data of this class is implicitly shared. You can pass this class by value. + + If you need the name of a field for presenting it to the user you should use + the functions ending in Label(). They return a translated string which can be + used as label for the corresponding field. + + About the name fields: + + givenName() is the first name and familyName() the last name. In some + countries the family name comes first, that's the reason for the + naming. formattedName() is the full name with the correct formatting. + It is used as an override, when the correct formatting can't be generated + from the other name fields automatically. + + realName() returns a fully formatted name(). It uses formattedName, if set, + otherwise it constucts the name from the name fields. As fallback, if + nothing else is set it uses name(). + + name() is the NAME type of RFC2426. It can be used as internal name for the + data enty, but shouldn't be used for displaying the data to the user. + */ +class Addressee +{ + friend QDataStream &operator<<( QDataStream &, const Addressee & ); + friend QDataStream &operator>>( QDataStream &, Addressee & ); + + public: + typedef QValueList<Addressee> List; + + /** + Construct an empty address book entry. + */ + Addressee(); + ~Addressee(); + + Addressee( const Addressee & ); + Addressee &operator=( const Addressee & ); + + bool operator==( const Addressee & ) const; + bool operator!=( const Addressee & ) const; + + /** + Return, if the address book entry is empty. + */ + bool isEmpty() const; + + /** + Set unique identifier. + */ + void setUid( const QString &uid ); + /** + Return unique identifier. + */ + QString uid() const; + /** + Return translated label for uid field. + */ + static QString uidLabel(); + + /** + Set name. + */ + void setName( const QString &name ); + /** + Return name. + */ + QString name() const; + /** + Return translated label for name field. + */ + static QString nameLabel(); + + /** + Set formatted name. + */ + void setFormattedName( const QString &formattedName ); + /** + Return formatted name. + */ + QString formattedName() const; + /** + Return translated label for formattedName field. + */ + static QString formattedNameLabel(); + + /** + Set family name. + */ + void setFamilyName( const QString &familyName ); + /** + Return family name. + */ + QString familyName() const; + /** + Return translated label for familyName field. + */ + static QString familyNameLabel(); + + /** + Set given name. + */ + void setGivenName( const QString &givenName ); + /** + Return given name. + */ + QString givenName() const; + /** + Return translated label for givenName field. + */ + static QString givenNameLabel(); + + /** + Set additional names. + */ + void setAdditionalName( const QString &additionalName ); + /** + Return additional names. + */ + QString additionalName() const; + /** + Return translated label for additionalName field. + */ + static QString additionalNameLabel(); + + /** + Set honorific prefixes. + */ + void setPrefix( const QString &prefix ); + /** + Return honorific prefixes. + */ + QString prefix() const; + /** + Return translated label for prefix field. + */ + static QString prefixLabel(); + + /** + Set honorific suffixes. + */ + void setSuffix( const QString &suffix ); + /** + Return honorific suffixes. + */ + QString suffix() const; + /** + Return translated label for suffix field. + */ + static QString suffixLabel(); + + /** + Set nick name. + */ + void setNickName( const QString &nickName ); + /** + Return nick name. + */ + QString nickName() const; + /** + Return translated label for nickName field. + */ + static QString nickNameLabel(); + + /** + Set birthday. + */ + void setBirthday( const QDateTime &birthday ); + /** + Return birthday. + */ + QDateTime birthday() const; + /** + Return translated label for birthday field. + */ + static QString birthdayLabel(); + + /** + Return translated label for homeAddressStreet field. + */ + static QString homeAddressStreetLabel(); + + /** + Return translated label for homeAddressLocality field. + */ + static QString homeAddressLocalityLabel(); + + /** + Return translated label for homeAddressRegion field. + */ + static QString homeAddressRegionLabel(); + + /** + Return translated label for homeAddressPostalCode field. + */ + static QString homeAddressPostalCodeLabel(); + + /** + Return translated label for homeAddressCountry field. + */ + static QString homeAddressCountryLabel(); + + /** + Return translated label for homeAddressLabel field. + */ + static QString homeAddressLabelLabel(); + + /** + Return translated label for businessAddressStreet field. + */ + static QString businessAddressStreetLabel(); + + /** + Return translated label for businessAddressLocality field. + */ + static QString businessAddressLocalityLabel(); + + /** + Return translated label for businessAddressRegion field. + */ + static QString businessAddressRegionLabel(); + + /** + Return translated label for businessAddressPostalCode field. + */ + static QString businessAddressPostalCodeLabel(); + + /** + Return translated label for businessAddressCountry field. + */ + static QString businessAddressCountryLabel(); + + /** + Return translated label for businessAddressLabel field. + */ + static QString businessAddressLabelLabel(); + + /** + Return translated label for homePhone field. + */ + static QString homePhoneLabel(); + + /** + Return translated label for businessPhone field. + */ + static QString businessPhoneLabel(); + + /** + Return translated label for mobilePhone field. + */ + static QString mobilePhoneLabel(); + + /** + Return translated label for homeFax field. + */ + static QString homeFaxLabel(); + + /** + Return translated label for businessFax field. + */ + static QString businessFaxLabel(); + + /** + Return translated label for carPhone field. + */ + static QString carPhoneLabel(); + + /** + Return translated label for isdn field. + */ + static QString isdnLabel(); + + /** + Return translated label for pager field. + */ + static QString pagerLabel(); + + /** + Return translated label for email field. + */ + static QString emailLabel(); + + /** + Set mail client. + */ + void setMailer( const QString &mailer ); + /** + Return mail client. + */ + QString mailer() const; + /** + Return translated label for mailer field. + */ + static QString mailerLabel(); + + /** + Set time zone. + */ + void setTimeZone( const TimeZone &timeZone ); + /** + Return time zone. + */ + TimeZone timeZone() const; + /** + Return translated label for timeZone field. + */ + static QString timeZoneLabel(); + + /** + Set geographic position. + */ + void setGeo( const Geo &geo ); + /** + Return geographic position. + */ + Geo geo() const; + /** + Return translated label for geo field. + */ + static QString geoLabel(); + + /** + Set title. + */ + void setTitle( const QString &title ); + /** + Return title. + */ + QString title() const; + /** + Return translated label for title field. + */ + static QString titleLabel(); + + /** + Set role. + */ + void setRole( const QString &role ); + /** + Return role. + */ + QString role() const; + /** + Return translated label for role field. + */ + static QString roleLabel(); + + /** + Set organization. + */ + void setOrganization( const QString &organization ); + /** + Return organization. + */ + QString organization() const; + /** + Return translated label for organization field. + */ + static QString organizationLabel(); + + /** + Set note. + */ + void setNote( const QString ¬e ); + /** + Return note. + */ + QString note() const; + /** + Return translated label for note field. + */ + static QString noteLabel(); + + /** + Set product identifier. + */ + void setProductId( const QString &productId ); + /** + Return product identifier. + */ + QString productId() const; + /** + Return translated label for productId field. + */ + static QString productIdLabel(); + + /** + Set revision date. + */ + void setRevision( const QDateTime &revision ); + /** + Return revision date. + */ + QDateTime revision() const; + /** + Return translated label for revision field. + */ + static QString revisionLabel(); + + /** + Set sort string. + */ + void setSortString( const QString &sortString ); + /** + Return sort string. + */ + QString sortString() const; + /** + Return translated label for sortString field. + */ + static QString sortStringLabel(); + + /** + Set URL. + */ + void setUrl( const KURL &url ); + /** + Return URL. + */ + KURL url() const; + /** + Return translated label for url field. + */ + static QString urlLabel(); + + /** + Set security class. + */ + void setSecrecy( const Secrecy &secrecy ); + /** + Return security class. + */ + Secrecy secrecy() const; + /** + Return translated label for secrecy field. + */ + static QString secrecyLabel(); + + /** + Set logo. + */ + void setLogo( const Picture &logo ); + /** + Return logo. + */ + Picture logo() const; + /** + Return translated label for logo field. + */ + static QString logoLabel(); + + /** + Set photo. + */ + void setPhoto( const Picture &photo ); + /** + Return photo. + */ + Picture photo() const; + /** + Return translated label for photo field. + */ + static QString photoLabel(); + + /** + Set sound. + */ + void setSound( const Sound &sound ); + /** + Return sound. + */ + Sound sound() const; + /** + Return translated label for sound field. + */ + static QString soundLabel(); + + /** + Set agent. + */ + void setAgent( const Agent &agent ); + /** + Return agent. + */ + Agent agent() const; + /** + Return translated label for agent field. + */ + static QString agentLabel(); + + /** + Set name fields by parsing the given string and trying to associate the + parts of the string with according fields. This function should probably + be a bit more clever. + */ + void setNameFromString( const QString & ); + + /** + Return the name of the addressee. This is calculated from all the name + fields. + */ + QString realName() const; + + /** + Return the name that consists of all name parts. + */ + QString assembledName() const; + + /** + Return email address including real name. + + @param email Email address to be used to construct the full email string. + If this is QString::null the preferred email address is used. + */ + QString fullEmail( const QString &email=QString::null ) const; + + /** + Insert an email address. If the email address already exists in this + addressee it is not duplicated. + + @param email Email address + @param preferred Set to true, if this is the preferred email address of + the addressee. + */ + void insertEmail( const QString &email, bool preferred=false ); + + /** + Remove email address. If the email address doesn't exist, nothing happens. + */ + void removeEmail( const QString &email ); + + /** + Return preferred email address. This is the first email address or the + last one added with @ref insertEmail() with a set preferred parameter. + */ + QString preferredEmail() const; + + /** + Return list of all email addresses. + */ + QStringList emails() const; + + /** + Set the emails to @param. + The first email address gets the preferred one! + @param list The list of email addresses. + */ + void setEmails( const QStringList& list); + + /** + Insert a phone number. If a phone number with the same id already exists + in this addressee it is not duplicated. + */ + void insertPhoneNumber( const PhoneNumber &phoneNumber ); + + /** + Remove phone number. If no phone number with the given id exists for this + addresse nothing happens. + */ + void removePhoneNumber( const PhoneNumber &phoneNumber ); + + /** + Return phone number, which matches the given type. + */ + PhoneNumber phoneNumber( int type ) const; + + /** + Return list of all phone numbers. + */ + PhoneNumber::List phoneNumbers() const; + + /** + Return list of phone numbers with a special type. + */ + PhoneNumber::List phoneNumbers( int type ) const; + + /** + Return phone number with the given id. + */ + PhoneNumber findPhoneNumber( const QString &id ) const; + + /** + Insert a key. If a key with the same id already exists + in this addressee it is not duplicated. + */ + void insertKey( const Key &key ); + + /** + Remove a key. If no key with the given id exists for this + addresse nothing happens. + */ + void removeKey( const Key &key ); + + /** + Return key, which matches the given type. + If @p type == Key::Custom you can specify a string + that should match. If you leave the string empty, the first + key with a custom value is returned. + */ + Key key( int type, QString customTypeString = QString::null ) const; + + /** + Return list of all keys. + */ + Key::List keys() const; + + /** + Set the list of keys + @param keys The keys to be set. + */ + void setKeys( const Key::List& keys); + + /** + Return list of keys with a special type. + If @p type == Key::Custom you can specify a string + that should match. If you leave the string empty, all custom + keys will be returned. + */ + Key::List keys( int type, QString customTypeString = QString::null ) const; + + /** + Return key with the given id. + */ + Key findKey( const QString &id ) const; + + /** + Insert an address. If an address with the same id already exists + in this addressee it is not duplicated. + */ + void insertAddress( const Address &address ); + + /** + Remove address. If no address with the given id exists for this + addresse nothing happens. + */ + void removeAddress( const Address &address ); + + /** + Return address, which matches the given type. + */ + Address address( int type ) const; + + /** + Return list of all addresses. + */ + Address::List addresses() const; + + /** + Return list of addresses with a special type. + */ + Address::List addresses( int type ) const; + + /** + Return address with the given id. + */ + Address findAddress( const QString &id ) const; + + /** + Insert category. If the category already exists it is not duplicated. + */ + void insertCategory( const QString & ); + + /** + Remove category. + */ + void removeCategory( const QString & ); + + /** + Return, if addressee has the given category. + */ + bool hasCategory( const QString & ) const; + + /** + Set categories to given value. + */ + void setCategories( const QStringList & ); + + /** + Return list of all set categories. + */ + QStringList categories() const; + + /** + Insert custom entry. The entry is identified by the name of the inserting + application and a unique name. If an entry with the given app and name + already exists its value is replaced with the new given value. + */ + void insertCustom( const QString &app, const QString &name, + const QString &value ); + + /** + Remove custom entry. + */ + void removeCustom( const QString &app, const QString &name ); + + /** + Return value of custom entry, identified by app and entry name. + */ + QString custom( const QString &app, const QString &name ) const; + + /** + Set all custom entries. + */ + void setCustoms( const QStringList & ); + + /** + Return list of all custom entries. + */ + QStringList customs() const; + + /** + Parse full email address. The result is given back in fullName and email. + */ + static void parseEmailAddress( const QString &rawEmail, QString &fullName, + QString &email ); + + /** + Debug output. + */ + void dump() const; + + /** + Returns string representation of the addressee. + */ + QString asString() const; + + /** + Set resource where the addressee is from. + */ + void setResource( Resource *resource ); + + /** + Return pointer to resource. + */ + Resource *resource() const; + + /** + Mark addressee as changed. + */ + void setChanged( bool value ); + + /** + Return whether the addressee is changed. + */ + bool changed() const; + + private: + Addressee copy(); + void detach(); + + struct AddresseeData; + mutable KSharedPtr<AddresseeData> mData; +}; + +QDataStream &operator<<( QDataStream &, const Addressee & ); +QDataStream &operator>>( QDataStream &, Addressee & ); + +} + +#endif diff --git a/kabc/addresseedialog.cpp b/kabc/addresseedialog.cpp new file mode 100644 index 0000000..033e857 --- a/dev/null +++ b/kabc/addresseedialog.cpp @@ -0,0 +1,264 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qlayout.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qapplication.h> +#include <qregexp.h> + +#include <klocale.h> +#include <kdebug.h> +#include <kglobalsettings.h> + +#include "stdaddressbook.h" + +#include "addresseedialog.h" +//#include "addresseedialog.moc" + +using namespace KABC; + +AddresseeItem::AddresseeItem( QListView *parent, const Addressee &addressee ) : + QListViewItem( parent ), + mAddressee( addressee ) +{ + setText( Name, addressee.realName() ); + setText( Email, addressee.preferredEmail() ); +} + +QString AddresseeItem::key( int column, bool ) const +{ + /* LR + if (column == Email) { + QString value = text(Email); + QRegExp emailRe("<\\S*>"); + int match = emailRe.search(value); + if (match > -1) + value = value.mid(match + 1, emailRe.matchedLength() - 2); + + return value.lower(); + } + */ + return text(column).lower(); +} + +AddresseeDialog::AddresseeDialog( QWidget *parent, bool multiple ) : + KDialogBase( KDialogBase::Plain, i18n("Select Addressee"), + Ok|Cancel, Ok, parent ), mMultiple( multiple ) +{ + QWidget *topWidget = plainPage(); + + QBoxLayout *topLayout = new QHBoxLayout( topWidget ); + QBoxLayout *listLayout = new QVBoxLayout; + topLayout->addLayout( listLayout ); + + mAddresseeList = new KListView( topWidget ); + mAddresseeList->addColumn( i18n("Name") ); + mAddresseeList->addColumn( i18n("Email") ); + mAddresseeList->setAllColumnsShowFocus( true ); + mAddresseeList->setFullWidth( true ); + listLayout->addWidget( mAddresseeList ); + connect( mAddresseeList, SIGNAL( doubleClicked( QListViewItem * ) ), + SLOT( slotOk() ) ); + connect( mAddresseeList, SIGNAL( selectionChanged( QListViewItem * ) ), + SLOT( updateEdit( QListViewItem * ) ) ); + + mAddresseeEdit = new KLineEdit( topWidget ); + //mAddresseeEdit->setCompletionMode( KGlobalSettings::CompletionAuto ); + // connect( mAddresseeEdit->completionObject(), SIGNAL( match( const QString & ) ), + // SLOT( selectItem( const QString & ) ) ); + mAddresseeEdit->setFocus(); + //mAddresseeEdit->completionObject()->setIgnoreCase( true ); + listLayout->addWidget( mAddresseeEdit ); + + //setInitialSize( QSize( 450, 300 ) ); + + if ( mMultiple ) { + QBoxLayout *selectedLayout = new QVBoxLayout; + topLayout->addLayout( selectedLayout ); + topLayout->setSpacing( spacingHint() ); + + QGroupBox *selectedGroup = new QGroupBox( 1, Horizontal, i18n("Selected"), + topWidget ); + selectedLayout->addWidget( selectedGroup ); + + mSelectedList = new KListView( selectedGroup ); + mSelectedList->addColumn( i18n("Name") ); + mSelectedList->addColumn( i18n("Email") ); + mSelectedList->setAllColumnsShowFocus( true ); + mSelectedList->setFullWidth( true ); + connect( mSelectedList, SIGNAL( doubleClicked( QListViewItem * ) ), + SLOT( removeSelected() ) ); + + QPushButton *unselectButton = new QPushButton( i18n("Unselect"), selectedGroup ); + connect ( unselectButton, SIGNAL( clicked() ), SLOT( removeSelected() ) ); + + connect( mAddresseeList, SIGNAL( clicked( QListViewItem * ) ), + SLOT( addSelected( QListViewItem * ) ) ); + + // setInitialSize( QSize( 650, 350 ) ); + } + + mAddressBook = StdAddressBook::self( true ); + connect( mAddressBook, SIGNAL( addressBookChanged( AddressBook* ) ), + SLOT( addressBookChanged() ) ); + connect( mAddressBook, SIGNAL( loadingFinished( Resource* ) ), + SLOT( addressBookChanged() ) ); + + loadAddressBook(); +} + +AddresseeDialog::~AddresseeDialog() +{ +} + +void AddresseeDialog::loadAddressBook() +{ + mAddresseeList->clear(); + mItemDict.clear(); + //mAddresseeEdit->completionObject()->clear(); + + AddressBook::Iterator it; + for( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { + AddresseeItem *item = new AddresseeItem( mAddresseeList, (*it) ); + addCompletionItem( (*it).realName(), item ); + addCompletionItem( (*it).preferredEmail(), item ); + } +} + +void AddresseeDialog::addCompletionItem( const QString &str, QListViewItem *item ) +{ + if ( str.isEmpty() ) return; + + mItemDict.insert( str, item ); + //mAddresseeEdit->completionObject()->addItem( str ); +} + +void AddresseeDialog::selectItem( const QString &str ) +{ + if ( str.isEmpty() ) return; + + QListViewItem *item = mItemDict.find( str ); + if ( item ) { + mAddresseeList->blockSignals( true ); + mAddresseeList->setSelected( item, true ); + mAddresseeList->ensureItemVisible( item ); + mAddresseeList->blockSignals( false ); + } +} + +void AddresseeDialog::updateEdit( QListViewItem *item ) +{ + mAddresseeEdit->setText( item->text( 0 ) ); + mAddresseeEdit->setSelection( 0, item->text( 0 ).length() ); +} + +void AddresseeDialog::addSelected( QListViewItem *item ) +{ + AddresseeItem *addrItem = (AddresseeItem *)( item ); + if ( !addrItem ) return; + + Addressee a = addrItem->addressee(); + + QListViewItem *selectedItem = mSelectedDict.find( a.uid() ); + if ( !selectedItem ) { + selectedItem = new AddresseeItem( mSelectedList, a ); + mSelectedDict.insert( a.uid(), selectedItem ); + } +} + +void AddresseeDialog::removeSelected() +{ + QListViewItem *item = mSelectedList->selectedItem(); + AddresseeItem *addrItem = (AddresseeItem *)( item ); + if ( !addrItem ) return; + + mSelectedDict.remove( addrItem->addressee().uid() ); + delete addrItem; +} + +Addressee AddresseeDialog::addressee() +{ + AddresseeItem *aItem = 0; + + if ( mMultiple ) + aItem = (AddresseeItem *)( mSelectedList->firstChild() ); + else + aItem = (AddresseeItem *)( mAddresseeList->selectedItem() ); + + if (aItem) return aItem->addressee(); + return Addressee(); +} + +Addressee::List AddresseeDialog::addressees() +{ + Addressee::List al; + AddresseeItem *aItem = 0; + + if ( mMultiple ) { + QListViewItem *item = mSelectedList->firstChild(); + while( item ) { + aItem = (AddresseeItem *)( item ); + if ( aItem ) al.append( aItem->addressee() ); + item = item->nextSibling(); + } + } + else + { + aItem = (AddresseeItem *)( mAddresseeList->selectedItem() ); + if (aItem) al.append( aItem->addressee() ); + } + + return al; +} + +Addressee AddresseeDialog::getAddressee( QWidget *parent ) +{ + AddresseeDialog *dlg = new AddresseeDialog( parent ); + Addressee addressee; + int result = dlg->exec(); + + if ( result == QDialog::Accepted ) { + addressee = dlg->addressee(); + } + + delete dlg; + return addressee; +} + +Addressee::List AddresseeDialog::getAddressees( QWidget *parent ) +{ + AddresseeDialog *dlg = new AddresseeDialog( parent, true ); + Addressee::List addressees; + if ( QApplication::desktop()->width() <= 640 ) + dlg->showMaximized(); + int result = dlg->exec(); + if ( result == QDialog::Accepted ) { + addressees = dlg->addressees(); + } + + delete dlg; + return addressees; +} + +void AddresseeDialog::addressBookChanged() +{ + loadAddressBook(); +} diff --git a/kabc/addresseedialog.h b/kabc/addresseedialog.h new file mode 100644 index 0000000..74e7871 --- a/dev/null +++ b/kabc/addresseedialog.h @@ -0,0 +1,160 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KABC_ADDRESSEEDIALOG_H +#define KABC_ADDRESSEEDIALOG_H + +#include <qdict.h> + +#include <kdialogbase.h> +#include <klineedit.h> +#include <klistview.h> + +#include "addressbook.h" + +namespace KABC { + +/** + @short Special ListViewItem, that is used by the AddresseeDialog. +*/ +class AddresseeItem : public QListViewItem +{ + public: + + /** + Type of column + @li @p Name - Name in Addressee + @li @p Email - Email in Addressee + */ + enum columns { Name = 0, Email = 1 }; + + /** + Constructor. + + @param parent The parent listview. + @param addressee The associated addressee. + */ + AddresseeItem( QListView *parent, const Addressee &addressee ); + + /** + Returns the addressee. + */ + Addressee addressee() const { return mAddressee; } + + /** + Method used by QListView to sort the items. + */ + virtual QString key( int column, bool ascending ) const; + + private: + Addressee mAddressee; +}; + +/** + @short Dialog for selecting address book entries. + + This class provides a dialog for selecting entries from the standard KDE + address book. Use the getAddressee() function to open a modal dialog, + returning an address book entry. + + In the dialog you can select an entry from the list with the mouse or type in + the first letters of the name or email address you are searching for. The + entry matching best is automatically selected. Use double click, pressing + return or pressing the ok button to return the selected addressee to the + application. +*/ +class AddresseeDialog : public KDialogBase +{ + Q_OBJECT + + public: + /** + Construct addressbook entry select dialog. + + @param parent parent widget + */ + AddresseeDialog( QWidget *parent=0, bool multiple=false ); + + /** + Destructor. + */ + virtual ~AddresseeDialog(); + + /** + Return the address chosen. + + If it is a multiple select, this will return only the first address chosen + */ + Addressee addressee(); + + /** + Return the list of addresses chosen + */ + Addressee::List addressees(); + + /** + Select a single address book entry. + + Open addressee select dialog and return the entry selected by the user. + If the user doesn't select an entry or presses cancel, the returned + addressee is empty. + */ + static Addressee getAddressee( QWidget *parent ); + + /** + Select multiple address book entries. + + Open addressee select dialog and return the entries selected by the user. + If the user doesn't select an entry or presses cancel, the returned + addressee list is empty. + */ + static Addressee::List getAddressees( QWidget *parent ); + + private slots: + void selectItem( const QString & ); + void updateEdit( QListViewItem *item ); + void addSelected( QListViewItem *item ); + void removeSelected(); + + protected slots: + void addressBookChanged(); + + private: + void loadAddressBook(); + void addCompletionItem( const QString &str, QListViewItem *item ); + + bool mMultiple; + + KListView *mAddresseeList; + KLineEdit *mAddresseeEdit; + + KListView *mSelectedList; + + AddressBook *mAddressBook; + + QDict<QListViewItem> mItemDict; + QDict<QListViewItem> mSelectedDict; + + class AddresseeDialogPrivate; + AddresseeDialogPrivate *d; +}; + +} +#endif diff --git a/kabc/addresseelist.cpp b/kabc/addresseelist.cpp new file mode 100644 index 0000000..097e162 --- a/dev/null +++ b/kabc/addresseelist.cpp @@ -0,0 +1,292 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Jost Schenck <jost@schenck.de> + 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <kdebug.h> +//US +#include <qtl.h> + + +#include "addresseelist.h" +#include "field.h" + +using namespace KABC; + +// +// +// Traits +// +// + +bool SortingTraits::Uid::eq( const Addressee &a1, const Addressee &a2 ) +{ + // locale awareness doesn't make sense sorting ids + return ( QString::compare( a1.uid(), a2.uid() ) == 0 ); +} + +bool SortingTraits::Uid::lt( const Addressee &a1, const Addressee &a2 ) +{ + // locale awareness doesn't make sense sorting ids + return ( QString::compare( a1.uid(), a2.uid() ) < 0 ); +} + +bool SortingTraits::Name::eq( const Addressee &a1, const Addressee &a2 ) +{ +//US QString::localeAwareCompare is not available in my distribution. Redefine it to compare + return ( QString::compare( a1.name(), a2.name() ) == 0 ); +} + +bool SortingTraits::Name::lt( const Addressee &a1, const Addressee &a2 ) +{ +//US QString::localeAwareCompare is not available in my distribution. Redefine it to compare + return ( QString::compare( a1.name(), a2.name() ) < 0 ); +} + +bool SortingTraits::FormattedName::eq( const Addressee &a1, const Addressee &a2 ) +{ +//US QString::localeAwareCompare is not available in my distribution. Redefine it to compare + return ( QString::compare( a1.formattedName(), a2.formattedName() ) == 0 ); +} + +bool SortingTraits::FormattedName::lt( const Addressee &a1, const Addressee &a2 ) +{ +//US QString::localeAwareCompare is not available in my distribution. Redefine it to compare + return ( QString::compare( a1.formattedName(), a2.formattedName() ) < 0 ); +} + +bool SortingTraits::FamilyName::eq( const Addressee &a1, const Addressee &a2 ) +{ +//US QString::localeAwareCompare is not available in my distribution. Redefine it to compare + return ( QString::compare( a1.familyName(), a2.familyName() ) == 0 + && QString::compare( a1.givenName(), a2.givenName() ) == 0 ); +} + +bool SortingTraits::FamilyName::lt( const Addressee &a1, const Addressee &a2 ) +{ +//US QString::localeAwareCompare is not available in my distribution. Redefine it to compare + int family = QString::compare( a1.familyName(), a2.familyName() ); + if ( 0 == family ) { + return ( QString::compare( a1.givenName(), a2.givenName() ) < 0 ); + } else { + return family < 0; + } +} + +bool SortingTraits::GivenName::eq( const Addressee &a1, const Addressee &a2 ) +{ +//US QString::localeAwareCompare is not available in my distribution. Redefine it to compare + return ( QString::compare( a1.givenName(), a2.givenName() ) == 0 + && QString::compare( a1.familyName(), a2.familyName() ) == 0 ); +} + +bool SortingTraits::GivenName::lt( const Addressee &a1, const Addressee &a2 ) +{ +//US QString::localeAwareCompare is not available in my distribution. Redefine it to compare + int given = QString::compare( a1.givenName(), a2.givenName() ); + if ( 0 == given ) { + return ( QString::compare( a1.familyName(), a2.familyName() ) < 0 ); + } else { + return given < 0; + } +} + +// +// +// AddresseeList +// +// + +AddresseeList::AddresseeList() + : QValueList<Addressee>() +{ + mReverseSorting = false; + mActiveSortingCriterion = FormattedName; + mActiveSortingField = 0; +} + +AddresseeList::~AddresseeList() +{ +} + +AddresseeList::AddresseeList( const AddresseeList &l ) + : QValueList<Addressee>( l ) +{ + mReverseSorting = l.reverseSorting(); + mActiveSortingCriterion = l.sortingCriterion(); +} + +AddresseeList::AddresseeList( const QValueList<Addressee> &l ) + : QValueList<Addressee>( l ) +{ + mReverseSorting = false; +} + +void AddresseeList::dump() const +{ + kdDebug(5700) << "AddresseeList {" << endl; + kdDebug(5700) << "reverse order: " << ( mReverseSorting ? "true" : "false" ) << endl; + + QString crit; + if ( Uid == mActiveSortingCriterion ) { + crit = "Uid"; + } else if ( Name == mActiveSortingCriterion ) { + crit = "Name"; + } else if ( FormattedName == mActiveSortingCriterion ) { + crit = "FormattedName"; + } else if ( FamilyName == mActiveSortingCriterion ) { + crit = "FamilyName"; + } else if ( GivenName == mActiveSortingCriterion ) { + crit = "GivenName"; + } else { + crit = "unknown -- update dump method"; + } + + kdDebug(5700) << "sorting criterion: " << crit << endl; + +//US +//US for ( const_iterator it = begin(); it != end(); ++it ) + for ( ConstIterator it = begin(); it != end(); ++it ) + (*it).dump(); + + kdDebug(5700) << "}" << endl; +} + +void AddresseeList::sortBy( SortingCriterion c ) +{ + mActiveSortingCriterion = c; + if ( Uid == c ) { + sortByTrait<SortingTraits::Uid>(); + } else if ( Name == c ) { + sortByTrait<SortingTraits::Name>(); + } else if ( FormattedName == c ) { + sortByTrait<SortingTraits::FormattedName>(); + } else if ( FamilyName == c ) { + sortByTrait<SortingTraits::FamilyName>(); + } else if ( GivenName==c ) { + sortByTrait<SortingTraits::GivenName>(); + } else { + kdError(5700) << "AddresseeList sorting criterion passed for which a trait is not known. No sorting done." << endl; + } +} + +void AddresseeList::sort() +{ + sortBy( mActiveSortingCriterion ); +} + +template<class Trait> +void AddresseeList::sortByTrait() +{ + // FIXME: better sorting algorithm, bubblesort is not acceptable for larger lists. + // + // for i := 1 to n - 1 + // do for j := 1 to n - i + // do if A[j] > A[j+1] + // then temp := A[j] + // A[j] := A[j + 1] + // A[j + 1 ] := temp + +//US iterator i1 = begin(); + Iterator i1 = begin(); +//US iterator endIt = end(); + Iterator endIt = end(); + --endIt; + if ( i1 == endIt ) // don't need sorting + return; + +//US iterator i2 = endIt; + Iterator i2 = endIt; + while( i1 != endIt ) { +//US iterator j1 = begin(); + Iterator j1 = begin(); +//US iterator j2 = j1; + Iterator j2 = j1; + ++j2; + while( j1 != i2 ) { + if ( !mReverseSorting && Trait::lt( *j2, *j1 ) + || mReverseSorting && Trait::lt( *j1, *j2 ) ) { + qSwap( *j1, *j2 ); + } + ++j1; + ++j2; + } + ++i1; + --i2; + } +} + +void AddresseeList::sortByField( Field *field ) +{ + if ( field ) + mActiveSortingField = field; + + if ( !mActiveSortingField ) { + kdWarning(5700) << "sortByField called with no active sort field" << endl; + return; + } + + if ( count() == 0 ) + return; + + quickSortByField( 0, count() - 1 ); +} + +void AddresseeList::quickSortByField( int left, int right ) +{ + int i = left; + int j = right; + int mid = ( left + right ) / 2; + +//US iterator x = at( mid ); + ConstIterator x = at( mid ); + + do { + if ( !mReverseSorting ) { + //US QString::localeAwareCompare was not available. Used compare instead. + while ( QString::compare( mActiveSortingField->value( *at( i ) ).upper(), mActiveSortingField->value( *x ).upper() ) < 0 ) + i++; + //US QString::localeAwareCompare was not available. Used compare instead. + while ( QString::compare( mActiveSortingField->value( *at( j ) ).upper(), mActiveSortingField->value( *x ).upper() ) > 0 ) + j--; + } else { + //US QString::localeAwareCompare was not available. Used compare instead. + while ( QString::compare( mActiveSortingField->value( *at( i ) ).upper(), mActiveSortingField->value( *x ).upper() ) > 0 ) + i++; + //US QString::localeAwareCompare was not available. Used compare instead. + while ( QString::compare( mActiveSortingField->value( *at( j ) ).upper(), mActiveSortingField->value( *x ).upper() ) < 0 ) + j--; + } + if ( i <= j ) { + qSwap( *at( i ), *at( j ) ); + i++; + j--; + } + } while ( i <= j ); + + if ( left < j ) quickSortByField( left, j ); + if ( right > i ) quickSortByField( i, right ); +} diff --git a/kabc/addresseelist.h b/kabc/addresseelist.h new file mode 100644 index 0000000..2df252c --- a/dev/null +++ b/kabc/addresseelist.h @@ -0,0 +1,218 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Jost Schenck <jost@schenck.de> + 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_ADDRESSEELIST_H +#define KABC_ADDRESSEELIST_H + +#include <qvaluelist.h> + +#include "addressee.h" + +namespace KABC { + +class Field; + +/** + * Each trait must implement one static function for equality, one for "less + * than". Class name should be the field name. A trait does not necessarily + * have to stick to just one field: a trait sorting by family name can e.g. + * sort addressees with equal family name by given name. + * + * If you want to implement reverse sorting, you do not have to write another + * trait, as AddresseeList takes care of that. + */ +namespace SortingTraits +{ + +class Uid +{ + public: + static bool eq( const Addressee &, const Addressee & ); + static bool lt( const Addressee &, const Addressee & ); +}; + +class Name +{ + public: + static bool eq( const Addressee &, const Addressee & ); + static bool lt( const Addressee &, const Addressee & ); +}; + +class FormattedName +{ + public: + static bool eq( const Addressee &, const Addressee & ); + static bool lt( const Addressee &, const Addressee & ); +}; + +class FamilyName // fallback to given name +{ + public: + static bool eq( const Addressee &, const Addressee & ); + static bool lt( const Addressee &, const Addressee & ); +}; + +class GivenName // fallback to family name +{ + public: + static bool eq( const Addressee &, const Addressee & ); + static bool lt( const Addressee &, const Addressee & ); +}; + +} + +/** + * Addressee attribute used for sorting. + */ +typedef enum { Uid, Name, FormattedName, FamilyName, GivenName } SortingCriterion; + +/** + * @short a QValueList of Addressee, with sorting functionality + * + * This class extends the functionality of QValueList with + * sorting methods specific to the Addressee class. It can be used + * just like any other QValueList but is no template class. + * + * An AddresseeList does not automatically keep sorted when addressees + * are added or removed or the sorting order is changed, as this would + * slow down larger operations by sorting after every step. So after + * such operations you have to call {@link #sort} or {@link #sortBy} to + * create a defined order again. + * + * Iterator usage is inherited by QValueList and extensively documented + * there. Please remember that the state of an iterator is undefined + * after any sorting operation. + * + * For the enumeration Type SortingCriterion, which specifies the + * field by the collection will be sorted, the following values exist: + * Uid, Name, FormattedName, FamilyName, GivenName. + * + * @author Jost Schenck jost@schenck.de + */ +class AddresseeList : public QValueList<Addressee> +{ + public: + AddresseeList(); + ~AddresseeList(); + AddresseeList( const AddresseeList & ); + AddresseeList( const QValueList<Addressee> & ); + + /** + * Debug output. + */ + void dump() const; + + /** + * Determines the direction of sorting. On change, the list + * will <em>not</em> automatically be resorted. + * @param r <tt>true</tt> if sorting should be done reverse, <tt>false</tt> otherwise + */ + void setReverseSorting( bool r = true ) { mReverseSorting = r; } + + /** + * Returns the direction of sorting. + * @return <tt>true</tt> if sorting is done reverse, <tt>false</tt> otherwise + */ + bool reverseSorting() const { return mReverseSorting; } + + /** + * Sorts this list by a specific criterion. + * @param c the criterion by which should be sorted + */ + void sortBy( SortingCriterion c ); + + /** + * Sorts this list by a specific field. If no parameter is given, the + * last used Field object will be used. + * @param field pointer to the Field object to be sorted by + */ + void sortByField( Field *field = 0 ); + + /** + * Sorts this list by its active sorting criterion. This normally is the + * criterion of the last sortBy operation or <tt>FormattedName</tt> if up + * to now there has been no sortBy operation. + * + * Please note that the sorting trait of the last {@link #sortByTrait} + * method call is not remembered and thus the action can not be repeated + * by this method. + */ + void sort(); + + /** + * Templated sort function. You normally will not want to use this but + * {@link #sortBy} and {@link #sort} instead as the existing sorting + * criteria completely suffice for most cases. + * + * However, if you do want to use some special sorting criterion, you can + * write a trait class that will be provided to this templated method. + * This trait class has to have a class declaration like the following: + * <pre> + * class MySortingTrait { + * public: + * // eq returns true if a1 and a2 are equal + * static bool eq(KABC::Addressee a1, KABC::Addressee a2); + * // lt returns true is a1 is "less than" a2 + * static bool lt(KABC::Addressee a1, KABC::Addressee a2); + * }; + * </pre> + * You can then pass this class to the sortByTrait method like this: + * <pre> + * myAddresseelist.sortByTrait<MySortingTrait>(); + * </pre> + * Please note that the {@link #sort} method can not be used to repeat the + * sorting of the last <tt>sortByTrait</tt> action. + * + * Right now this method uses the bubble sort algorithm. This should be + * replaced for a better one when I have time. + */ + template<class Trait> void sortByTrait(); + + /** + * Returns the active sorting criterion, ie the sorting criterion that + * will be used by a {@link #sort} call. + */ + SortingCriterion sortingCriterion() const { return mActiveSortingCriterion; } + + /** + * Returns the active sorting field, ie a pointer to the Field object + * which was used for the last {@link #sortByField} operation. + */ + Field* sortingField() const { return mActiveSortingField; } + + private: + void quickSortByField( int, int ); + + bool mReverseSorting; + SortingCriterion mActiveSortingCriterion; + Field* mActiveSortingField; +}; + +} + +#endif diff --git a/kabc/agent.cpp b/kabc/agent.cpp new file mode 100644 index 0000000..ef26cbf --- a/dev/null +++ b/kabc/agent.cpp @@ -0,0 +1,155 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include "addressee.h" + +#include "agent.h" + +using namespace KABC; + +Agent::Agent() + : mAddressee( 0 ), mIntern( false ) +{ +} + +Agent::Agent( const QString &url ) + : mAddressee( 0 ),mUrl( url ), mIntern( false ) +{ +} + +Agent::Agent( Addressee *addressee ) + : mAddressee( addressee ), mIntern( true ) +{ +} + +Agent::~Agent() +{ + delete mAddressee; + mAddressee = 0; +} + +bool Agent::operator==( const Agent &a ) const +{ + if ( mIntern != a.mIntern ) + return false; + + if ( !mIntern ) { + if ( mUrl != a.mUrl ) + return false; + } else { + if ( mAddressee && !a.mAddressee ) return false; + if ( !mAddressee && a.mAddressee ) return false; + if ( !mAddressee && !a.mAddressee ) return false; + if ( (*mAddressee) != (*a.mAddressee) ) return false; + } + + return true; +} + +bool Agent::operator!=( const Agent &a ) const +{ + return !( a == *this ); +} + +Agent &Agent::operator=( const Agent &addr ) +{ + if ( this == &addr ) + return *this; + + if ( addr.mIntern && addr.mAddressee ) { + if ( mAddressee ) + delete mAddressee; + + mAddressee = new Addressee; + *mAddressee = *(addr.mAddressee); + } + + mUrl = addr.mUrl; + mIntern = addr.mIntern; + + return *this; +} + +void Agent::setUrl( const QString &url ) +{ + mUrl = url; + mIntern = false; +} + +void Agent::setAddressee( Addressee *addressee ) +{ + mAddressee = addressee; + mIntern = true; +} + +bool Agent::isIntern() const +{ + return mIntern; +} + +QString Agent::url() const +{ + return mUrl; +} + +Addressee *Agent::addressee() const +{ + return mAddressee; +} + +QString Agent::asString() const +{ + if ( mIntern ) + return "intern agent"; + else + return mUrl; +} + +QDataStream &KABC::operator<<( QDataStream &s, const Agent &agent ) +{ + Q_UINT32 hasAddressee = ( agent.mAddressee != 0 ); + + s << agent.mIntern << agent.mUrl << hasAddressee; + if ( hasAddressee ) + s << (*agent.mAddressee); + + return s; +} + +QDataStream &KABC::operator>>( QDataStream &s, Agent &agent ) +{ + Q_UINT32 hasAddressee; + + s >> agent.mIntern >> agent.mUrl >> hasAddressee; + + if ( hasAddressee ) { + agent.mAddressee = new Addressee; + s >> (*agent.mAddressee); + } + + return s; +} diff --git a/kabc/agent.h b/kabc/agent.h new file mode 100644 index 0000000..fa459d5 --- a/dev/null +++ b/kabc/agent.h @@ -0,0 +1,129 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_AGENT_H +#define KABC_AGENT_H + +namespace KABC { + +class Addressee; + +/** + * Important!!! + * + * At the moment the vcard format does not support saving and loading + * this entity. + */ +class Agent +{ + friend QDataStream &operator<<( QDataStream &, const Agent & ); + friend QDataStream &operator>>( QDataStream &, Agent & ); + +public: + + /** + * Consturctor. Creates an empty object. + */ + Agent(); + + /** + * Consturctor. + * + * @param url A URL that describes the position of the agent file. + */ + Agent( const QString &url ); + + /** + * Consturctor. + * + * @param addressee The addressee object of the agent. + */ + Agent( Addressee *addressee ); + + /** + * Destructor. + */ + ~Agent(); + + + bool operator==( const Agent & ) const; + bool operator!=( const Agent & ) const; + Agent &operator=( const Agent & ); + + /** + * Sets a URL for the location of the agent file. When using this + * function, @ref isIntern() will return 'false' until you use + * @ref setAddressee(). + * + * @param url The location URL of the agent file. + */ + void setUrl( const QString &url ); + + /** + * Sets the addressee of the agent. When using this function, + * @ref isIntern() will return 'true' until you use @ref setUrl(). + * + * @param addressee The addressee object of the agent. + */ + void setAddressee( Addressee *addressee ); + + /** + * Returns whether the agent is described by a URL (extern) or + * by a addressee (intern). + * When this method returns 'true' you can use @ref addressee() to + * get a @ref Addressee object. Otherwise you can request the URL + * of this agent by @ref url() and load the data from that location. + */ + bool isIntern() const; + + /** + * Returns the location URL of this agent. + */ + QString url() const; + + /** + * Returns the addressee object of this agent. + */ + Addressee* addressee() const; + + /** + * Returns string representation of the agent. + */ + QString asString() const; + +private: + Addressee *mAddressee; + QString mUrl; + + int mIntern; +}; + +QDataStream &operator<<( QDataStream &, const Agent & ); +QDataStream &operator>>( QDataStream &, Agent & ); + +} +#endif diff --git a/kabc/distributionlist.cpp b/kabc/distributionlist.cpp new file mode 100644 index 0000000..aa2725d --- a/dev/null +++ b/kabc/distributionlist.cpp @@ -0,0 +1,293 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <kdebug.h> + +#include "distributionlist.h" + +using namespace KABC; + +DistributionList::DistributionList( DistributionListManager *manager, + const QString &name ) : + mManager( manager ), mName( name ) +{ + mManager->insert( this ); +} + +DistributionList::~DistributionList() +{ + mManager->remove( this ); +} + +void DistributionList::setName( const QString &name ) +{ + mName = name; +} + +QString DistributionList::name() const +{ + return mName; +} + +void DistributionList::insertEntry( const Addressee &a, const QString &email ) +{ + Entry e( a, email ); + + QValueList<Entry>::Iterator it; + for( it = mEntries.begin(); it != mEntries.end(); ++it ) { + if ( (*it).addressee.uid() == a.uid() ) { + /** + We have to check if both email addresses contains no data, + a simple 'email1 == email2' wont work here + */ + if ( ( (*it).email.isNull() && email.isEmpty() ) || + ( (*it).email.isEmpty() && email.isNull() ) || + ( (*it).email == email ) ) { + *it = e; + return; + } + } + } + mEntries.append( e ); +} + +void DistributionList::removeEntry( const Addressee &a, const QString &email ) +{ + QValueList<Entry>::Iterator it; + for( it = mEntries.begin(); it != mEntries.end(); ++it ) { + if ( (*it).addressee.uid() == a.uid() && (*it).email == email ) { + mEntries.remove( it ); + return; + } + } +} + +QStringList DistributionList::emails() const +{ + QStringList emails; + + Entry::List::ConstIterator it; + for( it = mEntries.begin(); it != mEntries.end(); ++it ) { + Addressee a = (*it).addressee; + QString email = (*it).email.isEmpty() ? a.fullEmail() : + a.fullEmail( (*it).email ); + + if ( !email.isEmpty() ) { + emails.append( email ); + } + } + + return emails; +} + +DistributionList::Entry::List DistributionList::entries() const +{ + return mEntries; +} + + +DistributionListManager::DistributionListManager( AddressBook *ab ) : + mAddressBook( ab ) +{ +} + +DistributionListManager::~DistributionListManager() +{ +} + +DistributionList *DistributionListManager::list( const QString &name ) +{ + DistributionList *list; + for( list = mLists.first(); list; list = mLists.next() ) { + if ( list->name() == name ) return list; + } + + return 0; +} + +void DistributionListManager::insert( DistributionList *l ) +{ + DistributionList *list; + for( list = mLists.first(); list; list = mLists.next() ) { + if ( list->name() == l->name() ) { + mLists.remove( list ); + break; + } + } + mLists.append( l ); +} + +void DistributionListManager::remove( DistributionList *l ) +{ + DistributionList *list; + for( list = mLists.first(); list; list = mLists.next() ) { + if ( list->name() == l->name() ) { + mLists.remove( list ); + return; + } + } +} + +QStringList DistributionListManager::listNames() +{ + QStringList names; + + DistributionList *list; + for( list = mLists.first(); list; list = mLists.next() ) { + names.append( list->name() ); + } + + return names; +} + +bool DistributionListManager::load() +{ + KSimpleConfig cfg( locateLocal( "data", "kabc/distlists" ) ); + +#ifndef KAB_EMBEDDED + + QMap<QString,QString> entryMap = cfg.entryMap( mAddressBook->identifier() ); + if ( entryMap.isEmpty() ) { + kdDebug(5700) << "No distlists for '" << mAddressBook->identifier() << "'" << endl; + return false; + } + + cfg.setGroup( mAddressBook->identifier() ); + + QMap<QString,QString>::ConstIterator it; + for( it = entryMap.begin(); it != entryMap.end(); ++it ) { + QString name = it.key(); + +#else //KAB_EMBEDDED + cfg.setGroup( mAddressBook->identifier() ); + //US we work in microkde with a list of distributionlists + QStringList distlists = cfg.readListEntry( "Lists" ); + if ( distlists.isEmpty() ) { + kdDebug(5700) << "No distlists for '" << mAddressBook->identifier() << "'" << endl; + return false; + } + + QStringList::ConstIterator it; + for( it = distlists.begin(); it != distlists.end(); ++it ) { + QString name = *it; + +#endif //KAB_EMBEDDED + + QStringList value = cfg.readListEntry( name ); + + kdDebug(5700) << "DLM::load(): " << name << ": " << value.join(",") << endl; + + DistributionList *list = new DistributionList( this, name ); + + QStringList::ConstIterator it2 = value.begin(); + while( it2 != value.end() ) { + QString id = *it2++; + QString email = *it2; + + kdDebug(5700) << "----- Entry " << id << endl; + + Addressee a = mAddressBook->findByUid( id ); + if ( !a.isEmpty() ) { + list->insertEntry( a, email ); + } + + if ( it2 == value.end() ) break; + ++it2; + } + } + + return true; +} + +bool DistributionListManager::save() +{ + kdDebug(5700) << "DistListManager::save()" << endl; + + KSimpleConfig cfg( locateLocal( "data", "kabc/distlists" ) ); + + cfg.deleteGroup( mAddressBook->identifier() ); + cfg.setGroup( mAddressBook->identifier() ); + + DistributionList *list; + for( list = mLists.first(); list; list = mLists.next() ) { + kdDebug(5700) << " Saving '" << list->name() << "'" << endl; + QStringList value; + DistributionList::Entry::List entries = list->entries(); + DistributionList::Entry::List::ConstIterator it; + for( it = entries.begin(); it != entries.end(); ++it ) { + value.append( (*it).addressee.uid() ); + value.append( (*it).email ); + } + cfg.writeEntry( list->name(), value ); + } + +#ifdef KAB_EMBEDDED +//US for microKDE we have not yet sophisticated methods to load maps. +// Because of that we store also a list of all distributionlists. + QStringList namelist; + for( list = mLists.first(); list; list = mLists.next() ) { + namelist.append( list->name() ); + } + cfg.writeEntry( "Lists", namelist ); + +#endif //KAB_EMBEDDED + + cfg.sync(); + + return true; +} + +DistributionListWatcher* DistributionListWatcher::mSelf = 0; + +DistributionListWatcher::DistributionListWatcher() + : QObject( 0, "DistributionListWatcher" ) +{ +#ifndef KAB_EMBEDDED + mDirWatch = new KDirWatch; + mDirWatch->addFile( locateLocal( "data", "kabc/distlists" ) ); + + connect( mDirWatch, SIGNAL( dirty( const QString& ) ), SIGNAL( changed() ) ); + mDirWatch->startScan(); +#endif //KAB_EMBEDDED +} + +DistributionListWatcher::~DistributionListWatcher() +{ +#ifndef KAB_EMBEDDED + delete mDirWatch; + mDirWatch = 0; +#endif //KAB_EMBEDDED +} + +DistributionListWatcher *DistributionListWatcher::self() +{ + if ( !mSelf ) + mSelf = new DistributionListWatcher(); + + return mSelf; +} + + +#ifndef KAB_EMBEDDED +#include "distributionlist.moc" +#endif //KAB_EMBEDDED + diff --git a/kabc/distributionlist.h b/kabc/distributionlist.h new file mode 100644 index 0000000..ccff487 --- a/dev/null +++ b/kabc/distributionlist.h @@ -0,0 +1,219 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KABC_DISTRIBUTIONLIST_H +#define KABC_DISTRIBUTIONLIST_H + +#include <kdirwatch.h> + +#include "addressbook.h" + +namespace KABC { + +class DistributionListManager; + +/** + @short Distribution list of email addresses + + This class represents a list of email addresses. Each email address is + associated with an address book entry. If the address book entry changes, the + entry in the distribution list is automatically updated. +*/ +class DistributionList +{ + public: + /** + @short Distribution List Entry + + This class represents an entry of a distribution list. It consists of an + addressee and an email address. If the email address is null, the + preferred email address of the addressee is used. + */ + struct Entry + { + typedef QValueList<Entry> List; + + Entry() {} + Entry( const Addressee &_addressee, const QString &_email ) : + addressee( _addressee ), email( _email ) {} + + Addressee addressee; + QString email; + }; + + /** + Create distribution list object. + + @param manager Managing object of this list. + @param name Name of this list. + */ + DistributionList( DistributionListManager *manager, const QString &name ); + + /** + Destructor. + */ + ~DistributionList(); + + /** + Set name of this list. The name is used as key by the + DistributinListManager. + */ + void setName( const QString & ); + + /** + Get name of this list. + */ + QString name() const; + + /** + Insert an entry into this distribution list. If the entry already exists + nothing happens. + */ + void insertEntry( const Addressee &, const QString &email=QString::null ); + + /** + Remove an entry from this distribution list. If the entry doesn't exist + nothing happens. + */ + void removeEntry( const Addressee &, const QString &email=QString::null ); + + /** + Return list of email addresses, which belong to this distributon list. + These addresses can be directly used by e.g. a mail client. + */ + QStringList emails() const; + + /** + Return list of entries belonging to this distribution list. This function + is mainly useful for a distribution list editor. + */ + Entry::List entries() const; + + private: + DistributionListManager *mManager; + QString mName; + + Entry::List mEntries; +}; + +/** + @short Manager of distribution lists + + This class represents a collection of distribution lists, which are associated + with a given address book. +*/ +class DistributionListManager +{ + public: + /** + Create manager for given address book. + */ + DistributionListManager( AddressBook * ); + + /** + Destructor. + */ + ~DistributionListManager(); + + /** + Return distribution list with given name. + */ + DistributionList *list( const QString &name ); + + /** + Insert distribution list. If a list with this name already exists, nothing + happens. + */ + void insert( DistributionList * ); + + /** + Remove distribution list. If a list with this name doesn't exist, nothing + happens. + */ + void remove( DistributionList * ); + + /** + Return names of all distribution lists managed by this manager. + */ + QStringList listNames(); + + /** + Load distribution lists form disk. + */ + bool load(); + + /** + Save distribution lists to disk. + */ + bool save(); + + private: + AddressBook *mAddressBook; + + QPtrList<DistributionList> mLists; +}; + +/** + @short Watchdog for distribution lists + + This class provides a @ref changed() signal that i emitted when the + distribution lists has changed in some way. + + Exapmle: + + <pre> + KABC::DistributionListWatcher *watchdog = KABC::DistributionListWatcher::self() + + connect( watchdog, SIGNAL( changed() ), SLOT( doSomething() ) ); + </pre> +*/ + +class DistributionListWatcher : public QObject +{ + Q_OBJECT + + public: + /** + * Returns the watcher object. + */ + static DistributionListWatcher *self(); + + + signals: + /** + * This signal is emmitted whenever the distribution lists has + * changed (if a list was added or removed, when a list was + * renamed or the entries of the list changed). + */ + void changed(); + + protected: + DistributionListWatcher(); + ~DistributionListWatcher(); + + private: + static DistributionListWatcher* mSelf; +#ifndef KAB_EMBEDDED + KDirWatch *mDirWatch; +#endif //KAB_EMBEDDED +}; + +} +#endif diff --git a/kabc/distributionlistdialog.cpp b/kabc/distributionlistdialog.cpp new file mode 100644 index 0000000..31d5944 --- a/dev/null +++ b/kabc/distributionlistdialog.cpp @@ -0,0 +1,396 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qlistview.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qcombobox.h> +#include <klineeditdlg.h> +#include <qbuttongroup.h> +#include <qradiobutton.h> + +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> + +#include "addressbook.h" +#include "addresseedialog.h" +#include "distributionlist.h" + +#include "distributionlistdialog.h" + +#ifndef KAB_EMBEDDED +#include "distributionlistdialog.moc" +#endif //KAB_EMBEDDED + +using namespace KABC; + +DistributionListDialog::DistributionListDialog( AddressBook *addressBook, QWidget *parent) + : KDialogBase( parent, "", true, i18n("Configure Distribution Lists"), Ok, Ok, true) +{ + mEditor = new DistributionListEditorWidget( addressBook, this ); + setMainWidget( mEditor ); + + connect( this, SIGNAL( okClicked() ), mEditor, SLOT( save() ) ); +} + +DistributionListDialog::~DistributionListDialog() +{ +} + + +EmailSelector::EmailSelector( const QStringList &emails, const QString ¤t, + QWidget *parent ) : + KDialogBase( KDialogBase::Plain, i18n("Select Email Address"), Ok, Ok, + parent ) +{ + QFrame *topFrame = plainPage(); + QBoxLayout *topLayout = new QVBoxLayout( topFrame ); + + mButtonGroup = new QButtonGroup( 1, Horizontal, i18n("Email Addresses"), + topFrame ); + topLayout->addWidget( mButtonGroup ); + + QStringList::ConstIterator it; + for( it = emails.begin(); it != emails.end(); ++it ) { + QRadioButton *button = new QRadioButton( *it, mButtonGroup ); + if ( (*it) == current ) { + button->setDown( true ); + } + } +} + +QString EmailSelector::selected() +{ + QButton *button = mButtonGroup->selected(); + if ( button ) return button->text(); + return QString::null; +} + +QString EmailSelector::getEmail( const QStringList &emails, const QString ¤t, + QWidget *parent ) +{ + EmailSelector *dlg = new EmailSelector( emails, current, parent ); + dlg->exec(); + + QString result = dlg->selected(); + + delete dlg; + + return result; +} + +class EntryItem : public QListViewItem +{ + public: + EntryItem( QListView *parent, const Addressee &addressee, + const QString &email=QString::null ) : + QListViewItem( parent ), + mAddressee( addressee ), + mEmail( email ) + { + setText( 0, addressee.realName() ); + if( email.isEmpty() ) { + setText( 1, addressee.preferredEmail() ); + setText( 2, i18n("Yes") ); + } else { + setText( 1, email ); + setText( 2, i18n("No") ); + } + } + + Addressee addressee() const + { + return mAddressee; + } + + QString email() const + { + return mEmail; + } + + private: + Addressee mAddressee; + QString mEmail; +}; + +DistributionListEditorWidget::DistributionListEditorWidget( AddressBook *addressBook, QWidget *parent) : + QWidget( parent ), + mAddressBook( addressBook ) +{ + kdDebug(5700) << "DistributionListEditor()" << endl; + + QBoxLayout *topLayout = new QVBoxLayout( this ); + topLayout->setSpacing( KDialog::spacingHint() ); + + QBoxLayout *nameLayout = new QHBoxLayout( topLayout) ; + + mNameCombo = new QComboBox( this ); + nameLayout->addWidget( mNameCombo ); + connect( mNameCombo, SIGNAL( activated( int ) ), SLOT( updateEntryView() ) ); + + mNewButton = new QPushButton( i18n("New List..."), this ); + nameLayout->addWidget( mNewButton ); + connect( mNewButton, SIGNAL( clicked() ), SLOT( newList() ) ); + + mEditButton = new QPushButton( i18n("Rename List..."), this ); + nameLayout->addWidget( mEditButton ); + connect( mEditButton, SIGNAL( clicked() ), SLOT( editList() ) ); + + mRemoveButton = new QPushButton( i18n("Remove List"), this ); + nameLayout->addWidget( mRemoveButton ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeList() ) ); + + QGridLayout *gridLayout = new QGridLayout( topLayout, 3, 3 ); + gridLayout->setColStretch(1, 1); + + QLabel *listLabel = new QLabel( i18n("Available addresses:"), this ); + gridLayout->addWidget( listLabel, 0, 0 ); + + mListLabel = new QLabel( this ); + gridLayout->addMultiCellWidget( mListLabel, 0, 0, 1, 2 ); + + mAddresseeView = new QListView( this ); + mAddresseeView->addColumn( i18n("Name") ); + mAddresseeView->addColumn( i18n("Preferred Email") ); + mAddresseeView->setAllColumnsShowFocus( true ); + gridLayout->addWidget( mAddresseeView, 1, 0 ); + connect( mAddresseeView, SIGNAL( selectionChanged() ), + SLOT( slotSelectionAddresseeViewChanged() ) ); + connect( mAddresseeView, SIGNAL( doubleClicked( QListViewItem * ) ), + SLOT( addEntry() ) ); + + mAddEntryButton = new QPushButton( i18n("Add Entry"), this ); + mAddEntryButton->setEnabled(false); + gridLayout->addWidget( mAddEntryButton, 2, 0 ); + connect( mAddEntryButton, SIGNAL( clicked() ), SLOT( addEntry() ) ); + + mEntryView = new QListView( this ); + mEntryView->addColumn( i18n("Name") ); + mEntryView->addColumn( i18n("Email") ); + mEntryView->addColumn( i18n("Use Preferred") ); + mEntryView->setEnabled(false); + mEntryView->setAllColumnsShowFocus( true ); + gridLayout->addMultiCellWidget( mEntryView, 1, 1, 1, 2 ); + connect( mEntryView, SIGNAL( selectionChanged() ), + SLOT( slotSelectionEntryViewChanged() ) ); + + mChangeEmailButton = new QPushButton( i18n("Change Email..."), this ); + gridLayout->addWidget( mChangeEmailButton, 2, 1 ); + connect( mChangeEmailButton, SIGNAL( clicked() ), SLOT( changeEmail() ) ); + + mRemoveEntryButton = new QPushButton( i18n("Remove Entry"), this ); + gridLayout->addWidget( mRemoveEntryButton, 2, 2 ); + connect( mRemoveEntryButton, SIGNAL( clicked() ), SLOT( removeEntry() ) ); + + mManager = new DistributionListManager( mAddressBook ); + mManager->load(); + + updateAddresseeView(); + updateNameCombo(); +} + +DistributionListEditorWidget::~DistributionListEditorWidget() +{ + kdDebug(5700) << "~DistributionListEditor()" << endl; + + delete mManager; +} + +void DistributionListEditorWidget::save() +{ + mManager->save(); +} + +void DistributionListEditorWidget::slotSelectionEntryViewChanged() +{ + EntryItem *entryItem = static_cast<EntryItem *>( mEntryView->selectedItem() ); + bool state=entryItem; + + mChangeEmailButton->setEnabled(state); + mRemoveEntryButton->setEnabled(state); +} + +void DistributionListEditorWidget::newList() +{ + KLineEditDlg dlg(i18n("Please enter name:"), QString::null, this); + dlg.setCaption(i18n("New Distribution List")); + if (!dlg.exec()) return; + + new DistributionList( mManager, dlg.text() ); + + mNameCombo->clear(); + mNameCombo->insertStringList( mManager->listNames() ); + mNameCombo->setCurrentItem( mNameCombo->count() - 1 ); + + updateEntryView(); + slotSelectionAddresseeViewChanged(); +} + +void DistributionListEditorWidget::editList() +{ + QString oldName = mNameCombo->currentText(); + + KLineEditDlg dlg(i18n("Please change name:"), oldName, this); + dlg.setCaption(i18n("Distribution List")); + if (!dlg.exec()) return; + + DistributionList *list = mManager->list( oldName ); + list->setName( dlg.text() ); + + mNameCombo->clear(); + mNameCombo->insertStringList( mManager->listNames() ); + mNameCombo->setCurrentItem( mNameCombo->count() - 1 ); + + updateEntryView(); + slotSelectionAddresseeViewChanged(); +} + +void DistributionListEditorWidget::removeList() +{ + int result = KMessageBox::warningContinueCancel( this, + i18n("Delete distribution list '%1'?") .arg( mNameCombo->currentText() ), + QString::null, i18n("Delete") ); + + if ( result != KMessageBox::Continue ) return; + + delete mManager->list( mNameCombo->currentText() ); + mNameCombo->removeItem( mNameCombo->currentItem() ); + + updateEntryView(); + slotSelectionAddresseeViewChanged(); +} + +void DistributionListEditorWidget::addEntry() +{ + AddresseeItem *addresseeItem = + static_cast<AddresseeItem *>( mAddresseeView->selectedItem() ); + + if( !addresseeItem ) { + kdDebug(5700) << "DLE::addEntry(): No addressee selected." << endl; + return; + } + + DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) { + kdDebug(5700) << "DLE::addEntry(): No dist list '" << mNameCombo->currentText() << "'" << endl; + return; + } + + list->insertEntry( addresseeItem->addressee() ); + updateEntryView(); + slotSelectionAddresseeViewChanged(); +} + +void DistributionListEditorWidget::removeEntry() +{ + DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) return; + + EntryItem *entryItem = + static_cast<EntryItem *>( mEntryView->selectedItem() ); + if ( !entryItem ) return; + + list->removeEntry( entryItem->addressee(), entryItem->email() ); + delete entryItem; +} + +void DistributionListEditorWidget::changeEmail() +{ + DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) return; + + EntryItem *entryItem = + static_cast<EntryItem *>( mEntryView->selectedItem() ); + if ( !entryItem ) return; + + QString email = EmailSelector::getEmail( entryItem->addressee().emails(), + entryItem->email(), this ); + list->removeEntry( entryItem->addressee(), entryItem->email() ); + list->insertEntry( entryItem->addressee(), email ); + + updateEntryView(); +} + +void DistributionListEditorWidget::updateEntryView() +{ + if ( mNameCombo->currentText().isEmpty() ) { + mListLabel->setText( i18n("Selected addressees:") ); + } else { + mListLabel->setText( i18n("Selected addresses in '%1':") + .arg( mNameCombo->currentText() ) ); + } + + mEntryView->clear(); + + DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) { + mEditButton->setEnabled(false); + mRemoveButton->setEnabled(false); + mChangeEmailButton->setEnabled(false); + mRemoveEntryButton->setEnabled(false); + mAddresseeView->setEnabled(false); + mEntryView->setEnabled(false); + return; + } else { + mEditButton->setEnabled(true); + mRemoveButton->setEnabled(true); + mAddresseeView->setEnabled(true); + mEntryView->setEnabled(true); + } + + DistributionList::Entry::List entries = list->entries(); + DistributionList::Entry::List::ConstIterator it; + for( it = entries.begin(); it != entries.end(); ++it ) { + new EntryItem( mEntryView, (*it).addressee, (*it).email ); + } + + EntryItem *entryItem = static_cast<EntryItem *>( mEntryView->selectedItem() ); + bool state=entryItem; + + mChangeEmailButton->setEnabled(state); + mRemoveEntryButton->setEnabled(state); +} + +void DistributionListEditorWidget::updateAddresseeView() +{ + mAddresseeView->clear(); + + AddressBook::Iterator it; + for( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { + new AddresseeItem( mAddresseeView, *it ); + } +} + +void DistributionListEditorWidget::updateNameCombo() +{ + mNameCombo->insertStringList( mManager->listNames() ); + + updateEntryView(); +} + +void DistributionListEditorWidget::slotSelectionAddresseeViewChanged() +{ + AddresseeItem *addresseeItem = + static_cast<AddresseeItem *>( mAddresseeView->selectedItem() ); + bool state=addresseeItem; + mAddEntryButton->setEnabled( state && !mNameCombo->currentText().isEmpty()); +} diff --git a/kabc/distributionlistdialog.h b/kabc/distributionlistdialog.h new file mode 100644 index 0000000..b6d3c80 --- a/dev/null +++ b/kabc/distributionlistdialog.h @@ -0,0 +1,140 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KABC_DISTRIBUTIONLISTDIALOG_H +#define KABC_DISTRIBUTIONLISTDIALOG_H + +#include <qwidget.h> + +#include <kdialogbase.h> + +class QListView; +class QLabel; +class QComboBox; +class QButtonGroup; + +namespace KABC { + +class AddressBook; +class DistributionListEditorWidget; +class DistributionListManager; + +/** + @short Frontend to create distribution lists + + Creating a new DistributionListDialog does automatically + load all addressees and distribution lists from the config + files. The changes will be saved when clicking the 'OK' + button. + + Example: + + <pre> + KABC::DistributionListDialog *dlg = new + KABC::DistributionListDialog( KABC::StdAddressBook::self(), this ); + + dlg->exec(); + </pre> +*/ +class DistributionListDialog : public KDialogBase +{ + Q_OBJECT + + public: + /** + Constructor. + + @param ab The addressbook, the addressees should be used from + @param parent The parent widget + */ + DistributionListDialog( AddressBook *ab, QWidget *parent ); + + /** + Destructor. + */ + virtual ~DistributionListDialog(); + + private: + DistributionListEditorWidget *mEditor; + + struct Data; + Data *d; +}; + +/** + @short Helper class +*/ +class EmailSelector : public KDialogBase +{ + public: + EmailSelector( const QStringList &emails, const QString ¤t, + QWidget *parent ); + + QString selected(); + + static QString getEmail( const QStringList &emails, const QString ¤t, + QWidget *parent ); + + private: + QButtonGroup *mButtonGroup; +}; + +/** + @short Helper class +*/ +class DistributionListEditorWidget : public QWidget +{ + Q_OBJECT + + public: + DistributionListEditorWidget( AddressBook *, QWidget *parent ); + virtual ~DistributionListEditorWidget(); + + private slots: + void newList(); + void editList(); + void removeList(); + void addEntry(); + void removeEntry(); + void changeEmail(); + void updateEntryView(); + void updateAddresseeView(); + void updateNameCombo(); + void slotSelectionEntryViewChanged(); + void slotSelectionAddresseeViewChanged(); + void save(); + + private: + QComboBox *mNameCombo; + QLabel *mListLabel; + QListView *mEntryView; + QListView *mAddresseeView; + + AddressBook *mAddressBook; + DistributionListManager *mManager; + QPushButton *mNewButton, *mEditButton, *mRemoveButton; + QPushButton *mChangeEmailButton, *mRemoveEntryButton, *mAddEntryButton; + + struct Data; + Data *d; +}; + +} +#endif diff --git a/kabc/distributionlisteditor.cpp b/kabc/distributionlisteditor.cpp new file mode 100644 index 0000000..569dc96 --- a/dev/null +++ b/kabc/distributionlisteditor.cpp @@ -0,0 +1,335 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qlistview.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qcombobox.h> +#include <qinputdialog.h> +#include <qbuttongroup.h> +#include <qradiobutton.h> + +#include <klocale.h> +#include <kdebug.h> + +#include "addressbook.h" +#include "addresseedialog.h" +#include "distributionlist.h" + +#include "distributionlisteditor.h" + +#ifndef KAB_EMBEDDED +#include "distributionlisteditor.moc" +#endif //KAB_EMBEDDED + +using namespace KABC; + +EmailSelectDialog::EmailSelectDialog( const QStringList &emails, const QString ¤t, + QWidget *parent ) : + KDialogBase( KDialogBase::Plain, i18n("Select Email Address"), Ok, Ok, + parent ) +{ + QFrame *topFrame = plainPage(); + QBoxLayout *topLayout = new QVBoxLayout( topFrame ); + + mButtonGroup = new QButtonGroup( 1, Horizontal, i18n("Email Addresses"), + topFrame ); + topLayout->addWidget( mButtonGroup ); + + QStringList::ConstIterator it; + for( it = emails.begin(); it != emails.end(); ++it ) { + QRadioButton *button = new QRadioButton( *it, mButtonGroup ); + if ( (*it) == current ) { + button->setDown( true ); + } + } +} + +QString EmailSelectDialog::selected() +{ + QButton *button = mButtonGroup->selected(); + if ( button ) return button->text(); + return QString::null; +} + +QString EmailSelectDialog::getEmail( const QStringList &emails, const QString ¤t, + QWidget *parent ) +{ + EmailSelectDialog *dlg = new EmailSelectDialog( emails, current, parent ); + dlg->exec(); + + QString result = dlg->selected(); + + delete dlg; + + return result; +} + +class EditEntryItem : public QListViewItem +{ + public: + EditEntryItem( QListView *parent, const Addressee &addressee, + const QString &email=QString::null ) : + QListViewItem( parent ), + mAddressee( addressee ), + mEmail( email ) + { + setText( 0, addressee.realName() ); + if( email.isEmpty() ) { + setText( 1, addressee.preferredEmail() ); + setText( 2, i18n("Yes") ); + } else { + setText( 1, email ); + setText( 2, i18n("No") ); + } + } + + Addressee addressee() const + { + return mAddressee; + } + + QString email() const + { + return mEmail; + } + + private: + Addressee mAddressee; + QString mEmail; +}; + +DistributionListEditor::DistributionListEditor( AddressBook *addressBook, QWidget *parent) : + QWidget( parent ), + mAddressBook( addressBook ) +{ + kdDebug(5700) << "DistributionListEditor()" << endl; + + QBoxLayout *topLayout = new QVBoxLayout( this ); + topLayout->setMargin( KDialog::marginHint() ); + topLayout->setSpacing( KDialog::spacingHint() ); + + QBoxLayout *nameLayout = new QHBoxLayout( topLayout) ; + + mNameCombo = new QComboBox( this ); + nameLayout->addWidget( mNameCombo ); + connect( mNameCombo, SIGNAL( activated( int ) ), SLOT( updateEntryView() ) ); + + newButton = new QPushButton( i18n("New List"), this ); + nameLayout->addWidget( newButton ); + connect( newButton, SIGNAL( clicked() ), SLOT( newList() ) ); + + removeButton = new QPushButton( i18n("Remove List"), this ); + nameLayout->addWidget( removeButton ); + connect( removeButton, SIGNAL( clicked() ), SLOT( removeList() ) ); + + mEntryView = new QListView( this ); + mEntryView->addColumn( i18n("Name") ); + mEntryView->addColumn( i18n("Email") ); + mEntryView->addColumn( i18n("Use Preferred") ); + topLayout->addWidget( mEntryView ); + connect(mEntryView,SIGNAL(selectionChanged ()),this, SLOT(slotSelectionEntryViewChanged())); + + changeEmailButton = new QPushButton( i18n("Change Email"), this ); + topLayout->addWidget( changeEmailButton ); + connect( changeEmailButton, SIGNAL( clicked() ), SLOT( changeEmail() ) ); + + removeEntryButton = new QPushButton( i18n("Remove Entry"), this ); + topLayout->addWidget( removeEntryButton ); + connect( removeEntryButton, SIGNAL( clicked() ), SLOT( removeEntry() ) ); + + addEntryButton = new QPushButton( i18n("Add Entry"), this ); + topLayout->addWidget( addEntryButton ); + connect( addEntryButton, SIGNAL( clicked() ), SLOT( addEntry() ) ); + + mAddresseeView = new QListView( this ); + mAddresseeView->addColumn( i18n("Name") ); + mAddresseeView->addColumn( i18n("Preferred Email") ); + topLayout->addWidget( mAddresseeView ); + + + connect(mAddresseeView,SIGNAL(selectionChanged ()),this, SLOT(slotSelectionAddresseeViewChanged())); + + mManager = new DistributionListManager( mAddressBook ); + mManager->load(); + + updateAddresseeView(); + updateNameCombo(); + removeButton->setEnabled(!mManager->listNames().isEmpty()); +} + +DistributionListEditor::~DistributionListEditor() +{ + kdDebug(5700) << "~DistributionListEditor()" << endl; + + mManager->save(); + delete mManager; +} + +void DistributionListEditor::slotSelectionEntryViewChanged() +{ +#ifndef KAB_EMBEDDED + EditEntryItem *entryItem = dynamic_cast<EditEntryItem *>( mEntryView->selectedItem() ); +#else //KAB_EMBEDDED + EditEntryItem *entryItem = (EditEntryItem *)( mEntryView->selectedItem() ); +#endif //KAB_EMBEDDED + bool state = (entryItem != 0L); + + changeEmailButton->setEnabled(state); + removeEntryButton->setEnabled(state); +} + +void DistributionListEditor::newList() +{ + bool ok = false; + QString name = QInputDialog::getText( i18n("New Distribution List"), + i18n("Please enter name:"), + QLineEdit::Normal, QString::null, &ok, + this ); + if ( !ok || name.isEmpty() ) return; + + new DistributionList( mManager, name ); + + mNameCombo->insertItem( name ); + removeButton->setEnabled(true); + updateEntryView(); +} + +void DistributionListEditor::removeList() +{ + delete mManager->list( mNameCombo->currentText() ); + mNameCombo->removeItem( mNameCombo->currentItem() ); + removeButton->setEnabled(!mManager->listNames().isEmpty()); + addEntryButton->setEnabled( !mNameCombo->currentText().isEmpty()); + updateEntryView(); +} + +void DistributionListEditor::addEntry() +{ +#ifndef KAB_EMBEDDED + AddresseeItem *addresseeItem = + dynamic_cast<AddresseeItem *>( mAddresseeView->selectedItem() ); +#else //KAB_EMBEDDED + AddresseeItem *addresseeItem = + (AddresseeItem *)( mAddresseeView->selectedItem() ); +#endif //KAB_EMBEDDED + + + if( !addresseeItem ) { + kdDebug(5700) << "DLE::addEntry(): No addressee selected." << endl; + return; + } + + DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) { + kdDebug(5700) << "DLE::addEntry(): No dist list '" << mNameCombo->currentText() << "'" << endl; + return; + } + + list->insertEntry( addresseeItem->addressee() ); + updateEntryView(); + slotSelectionAddresseeViewChanged(); +} + +void DistributionListEditor::removeEntry() +{ + DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) return; + +#ifndef KAB_EMBEDDED + EditEntryItem *entryItem = dynamic_cast<EditEntryItem *>( mEntryView->selectedItem() ); +#else //KAB_EMBEDDED + EditEntryItem *entryItem = (EditEntryItem *)( mEntryView->selectedItem() ); +#endif //KAB_EMBEDDED + if ( !entryItem ) return; + + list->removeEntry( entryItem->addressee(), entryItem->email() ); + delete entryItem; +} + +void DistributionListEditor::changeEmail() +{ + DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) return; + +#ifndef KAB_EMBEDDED + EditEntryItem *entryItem = dynamic_cast<EditEntryItem *>( mEntryView->selectedItem() ); +#else //KAB_EMBEDDED + EditEntryItem *entryItem = (EditEntryItem *)( mEntryView->selectedItem() ); +#endif //KAB_EMBEDDED + if ( !entryItem ) return; + + QString email = EmailSelectDialog::getEmail( entryItem->addressee().emails(), + entryItem->email(), this ); + list->removeEntry( entryItem->addressee(), entryItem->email() ); + list->insertEntry( entryItem->addressee(), email ); + + updateEntryView(); +} + +void DistributionListEditor::updateEntryView() +{ + DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) return; + + mEntryView->clear(); + DistributionList::Entry::List entries = list->entries(); + DistributionList::Entry::List::ConstIterator it; + for( it = entries.begin(); it != entries.end(); ++it ) { + new EditEntryItem( mEntryView, (*it).addressee, (*it).email ); + } +#ifndef KAB_EMBEDDED + EditEntryItem *entryItem = dynamic_cast<EditEntryItem *>( mEntryView->selectedItem() ); +#else //KAB_EMBEDDED + EditEntryItem *entryItem = (EditEntryItem *)( mEntryView->selectedItem() ); +#endif //KAB_EMBEDDED + bool state = (entryItem != 0L); + + changeEmailButton->setEnabled(state); + removeEntryButton->setEnabled(state); +} + +void DistributionListEditor::updateAddresseeView() +{ + mAddresseeView->clear(); + + AddressBook::Iterator it; + for( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { + new AddresseeItem( mAddresseeView, *it ); + } +} + +void DistributionListEditor::updateNameCombo() +{ + mNameCombo->insertStringList( mManager->listNames() ); + + updateEntryView(); +} + +void DistributionListEditor::slotSelectionAddresseeViewChanged() +{ +#ifndef KAB_EMBEDDED + AddresseeItem *addresseeItem = dynamic_cast<AddresseeItem *>( mAddresseeView->selectedItem() ); +#else //KAB_EMBEDDED + AddresseeItem *addresseeItem = (AddresseeItem *)( mAddresseeView->selectedItem() ); +#endif //KAB_EMBEDDED + bool state = (addresseeItem != 0L); + addEntryButton->setEnabled( state && !mNameCombo->currentText().isEmpty()); +} diff --git a/kabc/distributionlisteditor.h b/kabc/distributionlisteditor.h new file mode 100644 index 0000000..e0b4221 --- a/dev/null +++ b/kabc/distributionlisteditor.h @@ -0,0 +1,86 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KABC_DISTRIBUTIONLISTEDITOR_H +#define KABC_DISTRIBUTIONLISTEDITOR_H + +#include <qwidget.h> + +#include <kdialogbase.h> + +class QListView; +class QComboBox; +class QButtonGroup; + +namespace KABC { + +class AddressBook; +class DistributionListManager; + +class EmailSelectDialog : public KDialogBase +{ + public: + EmailSelectDialog( const QStringList &emails, const QString ¤t, + QWidget *parent ); + + QString selected(); + + static QString getEmail( const QStringList &emails, const QString ¤t, + QWidget *parent ); + + private: + QButtonGroup *mButtonGroup; +}; + +/** + @obsolete +*/ +class DistributionListEditor : public QWidget +{ + Q_OBJECT + public: + DistributionListEditor( AddressBook *, QWidget *parent ); + virtual ~DistributionListEditor(); + + private slots: + void newList(); + void removeList(); + void addEntry(); + void removeEntry(); + void changeEmail(); + void updateEntryView(); + void updateAddresseeView(); + void updateNameCombo(); + void slotSelectionEntryViewChanged(); + void slotSelectionAddresseeViewChanged(); + + private: + QComboBox *mNameCombo; + QListView *mEntryView; + QListView *mAddresseeView; + + AddressBook *mAddressBook; + DistributionListManager *mManager; + QPushButton *newButton, *removeButton; + QPushButton *changeEmailButton,*removeEntryButton,*addEntryButton; +}; + +} + +#endif diff --git a/kabc/field.cpp b/kabc/field.cpp new file mode 100644 index 0000000..41bbfde --- a/dev/null +++ b/kabc/field.cpp @@ -0,0 +1,550 @@ +/*** Warning! This file has been generated by the script makeaddressee ***/ +/* + This file is part of libkabc. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <klocale.h> +#include <kconfig.h> +#include <kconfigbase.h> +#include <kglobal.h> + +#include "field.h" + +using namespace KABC; + +class Field::FieldImpl +{ + public: + FieldImpl( int fieldId, int category = 0, + const QString &label = QString::null, + const QString &key = QString::null, + const QString &app = QString::null ) + : mFieldId( fieldId ), mCategory( category ), mLabel( label ), + mKey( key ), mApp( app ) {} + + enum FieldId + { + CustomField, + FormattedName, + FamilyName, + GivenName, + AdditionalName, + Prefix, + Suffix, + NickName, + Birthday, + HomeAddressStreet, + HomeAddressLocality, + HomeAddressRegion, + HomeAddressPostalCode, + HomeAddressCountry, + HomeAddressLabel, + BusinessAddressStreet, + BusinessAddressLocality, + BusinessAddressRegion, + BusinessAddressPostalCode, + BusinessAddressCountry, + BusinessAddressLabel, + HomePhone, + BusinessPhone, + MobilePhone, + HomeFax, + BusinessFax, + CarPhone, + Isdn, + Pager, + Email, + Mailer, + Title, + Role, + Organization, + Note, + Url + }; + + int fieldId() { return mFieldId; } + int category() { return mCategory; } + + QString label() { return mLabel; } + QString key() { return mKey; } + QString app() { return mApp; } + + private: + int mFieldId; + int mCategory; + + QString mLabel; + QString mKey; + QString mApp; +}; + + +Field::List Field::mAllFields; +Field::List Field::mDefaultFields; +Field::List Field::mCustomFields; + + +Field::Field( FieldImpl *impl ) +{ + mImpl = impl; +} + +Field::~Field() +{ + delete mImpl; +} + +QString Field::label() +{ + switch ( mImpl->fieldId() ) { + case FieldImpl::FormattedName: + return Addressee::formattedNameLabel(); + case FieldImpl::FamilyName: + return Addressee::familyNameLabel(); + case FieldImpl::GivenName: + return Addressee::givenNameLabel(); + case FieldImpl::AdditionalName: + return Addressee::additionalNameLabel(); + case FieldImpl::Prefix: + return Addressee::prefixLabel(); + case FieldImpl::Suffix: + return Addressee::suffixLabel(); + case FieldImpl::NickName: + return Addressee::nickNameLabel(); + case FieldImpl::Birthday: + return Addressee::birthdayLabel(); + case FieldImpl::HomeAddressStreet: + return Addressee::homeAddressStreetLabel(); + case FieldImpl::HomeAddressLocality: + return Addressee::homeAddressLocalityLabel(); + case FieldImpl::HomeAddressRegion: + return Addressee::homeAddressRegionLabel(); + case FieldImpl::HomeAddressPostalCode: + return Addressee::homeAddressPostalCodeLabel(); + case FieldImpl::HomeAddressCountry: + return Addressee::homeAddressCountryLabel(); + case FieldImpl::HomeAddressLabel: + return Addressee::homeAddressLabelLabel(); + case FieldImpl::BusinessAddressStreet: + return Addressee::businessAddressStreetLabel(); + case FieldImpl::BusinessAddressLocality: + return Addressee::businessAddressLocalityLabel(); + case FieldImpl::BusinessAddressRegion: + return Addressee::businessAddressRegionLabel(); + case FieldImpl::BusinessAddressPostalCode: + return Addressee::businessAddressPostalCodeLabel(); + case FieldImpl::BusinessAddressCountry: + return Addressee::businessAddressCountryLabel(); + case FieldImpl::BusinessAddressLabel: + return Addressee::businessAddressLabelLabel(); + case FieldImpl::HomePhone: + return Addressee::homePhoneLabel(); + case FieldImpl::BusinessPhone: + return Addressee::businessPhoneLabel(); + case FieldImpl::MobilePhone: + return Addressee::mobilePhoneLabel(); + case FieldImpl::HomeFax: + return Addressee::homeFaxLabel(); + case FieldImpl::BusinessFax: + return Addressee::businessFaxLabel(); + case FieldImpl::CarPhone: + return Addressee::carPhoneLabel(); + case FieldImpl::Isdn: + return Addressee::isdnLabel(); + case FieldImpl::Pager: + return Addressee::pagerLabel(); + case FieldImpl::Email: + return Addressee::emailLabel(); + case FieldImpl::Mailer: + return Addressee::mailerLabel(); + case FieldImpl::Title: + return Addressee::titleLabel(); + case FieldImpl::Role: + return Addressee::roleLabel(); + case FieldImpl::Organization: + return Addressee::organizationLabel(); + case FieldImpl::Note: + return Addressee::noteLabel(); + case FieldImpl::Url: + return Addressee::urlLabel(); + case FieldImpl::CustomField: + return mImpl->label(); + default: + return i18n("Unknown Field"); + } +} + +int Field::category() +{ + return mImpl->category(); +} + +QString Field::categoryLabel( int category ) +{ + switch ( category ) { + case All: + return i18n("All"); + case Frequent: + return i18n("Frequent"); + case Address: + return i18n("Address"); + case Email: + return i18n("Email"); + case Personal: + return i18n("Personal"); + case Organization: + return i18n("Organization"); + case CustomCategory: + return i18n("Custom"); + default: + return i18n("Undefined"); + } +} + +QString Field::value( const KABC::Addressee &a ) +{ + switch ( mImpl->fieldId() ) { + case FieldImpl::FormattedName: + return a.formattedName(); + case FieldImpl::FamilyName: + return a.familyName(); + case FieldImpl::GivenName: + return a.givenName(); + case FieldImpl::AdditionalName: + return a.additionalName(); + case FieldImpl::Prefix: + return a.prefix(); + case FieldImpl::Suffix: + return a.suffix(); + case FieldImpl::NickName: + return a.nickName(); + case FieldImpl::Mailer: + return a.mailer(); + case FieldImpl::Title: + return a.title(); + case FieldImpl::Role: + return a.role(); + case FieldImpl::Organization: + return a.organization(); + case FieldImpl::Note: + return a.note(); + case FieldImpl::Email: + return a.preferredEmail(); + case FieldImpl::Birthday: + if ( a.birthday().isValid() ) { +//the generated code had the following format: return a.birthday().date().toString( Qt::ISODate ); +// But Qt::IsoDate was not specified. + QString _oldFormat = KGlobal::locale()->dateFormat(); + KGlobal::locale()->setDateFormat("%Y-%m-%d"); // = Qt::ISODate + QString dt = KGlobal::locale()->formatDate(a.birthday().date(), false); + KGlobal::locale()->setDateFormat(_oldFormat); + return dt; + } + else + return QString::null; + case FieldImpl::Url: + return a.url().prettyURL(); + case FieldImpl::HomePhone: + return a.phoneNumber( PhoneNumber::Home ).number(); + case FieldImpl::BusinessPhone: + return a.phoneNumber( PhoneNumber::Work ).number(); + case FieldImpl::MobilePhone: + return a.phoneNumber( PhoneNumber::Cell ).number(); + case FieldImpl::HomeFax: + return a.phoneNumber( PhoneNumber::Home | PhoneNumber::Fax ).number(); + case FieldImpl::BusinessFax: + return a.phoneNumber( PhoneNumber::Work | PhoneNumber::Fax ).number(); + case FieldImpl::CarPhone: + return a.phoneNumber( PhoneNumber::Car ).number(); + case FieldImpl::Isdn: + return a.phoneNumber( PhoneNumber::Isdn ).number(); + case FieldImpl::Pager: + return a.phoneNumber( PhoneNumber::Pager ).number(); + case FieldImpl::HomeAddressStreet: + return a.address( Address::Home ).street(); + case FieldImpl::HomeAddressLocality: + return a.address( Address::Home ).locality(); + case FieldImpl::HomeAddressRegion: + return a.address( Address::Home ).region(); + case FieldImpl::HomeAddressPostalCode: + return a.address( Address::Home ).postalCode(); + case FieldImpl::HomeAddressCountry: + return a.address( Address::Home ).country(); + case FieldImpl::BusinessAddressStreet: + return a.address( Address::Work ).street(); + case FieldImpl::BusinessAddressLocality: + return a.address( Address::Work ).locality(); + case FieldImpl::BusinessAddressRegion: + return a.address( Address::Work ).region(); + case FieldImpl::BusinessAddressPostalCode: + return a.address( Address::Work ).postalCode(); + case FieldImpl::BusinessAddressCountry: + return a.address( Address::Work ).country(); + case FieldImpl::CustomField: + return a.custom( mImpl->app(), mImpl->key() ); + default: + return QString::null; + } +} + +bool Field::setValue( KABC::Addressee &a, const QString &value ) +{ + switch ( mImpl->fieldId() ) { + case FieldImpl::FormattedName: + a.setFormattedName( value ); + return true; + case FieldImpl::FamilyName: + a.setFamilyName( value ); + return true; + case FieldImpl::GivenName: + a.setGivenName( value ); + return true; + case FieldImpl::AdditionalName: + a.setAdditionalName( value ); + return true; + case FieldImpl::Prefix: + a.setPrefix( value ); + return true; + case FieldImpl::Suffix: + a.setSuffix( value ); + return true; + case FieldImpl::NickName: + a.setNickName( value ); + return true; + case FieldImpl::Mailer: + a.setMailer( value ); + return true; + case FieldImpl::Title: + a.setTitle( value ); + return true; + case FieldImpl::Role: + a.setRole( value ); + return true; + case FieldImpl::Organization: + a.setOrganization( value ); + return true; + case FieldImpl::Note: + a.setNote( value ); + return true; + case FieldImpl::Birthday: +//US +//the generated code had the following format: return a.setBirthday( QDate::fromString( value, Qt::ISODate ) ); +// But Qt::IsoDate and QDate::fromString was not specified. Do I have the wrong QT version ? + { + QDate dt = KGlobal::locale()->readDate( value, "%Y-%m-%d"); // = Qt::ISODate + a.setBirthday(dt); + } + return true; + case FieldImpl::CustomField: + a.insertCustom( mImpl->app(), mImpl->key(), value ); + default: + return false; + } +} + +bool Field::isCustom() +{ + return mImpl->fieldId() == FieldImpl::CustomField; +} + +Field::List Field::allFields() +{ + if ( mAllFields.isEmpty() ) { + createField( FieldImpl::FormattedName, Frequent ); + createField( FieldImpl::FamilyName, Frequent ); + createField( FieldImpl::GivenName, Frequent ); + createField( FieldImpl::AdditionalName ); + createField( FieldImpl::Prefix ); + createField( FieldImpl::Suffix ); + createField( FieldImpl::NickName, Personal ); + createField( FieldImpl::Birthday, Personal ); + createField( FieldImpl::HomeAddressStreet, Address|Personal ); + createField( FieldImpl::HomeAddressLocality, Address|Personal ); + createField( FieldImpl::HomeAddressRegion, Address|Personal ); + createField( FieldImpl::HomeAddressPostalCode, Address|Personal ); + createField( FieldImpl::HomeAddressCountry, Address|Personal ); + createField( FieldImpl::HomeAddressLabel, Address|Personal ); + createField( FieldImpl::BusinessAddressStreet, Address|Organization ); + createField( FieldImpl::BusinessAddressLocality, Address|Organization ); + createField( FieldImpl::BusinessAddressRegion, Address|Organization ); + createField( FieldImpl::BusinessAddressPostalCode, Address|Organization ); + createField( FieldImpl::BusinessAddressCountry, Address|Organization ); + createField( FieldImpl::BusinessAddressLabel, Address|Organization ); + createField( FieldImpl::HomePhone, Personal|Frequent ); + createField( FieldImpl::BusinessPhone, Organization|Frequent ); + createField( FieldImpl::MobilePhone, Frequent ); + createField( FieldImpl::HomeFax ); + createField( FieldImpl::BusinessFax ); + createField( FieldImpl::CarPhone ); + createField( FieldImpl::Isdn ); + createField( FieldImpl::Pager ); + createField( FieldImpl::Email, Email|Frequent ); + createField( FieldImpl::Mailer, Email ); + createField( FieldImpl::Title, Organization ); + createField( FieldImpl::Role, Organization ); + createField( FieldImpl::Organization, Organization ); + createField( FieldImpl::Note ); + createField( FieldImpl::Url ); + } + + return mAllFields; +} + +Field::List Field::defaultFields() +{ + if ( mDefaultFields.isEmpty() ) { + createDefaultField( FieldImpl::GivenName ); + createDefaultField( FieldImpl::FamilyName ); + createDefaultField( FieldImpl::Email ); + } + + return mDefaultFields; +} + +void Field::createField( int id, int category ) +{ + mAllFields.append( new Field( new FieldImpl( id, category ) ) ); +} + +void Field::createDefaultField( int id, int category ) +{ + mDefaultFields.append( new Field( new FieldImpl( id, category ) ) ); +} + +void Field::deleteFields() +{ + Field::List::ConstIterator it; + + for( it = mAllFields.begin(); it != mAllFields.end(); ++it ) { + delete (*it); + } + mAllFields.clear(); + + for( it = mDefaultFields.begin(); it != mDefaultFields.end(); ++it ) { + delete (*it); + } + mDefaultFields.clear(); + + for( it = mCustomFields.begin(); it != mCustomFields.end(); ++it ) { + delete (*it); + } + mCustomFields.clear(); +} + +void Field::saveFields( const QString &identifier, + const Field::List &fields ) +{ + KConfig *cfg = KGlobal::config(); + KConfigGroupSaver( cfg, "KABCFields" ); + saveFields( cfg, identifier, fields ); +} + +void Field::saveFields( KConfig *cfg, const QString &identifier, + const Field::List &fields ) +{ + QValueList<int> fieldIds; + +//US +//US qDebug("Field::saveFields to %s %s", cfg->getFileName().latin1(), identifier.latin1()); + + int custom = 0; + Field::List::ConstIterator it; + for( it = fields.begin(); it != fields.end(); ++it ) { +//US +//US qDebug("Field::saveFields field:%i", (*it)->mImpl->fieldId()); + + fieldIds.append( (*it)->mImpl->fieldId() ); + if( (*it)->isCustom() ) { + QStringList customEntry; + customEntry << (*it)->mImpl->label(); + customEntry << (*it)->mImpl->key(); + customEntry << (*it)->mImpl->app(); + cfg->writeEntry( "KABC_CustomEntry_" + identifier + "_" + + QString::number( custom++ ), customEntry ); + } + } + cfg->writeEntry( identifier, fieldIds ); +} + +Field::List Field::restoreFields( const QString &identifier ) +{ + KConfig *cfg = KGlobal::config(); + KConfigGroupSaver( cfg, "KABCFields" ); + cfg->setGroup( "KABCFields" ); + + Field::List l = restoreFields( cfg, identifier ); + + return l; +} + +Field::List Field::restoreFields( KConfig *cfg, const QString &identifier ) +{ + QValueList<int> fieldIds = cfg->readIntListEntry( identifier); +//US + qDebug("Field::restoreFields from %s", cfg->getFileName().latin1()); + + Field::List fields; + + int custom = 0; + QValueList<int>::ConstIterator it; + for( it = fieldIds.begin(); it != fieldIds.end(); ++it ) { + FieldImpl *f = 0; + if ( (*it) == FieldImpl::CustomField ) { + QStringList customEntry = cfg->readListEntry( "KABC_CustomEntry_" + + identifier + "_" + + QString::number( custom++ ) ); + f = new FieldImpl( *it, CustomCategory, customEntry[ 0 ], + customEntry[ 1 ], customEntry[ 2 ] ); + } else { + f = new FieldImpl( *it ); + } + fields.append( new Field( f ) ); + } + + return fields; +} + +bool Field::equals( Field *field ) +{ + bool sameId = ( mImpl->fieldId() == field->mImpl->fieldId() ); + + if ( !sameId ) return false; + + if ( mImpl->fieldId() != FieldImpl::CustomField ) return true; + + return mImpl->key() == field->mImpl->key(); +} + +Field *Field::createCustomField( const QString &label, int category, + const QString &key, const QString &app ) +{ + Field *field = new Field( new FieldImpl( FieldImpl::CustomField, + category | CustomCategory, + label, key, app ) ); + mCustomFields.append( field ); + + return field; +} diff --git a/kabc/field.h b/kabc/field.h new file mode 100644 index 0000000..9e06597 --- a/dev/null +++ b/kabc/field.h @@ -0,0 +1,178 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_FIELD_H +#define KABC_FIELD_H + +#include <qstring.h> +#include <qvaluelist.h> + +#include "addressee.h" + +class KConfig; + +namespace KABC { + +class Field +{ + class FieldImpl; + friend class FieldImpl; + +public: + typedef QValueList<Field *> List; + + /** + * @li @p All - + * @li @p Frequent - + * @li @p Address - + * @li @p Email - + * @li @p Personal - + * @li @p Organization - + * @li @p CustomCategory - + */ + enum FieldCategory + { + All = 0x0, + Frequent = 0x01, + Address = 0x02, + Email = 0x04, + Personal = 0x08, + Organization = 0x10, + CustomCategory = 0x20 + }; + + /** + * Returns the translated label for this field. + */ + virtual QString label(); + + /** + * Returns the ored categories the field belongs to. + */ + virtual int category(); + + /** + * Returns the translated label for field category. + */ + static QString categoryLabel( int category ); + + /** + * Returns a string representation of the value the field has in the given + * Addressee. Returns QString::null, if it is not possible to convert the + * value to a string. + */ + virtual QString value( const KABC::Addressee & ); + + /** + * Sets the value of the field in the given Addressee. Returns true on success + * or false, if the given string couldn't be converted to a valid value. + */ + virtual bool setValue( KABC::Addressee &, const QString & ); + + /** + * Returns, if the field is a user-defined field. + */ + virtual bool isCustom(); + + /** + * Returns, if the field is equal with @param field. + */ + virtual bool equals( Field *field ); + + /** + * Returns a list of all fields. + */ + static Field::List allFields(); + + /** + * Returns a list of the default fields. + */ + static Field::List defaultFields(); + + /** + * Creates a custom field. + * + * @param label The label for this field + * @param category The category of this field + * @param key Unique key for this field + * @param app Unique app name for this field + */ + static Field *createCustomField( const QString &label, int category, + const QString &key, const QString &app ); + + /** + * Delete all fields from list. + */ + static void deleteFields(); + + /** + * Save the field settings to a config file. + * + * @param cfg The config file object + * @param identifier The unique identifier + * @param fields The list of the fields + */ + static void saveFields( KConfig *cfg, const QString &identifier, + const Field::List &fields ); + /** + * This is the same as above, with the difference, that + * the list is stored in KGlobal::config() in group "KABCFields". + */ + static void saveFields( const QString &identifier, + const Field::List &fields ); + + /** + * Load the field settings from a config file. + * + * @param cfg The config file object + * @param identifier The unique identifier + */ + static Field::List restoreFields( KConfig *cfg, const QString &identifier ); + + /** + * This is the same as above, with the difference, that + * the list is loaded from KGlobal::config() from group "KABCFields". + */ + static Field::List restoreFields( const QString &identifier ); + +protected: + static void createField( int id, int category = 0 ); + static void createDefaultField( int id, int category = 0 ); + +private: + Field( FieldImpl * ); + virtual ~Field(); + + FieldImpl *mImpl; + + static Field::List mAllFields; + static Field::List mDefaultFields; + static Field::List mCustomFields; +}; + +} +#endif diff --git a/kabc/formatfactory.cpp b/kabc/formatfactory.cpp new file mode 100644 index 0000000..2b073d7 --- a/dev/null +++ b/kabc/formatfactory.cpp @@ -0,0 +1,181 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> +#include <klocale.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <kstaticdeleter.h> + +#include <qfile.h> +#include <qstringlist.h> + +#include "vcardformatplugin.h" + +#include "formatfactory.h" + +using namespace KABC; + +FormatFactory *FormatFactory::mSelf = 0; +static KStaticDeleter<FormatFactory> factoryDeleter; + +FormatFactory *FormatFactory::self() +{ + kdDebug(5700) << "FormatFactory::self()" << endl; + + if ( !mSelf ) { +#ifdef KAB_EMBEDDED + mSelf = factoryDeleter.setObject( new FormatFactory ); +#else //KAB_EMBEDDED + factoryDeleter.setObject( mSelf, new FormatFactory ); +#endif //KAB_EMBEDDED + + } + return mSelf; +} + +FormatFactory::FormatFactory() +{ + mFormatList.setAutoDelete( true ); + + // dummy entry for default format + FormatInfo *info = new FormatInfo; + info->library = "<NoLibrary>"; + info->nameLabel = i18n( "vCard" ); + info->descriptionLabel = i18n( "vCard Format" ); + mFormatList.insert( "vcard", info ); + + QStringList list = KGlobal::dirs()->findAllResources( "data" ,"kabc/formats/*.desktop", true, true ); + for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it ) + { +//US KSimpleConfig config( *it, true ); + KConfig config( *it ); + + if ( !config.hasGroup( "Misc" ) || !config.hasGroup( "Plugin" ) ) + continue; + + info = new FormatInfo; + + config.setGroup( "Plugin" ); + QString type = config.readEntry( "Type" ); + info->library = config.readEntry( "X-KDE-Library" ); + + config.setGroup( "Misc" ); + info->nameLabel = config.readEntry( "Name" ); + info->descriptionLabel = config.readEntry( "Comment", i18n( "No description available." ) ); + + mFormatList.insert( type, info ); + } +} + +FormatFactory::~FormatFactory() +{ + mFormatList.clear(); +} + +QStringList FormatFactory::formats() +{ + QStringList retval; + + // make sure 'vcard' is the first entry + retval << "vcard"; + + QDictIterator<FormatInfo> it( mFormatList ); + for ( ; it.current(); ++it ) + if ( it.currentKey() != "vcard" ) + retval << it.currentKey(); + + return retval; +} + +FormatInfo *FormatFactory::info( const QString &type ) +{ + if ( type.isEmpty() ) + return 0; + else + return mFormatList[ type ]; +} + +FormatPlugin *FormatFactory::format( const QString& type ) +{ + FormatPlugin *format = 0; + + if ( type.isEmpty() ) + return 0; + + if ( type == "vcard" ) { + format = new VCardFormatPlugin; + /* // LR + format->setType( type ); + format->setNameLabel( i18n( "vCard" ) ); + format->setDescriptionLabel( i18n( "vCard Format" ) ); + */ + return format; + } + + FormatInfo *fi = mFormatList[ type ]; + if (!fi) + return 0; + QString libName = fi->library; +#ifndef DESKTOP_VERSION + KLibrary *library = openLibrary( libName ); + if ( !library ) + return 0; + + void *format_func = library->symbol( "format" ); + + if ( format_func ) { + format = ((FormatPlugin* (*)())format_func)(); + // LR + /* + format->setType( type ); + format->setNameLabel( fi->nameLabel ); + format->setDescriptionLabel( fi->descriptionLabel ); + */ + } else { + kdDebug( 5700 ) << "'" << libName << "' is not a format plugin." << endl; + return 0; + } +#endif + return format; +} + +#ifndef DESKTOP_VERSION +KLibrary *FormatFactory::openLibrary( const QString& libName ) +{ + KLibrary *library = 0; + + QString path = KLibLoader::findLibrary( QFile::encodeName( libName ) ); + + if ( path.isEmpty() ) { + kdDebug( 5700 ) << "No format plugin library was found!" << endl; + return 0; + } + + library = KLibLoader::self()->library( QFile::encodeName( path ) ); + + if ( !library ) { + kdDebug( 5700 ) << "Could not load library '" << libName << "'" << endl; + return 0; + } + + return library; +} +#endif diff --git a/kabc/formatfactory.h b/kabc/formatfactory.h new file mode 100644 index 0000000..9612374 --- a/dev/null +++ b/kabc/formatfactory.h @@ -0,0 +1,104 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KABC_FORMATFACTORY_H +#define KABC_FORMATFACTORY_H + +#include <qdict.h> +#include <qstring.h> + +#include <kconfig.h> +#ifndef DESKTOP_VERSION +#include <klibloader.h> +#endif + +#include "formatplugin.h" + +namespace KABC { + +struct FormatInfo +{ + QString library; + QString nameLabel; + QString descriptionLabel; +}; + +/** + * Class for loading format plugins. + * + * Example: + * + * <pre> + * KABC::FormatFactory *factory = KABC::FormatFactory::self(); + * + * QStringList list = factory->formats(); + * QStringList::Iterator it; + * for ( it = list.begin(); it != list.end(); ++it ) { + * KABC::FormatPlugin *format = factory->format( (*it) ); + * // do something with format + * } + * </pre> + */ +class FormatFactory +{ + public: + + /** + Destructor. + */ + ~FormatFactory(); + + /** + * Returns the global format factory. + */ + static FormatFactory *self(); + + /** + * Returns a pointer to a format object or a null pointer + * if format type doesn't exist. + * + * @param type The type of the format, returned by @ref formats() + */ + FormatPlugin *format( const QString &type ); + + /** + * Returns a list of all available format types. + */ + QStringList formats(); + + /** + * Returns the info structure for a special type. + */ + FormatInfo *info( const QString &type ); + + protected: + FormatFactory(); + + private: +#ifndef DESKTOP_VERSION + KLibrary *openLibrary( const QString& libName ); +#endif + static FormatFactory *mSelf; + + QDict<FormatInfo> mFormatList; +}; + +} +#endif diff --git a/kabc/formatplugin.h b/kabc/formatplugin.h new file mode 100644 index 0000000..d784daf --- a/dev/null +++ b/kabc/formatplugin.h @@ -0,0 +1,81 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_FORMATPLUGIN_H +#define KABC_FORMATPLUGIN_H + +#include <qfile.h> + +//US #include "plugin.h" +#include "resource.h" + +namespace KABC { + +class AddressBook; +class Addressee; + +/** + * @short Base class for address book formats. + * + * This class provides an abstract interface for ResourceFile and + * ResourceDir formats. + * + * @internal + */ +//US class FormatPlugin : public Plugin +class FormatPlugin +{ +public: + + /** + * Load single addressee from file. + */ + virtual bool load( Addressee &, QFile *file ) = 0; + + /** + * Load whole addressbook from file. + */ + virtual bool loadAll( AddressBook *, Resource *, QFile *file ) = 0; + + /** + * Save a single Addressee to file. + */ + virtual void save( const Addressee &, QFile *file ) = 0; + + /** + * Save whole addressbook to file. + */ + virtual void saveAll( AddressBook *, Resource *, QFile *file ) = 0; + + /** + * Checks if given file contains the right format + */ + virtual bool checkFormat( QFile *file ) const = 0; +}; + +} +#endif diff --git a/kabc/formats/binaryformat.cpp b/kabc/formats/binaryformat.cpp new file mode 100644 index 0000000..e2f28b8 --- a/dev/null +++ b/kabc/formats/binaryformat.cpp @@ -0,0 +1,236 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + + +#include <qdatastream.h> +#include <qimage.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kstandarddirs.h> + +#include "addressbook.h" +#include "addressee.h" +#include "picture.h" +#include "sound.h" + +#include "binaryformat.h" + +#define BINARY_FORMAT_VERSION 2 + +using namespace KABC; + +/*US +extern "C" +{ + FormatPlugin *format() + { + qDebug(" BinaryFormat::format = new BinaryFormat"); + return new BinaryFormat; + } +} +*/ +bool BinaryFormat::load( Addressee &addressee, QFile *file ) +{ + kdDebug(5700) << "BinaryFormat::load()" << endl; + QDataStream stream( file ); + + if ( !checkHeader( stream ) ) + return false; + + loadAddressee( addressee, stream ); + + return true; +} + +bool BinaryFormat::loadAll( AddressBook *addressBook, Resource *resource, QFile *file ) +{ + kdDebug(5700) << "BinaryFormat::loadAll()" << endl; + + QDataStream stream( file ); + + if ( !checkHeader( stream ) ) + return false; + + Q_UINT32 entries; + + stream >> entries; + + for ( uint i = 0; i < entries; ++i ) { + Addressee addressee; + loadAddressee( addressee, stream ); + addressee.setResource( resource ); + addressBook->insertAddressee( addressee ); + } + + return true; +} + +void BinaryFormat::save( const Addressee &addressee, QFile *file ) +{ + kdDebug(5700) << "BinaryFormat::save()" << endl; + + QDataStream stream( file ); + + writeHeader( stream ); + + Q_UINT32 entries = 1; + stream << entries; + saveAddressee( addressee, stream ); +} + +void BinaryFormat::saveAll( AddressBook *ab, Resource *resource, QFile *file ) +{ + kdDebug(5700) << "BinaryFormat::saveAll()" << endl; + + Q_UINT32 counter = 0; + QDataStream stream( file ); + + writeHeader( stream ); + // set dummy number of entries + stream << counter; + + AddressBook::Iterator it; + for ( it = ab->begin(); it != ab->end(); ++it ) { + if ( (*it).resource() == resource ) { + saveAddressee( (*it), stream ); + counter++; + (*it).setChanged( false ); + } + } + + // set real number of entries + stream.device()->at( 2 * sizeof( Q_UINT32 ) ); + stream << counter; +} + +bool BinaryFormat::checkFormat( QFile *file ) const +{ + kdDebug(5700) << "BinaryFormat::checkFormat()" << endl; + + QDataStream stream( file ); + + return checkHeader( stream ); +} + +bool BinaryFormat::checkHeader( QDataStream &stream ) const +{ + Q_UINT32 magic, version; + + stream >> magic >> version; + +//US QFile *file = dynamic_cast<QFile*>( stream.device() ); + QFile *file = (QFile*)( stream.device() ); + + if ( !file ) { + qDebug("BinaryFormat::checkHeader : Not a file?"); + kdError() << i18n("Not a file?") << endl; + return false; + } + + if ( magic != 0x2e93e ) { + qDebug("BinaryFormat::checkHeader : File '%s' is not binary format.", file->name().latin1()); + kdError() << i18n("File '%1' is not binary format.").arg( file->name() ) << endl; + return false; + } + + if ( version != BINARY_FORMAT_VERSION ) { + qDebug("BinaryFormat::checkHeader : File '%s' is the wrong version.", file->name().latin1()); + kdError() << i18n("File '%1' is the wrong version.").arg( file->name() ) << endl; + return false; + } + + return true; +} + +void BinaryFormat::writeHeader( QDataStream &stream ) +{ + Q_UINT32 magic, version; + + magic = 0x2e93e; + version = BINARY_FORMAT_VERSION; + + stream << magic << version; +} + +void BinaryFormat::loadAddressee( Addressee &addressee, QDataStream &stream ) +{ + stream >> addressee; +/* + // load pictures + Picture photo = addressee.photo(); + Picture logo = addressee.logo(); + + if ( photo.isIntern() ) { + QImage img; + if ( !img.load( locateLocal( "data", "kabc/photos/" ) + addressee.uid() ) ) + kdDebug(5700) << "No photo available for '" << addressee.uid() << "'." << endl; + + addressee.setPhoto( img ); + } + + if ( logo.isIntern() ) { + QImage img; + if ( !img.load( locateLocal( "data", "kabc/logos/" ) + addressee.uid() ) ) + kdDebug(5700) << "No logo available for '" << addressee.uid() << "'." << endl; + + addressee.setLogo( img ); + } + + // load sound + // TODO: load sound data from file +*/ +} + +void BinaryFormat::saveAddressee( const Addressee &addressee, QDataStream &stream ) +{ + stream << addressee; +/* + // load pictures + Picture photo = addressee.photo(); + Picture logo = addressee.logo(); + + if ( photo.isIntern() ) { + QImage img = photo.data(); + QString fileName = locateLocal( "data", "kabc/photos/" ) + addressee.uid(); + + if ( !img.save( fileName, "PNG" ) ) + kdDebug(5700) << "Unable to save photo for '" << addressee.uid() << "'." << endl; + } + + if ( logo.isIntern() ) { + QImage img = logo.data(); + QString fileName = locateLocal( "data", "kabc/logos/" ) + addressee.uid(); + + if ( !img.save( fileName, "PNG" ) ) + kdDebug(5700) << "Unable to save logo for '" << addressee.uid() << "'." << endl; + } + + // save sound + // TODO: save the sound data to file +*/ +} diff --git a/kabc/formats/binaryformat.h b/kabc/formats/binaryformat.h new file mode 100644 index 0000000..415fd3b --- a/dev/null +++ b/kabc/formats/binaryformat.h @@ -0,0 +1,76 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_BINARYFORMAT_H +#define KABC_BINARYFORMAT_H + +#include "formatplugin.h" + +namespace KABC { + +class AddressBook; +class Addressee; + +/** + @short binary file format for addressbook entries. +*/ +class BinaryFormat : public FormatPlugin +{ +public: + /** + * Load single addressee from file. + */ + bool load( Addressee &, QFile *file ); + + /** + * Load whole addressee from file. + */ + bool loadAll( AddressBook *, Resource *, QFile *file ); + + /** + * Save single addressee to file. + */ + void save( const Addressee &, QFile *file ); + + /** + * Save all addressees to file. + */ + void saveAll( AddressBook *, Resource *, QFile *file ); + + /** + * Check for valid format of a file. + */ + bool checkFormat( QFile *file ) const; + +private: + void loadAddressee( Addressee &, QDataStream & ); + void saveAddressee( const Addressee &, QDataStream & ); + bool checkHeader( QDataStream & ) const; + void writeHeader( QDataStream & ); +}; + +} +#endif diff --git a/kabc/formats/vcardformatplugin2.cpp b/kabc/formats/vcardformatplugin2.cpp new file mode 100644 index 0000000..2a772b4 --- a/dev/null +++ b/kabc/formats/vcardformatplugin2.cpp @@ -0,0 +1,123 @@ +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include "vcardformatplugin2.h" + +#include "address.h" +#include "addressee.h" +#include "vcardparser/vcardtool.h" + +#include <qtextstream.h> +#include <qfile.h> + +using namespace KABC; + +/*US +extern "C" +{ + FormatPlugin *format() + { + qDebug(" VCardFormatPlugin2::format = new VCardFormatPlugin2"); + return new VCardFormatPlugin2(); + } +} +*/ + +VCardFormatPlugin2::VCardFormatPlugin2() +{ +} + +VCardFormatPlugin2::~VCardFormatPlugin2() +{ +} + +bool VCardFormatPlugin2::load( Addressee &addressee, QFile *file ) +{ + QString data; + + QTextStream t( file ); + t.setEncoding( QTextStream::UnicodeUTF8 ); + data = t.read(); + + VCardTool tool; + + Addressee::List l = tool.parseVCards( data ); + + if ( ! l.first().isEmpty() ) { + addressee = l.first(); + return true; + } + + return false; +} + +bool VCardFormatPlugin2::loadAll( AddressBook *addressBook, Resource *resource, QFile *file ) +{ + QString data; + + QTextStream t( file ); + t.setEncoding( QTextStream::UnicodeUTF8 ); + data = t.read(); + + VCardTool tool; + + Addressee::List l = tool.parseVCards( data ); + + Addressee::List::Iterator itr; + + for ( itr = l.begin(); itr != l.end(); ++itr) { + Addressee addressee = *itr; + addressee.setResource( resource ); + addressBook->insertAddressee( addressee ); + } + + return true; +} + +void VCardFormatPlugin2::save( const Addressee &addressee, QFile *file ) +{ + VCardTool tool; + Addressee::List vcardlist; + + + vcardlist.append( addressee ); + + QTextStream t( file ); + t.setEncoding( QTextStream::UnicodeUTF8 ); + t << tool.createVCards( vcardlist ); +} + +void VCardFormatPlugin2::saveAll( AddressBook *ab, Resource *resource, QFile *file ) +{ + VCardTool tool; + Addressee::List vcardlist; + + AddressBook::Iterator it; + for ( it = ab->begin(); it != ab->end(); ++it ) { + if ( (*it).resource() == resource ) { + (*it).setChanged( false ); + vcardlist.append( *it ); + } + } + + QTextStream t( file ); + t.setEncoding( QTextStream::UnicodeUTF8 ); + t << tool.createVCards( vcardlist ); +} + +bool VCardFormatPlugin2::checkFormat( QFile *file ) const +{ + QString line; + + file->readLine( line, 1024 ); + line = line.stripWhiteSpace(); + if ( line == "BEGIN:VCARD" ) + return true; + else + return false; +} + diff --git a/kabc/formats/vcardformatplugin2.h b/kabc/formats/vcardformatplugin2.h new file mode 100644 index 0000000..585ab6b --- a/dev/null +++ b/kabc/formats/vcardformatplugin2.h @@ -0,0 +1,68 @@ +/* + This file is part of libkabc. + Copyright (c) 2003 Zack Rusin <zack@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef VCARDFORMATPLUGIN2_H +#define VCARDFORMATPLUGIN2_H + +#include "formatplugin.h" +#include "addressee.h" + +class QFile; + +namespace KABC { + + class Resource; + class AddressBook; + /** + @short Interface of vCard backend for address book. + + This class implements the file format interface of address book entries for + the vCard format. + */ + class VCardFormatPlugin2 : public FormatPlugin + { + public: + VCardFormatPlugin2(); + virtual ~VCardFormatPlugin2(); + + bool load( Addressee &, QFile *file ); + bool loadAll( AddressBook *, Resource *, QFile *file ); + void save( const Addressee &, QFile *file ); + void saveAll( AddressBook *, Resource *, QFile *file ); + + bool checkFormat( QFile *file ) const; + + private: + struct VCardFormatPrivate; + VCardFormatPrivate *d; + }; + + +} + + +#endif diff --git a/kabc/geo.cpp b/kabc/geo.cpp new file mode 100644 index 0000000..33597b7 --- a/dev/null +++ b/kabc/geo.cpp @@ -0,0 +1,116 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qdatastream.h> + +#include "geo.h" + +using namespace KABC; + +Geo::Geo() + : mLatitude( 91 ), mLongitude( 181 ), mValidLat( false ), mValidLong( false ) +{ +} + +Geo::Geo( float latitude, float longitude ) +{ + setLatitude( latitude ); + setLongitude( longitude ); +} + +void Geo::setLatitude( float latitude ) +{ + if ( latitude >= -90 && latitude <= 90 ) { + mLatitude = latitude; + mValidLat = true; + } else { + mLatitude = 91; + mValidLat = false; + } +} + +float Geo::latitude() const +{ + return mLatitude; +} + +void Geo::setLongitude( float longitude) +{ + if ( longitude >= -180 && longitude <= 180 ) { + mLongitude = longitude; + mValidLong = true; + } else { + mLongitude = 181; + mValidLong = false; + } +} + +float Geo::longitude() const +{ + return mLongitude; +} + +bool Geo::isValid() const +{ + return mValidLat && mValidLong; +} + +bool Geo::operator==( const Geo &g ) const +{ + if ( !g.isValid() && !isValid() ) return true; + if ( !g.isValid() || !isValid() ) return false; + if ( g.mLatitude == mLatitude && g.mLongitude == mLongitude ) return true; + return false; +} + +bool Geo::operator!=( const Geo &g ) const +{ + if ( !g.isValid() && !isValid() ) return false; + if ( !g.isValid() || !isValid() ) return true; + if ( g.mLatitude == mLatitude && g.mLongitude == mLongitude ) return false; + return true; +} + +QString Geo::asString() const +{ + return "(" + QString::number(mLatitude) + "," + QString::number(mLongitude) + ")"; +} + +QDataStream &KABC::operator<<( QDataStream &s, const Geo &geo ) +{ + return s << (float)geo.mLatitude << (float)geo.mLongitude; +} + +QDataStream &KABC::operator>>( QDataStream &s, Geo &geo ) +{ + s >> geo.mLatitude >> geo.mLongitude; + + geo.mValidLat = true; + geo.mValidLong = true; + + return s; +} diff --git a/kabc/geo.h b/kabc/geo.h new file mode 100644 index 0000000..4c7f90f --- a/dev/null +++ b/kabc/geo.h @@ -0,0 +1,106 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_GEO_H +#define KABC_GEO_H + +#include <qstring.h> + +namespace KABC { + +/** + @short Geographic position + + This class represents a geographic position. +*/ +class Geo +{ + friend QDataStream &operator<<( QDataStream &, const Geo & ); + friend QDataStream &operator>>( QDataStream &, Geo & ); + + public: + /** + Construct invalid geographics position object. + */ + Geo(); + + /** + Construct geographics position object. + + @param latitude Geographical latitude + @param longitude Geographical longitude + */ + Geo( float latitude, float longitude ); + + /** + Sets the latitude. + */ + void setLatitude( float ); + + /** + Returns the latitude. + */ + float latitude() const; + + /** + Sets the longitude. + */ + void setLongitude( float ); + + /** + Returns the longitude. + */ + float longitude() const; + + /** + Returns, if this object contains a valid geographical position. + */ + bool isValid() const; + + bool operator==( const Geo & ) const; + bool operator!=( const Geo & ) const; + + /** + Returns string representation of geographical position. + */ + QString asString() const; + + private: + float mLatitude; + float mLongitude; + + bool mValid; + bool mValidLat; + bool mValidLong; +}; + +QDataStream &operator<<( QDataStream &, const Geo & ); +QDataStream &operator>>( QDataStream &, Geo & ); + +} + +#endif diff --git a/kabc/kabc.pro b/kabc/kabc.pro new file mode 100644 index 0000000..ea4bbb7 --- a/dev/null +++ b/kabc/kabc.pro @@ -0,0 +1,214 @@ +TEMPLATE = lib +CONFIG += qt warn_on +#release debug +DESTDIR=../bin + +TARGET = microkabc + +include( ../variables.pri ) + +INCLUDEPATH += . ./vcard/include ./vcard/include/generated ../microkde ../microkde/kdecore ../microkde/kio/kfile ../qtcompat ../microkde/kdeui + +#LIBS += -lmicrokde -lldap +LIBS += -L$(QPEDIR)/lib +DEFINES += KAB_EMBEDDED DESKTOP_VERSION +unix : { + +OBJECTS_DIR = obj/unix +MOC_DIR = moc/unix +} +win32: { +DEFINES += _WIN32_ +OBJECTS_DIR = obj/win +MOC_DIR = moc/win +} +INTERFACES = \ + + +HEADERS = \ + resource.h \ + stdaddressbook.h \ + agent.h \ + geo.h \ + key.h \ + field.h \ + plugin.h \ + address.h \ + addresseelist.h \ +formatfactory.h \ + formatplugin.h \ + phonenumber.h \ +distributionlist.h \ +distributionlistdialog.h \ +distributionlisteditor.h \ +vcardformatplugin.h \ +formats/binaryformat.h \ +formats/vcardformatplugin2.h \ + picture.h \ + secrecy.h \ + sound.h \ + addressbook.h \ + timezone.h \ + addressee.h \ + addresseedialog.h \ + vcardconverter.h \ + vcard21parser.h \ + vcardformatimpl.h \ + plugins/file/resourcefile.h \ + plugins/file/resourcefileconfig.h \ + plugins/dir/resourcedir.h \ + plugins/dir/resourcedirconfig.h \ + vcardparser/vcardline.h \ + vcardparser/vcard.h \ + vcardparser/vcardtool.h \ + vcardparser/vcardparser.h \ +vcard/include/VCardAdrParam.h \ +vcard/include/VCardAdrValue.h \ +vcard/include/VCardAgentParam.h \ +vcard/include/VCardContentLine.h \ +vcard/include/VCardDateParam.h \ +vcard/include/VCardDateValue.h \ +vcard/include/VCardEmailParam.h \ +vcard/include/VCardGeoValue.h \ +vcard/include/VCardGroup.h \ +vcard/include/VCardImageParam.h \ +vcard/include/VCardImageValue.h \ +vcard/include/VCardLangValue.h \ +vcard/include/VCardNValue.h \ +vcard/include/VCardParam.h \ +vcard/include/VCardPhoneNumberValue.h \ +vcard/include/VCardSourceParam.h \ +vcard/include/VCardTelParam.h \ +vcard/include/VCardTextParam.h \ +vcard/include/VCardTextNSParam.h \ +vcard/include/VCardTextValue.h \ +vcard/include/VCardTextBinParam.h \ +vcard/include/VCardURIValue.h \ +vcard/include/VCardVCard.h \ +vcard/include/VCardEntity.h \ +vcard/include/VCardValue.h \ +vcard/include/VCardSoundValue.h \ +vcard/include/VCardAgentValue.h \ +vcard/include/VCardTelValue.h \ +vcard/include/VCardTextBinValue.h \ +vcard/include/VCardOrgValue.h \ +vcard/include/VCardUTCValue.h \ +vcard/include/VCardClassValue.h \ +vcard/include/VCardFloatValue.h \ +vcard/include/VCardTextListValue.h \ +vcard/include/generated/AdrParam-generated.h \ +vcard/include/generated/AdrValue-generated.h \ +vcard/include/generated/AgentParam-generated.h \ +vcard/include/generated/ContentLine-generated.h \ +vcard/include/generated/DateParam-generated.h \ +vcard/include/generated/DateValue-generated.h \ +vcard/include/generated/EmailParam-generated.h \ +vcard/include/generated/GeoValue-generated.h \ +vcard/include/generated/Group-generated.h \ +vcard/include/generated/ImageParam-generated.h \ +vcard/include/generated/ImageValue-generated.h \ +vcard/include/generated/LangValue-generated.h \ +vcard/include/generated/NValue-generated.h \ +vcard/include/generated/Param-generated.h \ +vcard/include/generated/PhoneNumberValue-generated.h \ +vcard/include/generated/SourceParam-generated.h \ +vcard/include/generated/TelParam-generated.h \ +vcard/include/generated/TextParam-generated.h \ +vcard/include/generated/TextNSParam-generated.h \ +vcard/include/generated/TextValue-generated.h \ +vcard/include/generated/TextBinParam-generated.h \ +vcard/include/generated/URIValue-generated.h \ +vcard/include/generated/VCard-generated.h \ +vcard/include/generated/VCardEntity-generated.h \ +vcard/include/generated/Value-generated.h \ +vcard/include/generated/SoundValue-generated.h \ +vcard/include/generated/AgentValue-generated.h \ +vcard/include/generated/TelValue-generated.h \ +vcard/include/generated/TextBinValue-generated.h \ +vcard/include/generated/OrgValue-generated.h \ +vcard/include/generated/UTCValue-generated.h \ +vcard/include/generated/ClassValue-generated.h \ +vcard/include/generated/FloatValue-generated.h \ +vcard/include/generated/TextListValue-generated.h + + +# plugins/ldap/resourceldap.h \ +# plugins/ldap/resourceldapconfig.h \ + + +SOURCES = \ +distributionlist.cpp \ +distributionlistdialog.cpp \ +distributionlisteditor.cpp \ +vcardformatplugin.cpp \ +formats/binaryformat.cpp \ +formats/vcardformatplugin2.cpp \ +formatfactory.cpp \ + resource.cpp \ + stdaddressbook.cpp \ + plugin.cpp \ + agent.cpp \ + geo.cpp \ + key.cpp \ + field.cpp \ + address.cpp \ + phonenumber.cpp \ + picture.cpp \ + secrecy.cpp \ + sound.cpp \ + addressbook.cpp \ + timezone.cpp \ + addressee.cpp \ + addresseelist.cpp \ + addresseedialog.cpp \ + vcardconverter.cpp \ + vcard21parser.cpp \ + vcardformatimpl.cpp \ + plugins/file/resourcefile.cpp \ + plugins/file/resourcefileconfig.cpp \ + plugins/dir/resourcedir.cpp \ + plugins/dir/resourcedirconfig.cpp \ + vcardparser/vcardline.cpp \ + vcardparser/vcard.cpp \ + vcardparser/vcardtool.cpp \ + vcardparser/vcardparser.cpp \ +vcard/AdrParam.cpp \ +vcard/AdrValue.cpp \ +vcard/AgentParam.cpp \ +vcard/ContentLine.cpp \ +vcard/DateParam.cpp \ +vcard/DateValue.cpp \ +vcard/EmailParam.cpp \ +vcard/Entity.cpp \ +vcard/Enum.cpp \ +vcard/GeoValue.cpp \ +vcard/ImageParam.cpp \ +vcard/ImageValue.cpp \ +vcard/LangValue.cpp \ +vcard/NValue.cpp \ +vcard/Param.cpp \ +vcard/PhoneNumberValue.cpp \ +vcard/RToken.cpp \ +vcard/SourceParam.cpp \ +vcard/TelParam.cpp \ +vcard/TextParam.cpp \ +vcard/TextValue.cpp \ +vcard/TextBinParam.cpp \ +vcard/URIValue.cpp \ +vcard/VCardv.cpp \ +vcard/VCardEntity.cpp \ +vcard/Value.cpp \ +vcard/SoundValue.cpp \ +vcard/AgentValue.cpp \ +vcard/TelValue.cpp \ +vcard/TextBinValue.cpp \ +vcard/OrgValue.cpp \ +vcard/UTCValue.cpp \ +vcard/ClassValue.cpp \ +vcard/FloatValue.cpp \ +vcard/TextListValue.cpp + + +# plugins/ldap/resourceldap.cpp \ +# plugins/ldap/resourceldapconfig.cpp \ + diff --git a/kabc/kabcE.pro b/kabc/kabcE.pro new file mode 100644 index 0000000..6c37beb --- a/dev/null +++ b/kabc/kabcE.pro @@ -0,0 +1,202 @@ +TEMPLATE = lib +CONFIG += qt warn_on +TARGET = microkabc + + +INCLUDEPATH += . ./vcard/include ./vcard/include/generated ../microkde ../microkde/kdecore ../microkde/kdeui ../microkde/kio/kfile ../qtcompat +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR = $(QPEDIR)/lib +LIBS += -lmicrokde +#LIBS += -lldap +LIBS += -L$(QPEDIR)/lib +DEFINES += KAB_EMBEDDED + +INTERFACES = \ + +HEADERS = \ + resource.h \ + stdaddressbook.h \ + agent.h \ + geo.h \ + key.h \ + field.h \ + plugin.h \ + address.h \ + addresseelist.h \ +formatfactory.h \ + formatplugin.h \ + phonenumber.h \ +distributionlist.h \ +distributionlistdialog.h \ +distributionlisteditor.h \ +vcardformatplugin.h \ +formats/binaryformat.h \ +formats/vcardformatplugin2.h \ + picture.h \ + secrecy.h \ + sound.h \ + addressbook.h \ + timezone.h \ + addressee.h \ + addresseedialog.h \ + vcardconverter.h \ + vcard21parser.h \ + vcardformatimpl.h \ + plugins/file/resourcefile.h \ + plugins/file/resourcefileconfig.h \ + plugins/dir/resourcedir.h \ + plugins/dir/resourcedirconfig.h \ + vcardparser/vcardline.h \ + vcardparser/vcard.h \ + vcardparser/vcardtool.h \ + vcardparser/vcardparser.h \ +vcard/include/VCardAdrParam.h \ +vcard/include/VCardAdrValue.h \ +vcard/include/VCardAgentParam.h \ +vcard/include/VCardContentLine.h \ +vcard/include/VCardDateParam.h \ +vcard/include/VCardDateValue.h \ +vcard/include/VCardEmailParam.h \ +vcard/include/VCardGeoValue.h \ +vcard/include/VCardGroup.h \ +vcard/include/VCardImageParam.h \ +vcard/include/VCardImageValue.h \ +vcard/include/VCardLangValue.h \ +vcard/include/VCardNValue.h \ +vcard/include/VCardParam.h \ +vcard/include/VCardPhoneNumberValue.h \ +vcard/include/VCardSourceParam.h \ +vcard/include/VCardTelParam.h \ +vcard/include/VCardTextParam.h \ +vcard/include/VCardTextNSParam.h \ +vcard/include/VCardTextValue.h \ +vcard/include/VCardTextBinParam.h \ +vcard/include/VCardURIValue.h \ +vcard/include/VCardVCard.h \ +vcard/include/VCardEntity.h \ +vcard/include/VCardValue.h \ +vcard/include/VCardSoundValue.h \ +vcard/include/VCardAgentValue.h \ +vcard/include/VCardTelValue.h \ +vcard/include/VCardTextBinValue.h \ +vcard/include/VCardOrgValue.h \ +vcard/include/VCardUTCValue.h \ +vcard/include/VCardClassValue.h \ +vcard/include/VCardFloatValue.h \ +vcard/include/VCardTextListValue.h \ +vcard/include/generated/AdrParam-generated.h \ +vcard/include/generated/AdrValue-generated.h \ +vcard/include/generated/AgentParam-generated.h \ +vcard/include/generated/ContentLine-generated.h \ +vcard/include/generated/DateParam-generated.h \ +vcard/include/generated/DateValue-generated.h \ +vcard/include/generated/EmailParam-generated.h \ +vcard/include/generated/GeoValue-generated.h \ +vcard/include/generated/Group-generated.h \ +vcard/include/generated/ImageParam-generated.h \ +vcard/include/generated/ImageValue-generated.h \ +vcard/include/generated/LangValue-generated.h \ +vcard/include/generated/NValue-generated.h \ +vcard/include/generated/Param-generated.h \ +vcard/include/generated/PhoneNumberValue-generated.h \ +vcard/include/generated/SourceParam-generated.h \ +vcard/include/generated/TelParam-generated.h \ +vcard/include/generated/TextParam-generated.h \ +vcard/include/generated/TextNSParam-generated.h \ +vcard/include/generated/TextValue-generated.h \ +vcard/include/generated/TextBinParam-generated.h \ +vcard/include/generated/URIValue-generated.h \ +vcard/include/generated/VCard-generated.h \ +vcard/include/generated/VCardEntity-generated.h \ +vcard/include/generated/Value-generated.h \ +vcard/include/generated/SoundValue-generated.h \ +vcard/include/generated/AgentValue-generated.h \ +vcard/include/generated/TelValue-generated.h \ +vcard/include/generated/TextBinValue-generated.h \ +vcard/include/generated/OrgValue-generated.h \ +vcard/include/generated/UTCValue-generated.h \ +vcard/include/generated/ClassValue-generated.h \ +vcard/include/generated/FloatValue-generated.h \ +vcard/include/generated/TextListValue-generated.h + + +# plugins/ldap/resourceldap.h \ +# plugins/ldap/resourceldapconfig.h \ + + +SOURCES = \ +distributionlist.cpp \ +distributionlistdialog.cpp \ +distributionlisteditor.cpp \ +vcardformatplugin.cpp \ +formats/binaryformat.cpp \ +formats/vcardformatplugin2.cpp \ +formatfactory.cpp \ + resource.cpp \ + stdaddressbook.cpp \ + plugin.cpp \ + agent.cpp \ + geo.cpp \ + key.cpp \ + field.cpp \ + address.cpp \ + phonenumber.cpp \ + picture.cpp \ + secrecy.cpp \ + sound.cpp \ + addressbook.cpp \ + timezone.cpp \ + addressee.cpp \ + addresseelist.cpp \ + addresseedialog.cpp \ + vcardconverter.cpp \ + vcard21parser.cpp \ + vcardformatimpl.cpp \ + plugins/file/resourcefile.cpp \ + plugins/file/resourcefileconfig.cpp \ + plugins/dir/resourcedir.cpp \ + plugins/dir/resourcedirconfig.cpp \ + vcardparser/vcardline.cpp \ + vcardparser/vcard.cpp \ + vcardparser/vcardtool.cpp \ + vcardparser/vcardparser.cpp \ +vcard/AdrParam.cpp \ +vcard/AdrValue.cpp \ +vcard/AgentParam.cpp \ +vcard/ContentLine.cpp \ +vcard/DateParam.cpp \ +vcard/DateValue.cpp \ +vcard/EmailParam.cpp \ +vcard/Entity.cpp \ +vcard/Enum.cpp \ +vcard/GeoValue.cpp \ +vcard/ImageParam.cpp \ +vcard/ImageValue.cpp \ +vcard/LangValue.cpp \ +vcard/NValue.cpp \ +vcard/Param.cpp \ +vcard/PhoneNumberValue.cpp \ +vcard/RToken.cpp \ +vcard/SourceParam.cpp \ +vcard/TelParam.cpp \ +vcard/TextParam.cpp \ +vcard/TextValue.cpp \ +vcard/TextBinParam.cpp \ +vcard/URIValue.cpp \ +vcard/VCardv.cpp \ +vcard/VCardEntity.cpp \ +vcard/Value.cpp \ +vcard/SoundValue.cpp \ +vcard/AgentValue.cpp \ +vcard/TelValue.cpp \ +vcard/TextBinValue.cpp \ +vcard/OrgValue.cpp \ +vcard/UTCValue.cpp \ +vcard/ClassValue.cpp \ +vcard/FloatValue.cpp \ +vcard/TextListValue.cpp + + +# plugins/ldap/resourceldap.cpp \ +# plugins/ldap/resourceldapconfig.cpp \ diff --git a/kabc/key.cpp b/kabc/key.cpp new file mode 100644 index 0000000..802424b --- a/dev/null +++ b/kabc/key.cpp @@ -0,0 +1,160 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <kapplication.h> +#include <klocale.h> + +#include "key.h" + +using namespace KABC; + +Key::Key( const QString &text, int type ) + : mTextData( text ), mIsBinary( false ), mType( type ) +{ + mId = KApplication::randomString(8); +} + +Key::~Key() +{ +} + +bool Key::operator==( const Key &k ) const +{ + if ( mIsBinary != k.mIsBinary ) return false; + if ( mIsBinary ) + if ( mBinaryData != k.mBinaryData ) return false; + else + if ( mTextData != k.mTextData ) return false; + if ( mType != k.mType ) return false; + if ( mCustomTypeString != k.mCustomTypeString ) return false; + + return true; +} + +bool Key::operator!=( const Key &k ) const +{ + return !( k == *this ); +} + +void Key::setId( const QString &id ) +{ + mId = id; +} + +QString Key::id() const +{ + return mId; +} + +void Key::setBinaryData( const QByteArray &binary ) +{ + mBinaryData = binary; + mIsBinary = true; +} + +QByteArray Key::binaryData() const +{ + return mBinaryData; +} + +void Key::setTextData( const QString &text ) +{ + mTextData = text; + mIsBinary = false; +} + +QString Key::textData() const +{ + return mTextData; +} + +bool Key::isBinary() const +{ + return mIsBinary; +} + +void Key::setType( int type ) +{ + mType = type; +} + +void Key::setCustomTypeString( const QString &custom ) +{ + mCustomTypeString = custom; +} + +int Key::type() const +{ + return mType; +} + +QString Key::customTypeString() const +{ + return mCustomTypeString; +} + +Key::TypeList Key::typeList() +{ + TypeList list; + list << X509; + list << PGP; + list << Custom; + + return list; +} + +QString Key::typeLabel( int type ) +{ + switch ( type ) { + case X509: + return i18n( "X509" ); + break; + case PGP: + return i18n( "PGP" ); + break; + case Custom: + return i18n( "Custom" ); + break; + default: + return i18n( "Unknown type" ); + break; + } +} + +QDataStream &KABC::operator<<( QDataStream &s, const Key &key ) +{ + return s << key.mId << key.mIsBinary << key.mTextData << key.mBinaryData << + key.mCustomTypeString << key.mType; +} + +QDataStream &KABC::operator>>( QDataStream &s, Key &key ) +{ + s >> key.mId >> key.mIsBinary >> key.mTextData >> key.mBinaryData >> + key.mCustomTypeString >> key.mType; + + return s; +} diff --git a/kabc/key.h b/kabc/key.h new file mode 100644 index 0000000..6ea5b47 --- a/dev/null +++ b/kabc/key.h @@ -0,0 +1,155 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_KEY_H +#define KABC_KEY_H + +#include <qvaluelist.h> + +namespace KABC { + +/** + * @short A class to store an encryption key. + */ +class Key +{ + friend QDataStream &operator<<( QDataStream &, const Key & ); + friend QDataStream &operator>>( QDataStream &, Key & ); + +public: + typedef QValueList<Key> List; + typedef QValueList<int> TypeList; + + /** + * Key types + * + * @li X509 - X509 key + * @li PGP - Pretty Good Privacy key + * @li Custom - Custom or IANA conform key + */ + enum Types { + X509, + PGP, + Custom + }; + + /** + * Constructor. + * + * @param text The text data. + * @param type The key type, @see Types. + */ + Key( const QString &text = QString::null, int type = PGP ); + + /** + * Destructor. + */ + ~Key(); + + bool operator==( const Key & ) const; + bool operator!=( const Key & ) const; + + /** + * Sets the unique identifier. + */ + void setId( const QString &id ); + + /** + * Returns the unique identifier. + */ + QString id() const; + + /** + * Sets binary data. + */ + void setBinaryData( const QByteArray &binary ); + + /** + * Returns the binary data. + */ + QByteArray binaryData() const; + + /** + * Sets text data. + */ + void setTextData( const QString &text ); + + /** + * Returns the text data. + */ + QString textData() const; + + /** + * Returns whether the key contains binary or text data. + */ + bool isBinary() const; + + /** + * Sets the type, @see Type. + */ + void setType( int type ); + + /** + * Sets custom type string. + */ + void setCustomTypeString( const QString &custom ); + + /** + * Returns the type, @see Type. + */ + int type() const; + + /** + * Returns the custom type string. + */ + QString customTypeString() const; + + /** + * Returns a list of all available key types. + */ + static TypeList typeList(); + + /** + * Returns a translated label for a given key type. + */ + static QString typeLabel( int type ); + +private: + QByteArray mBinaryData; + QString mId; + QString mTextData; + QString mCustomTypeString; + + int mIsBinary; + int mType; +}; + +QDataStream &operator<<( QDataStream &, const Key & ); +QDataStream &operator>>( QDataStream &, Key & ); + +} +#endif diff --git a/kabc/phonenumber.cpp b/kabc/phonenumber.cpp new file mode 100644 index 0000000..ad3e65b --- a/dev/null +++ b/kabc/phonenumber.cpp @@ -0,0 +1,204 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <kapplication.h> +#include <klocale.h> + +#include "phonenumber.h" + +using namespace KABC; + +PhoneNumber::PhoneNumber() : + mType( Home ) +{ + init(); +} + +PhoneNumber::PhoneNumber( const QString &number, int type ) : + mType( type ), mNumber( number ) +{ + init(); +} + +PhoneNumber::~PhoneNumber() +{ +} + +void PhoneNumber::init() +{ + mId = KApplication::randomString( 8 ); +} + +bool PhoneNumber::operator==( const PhoneNumber &p ) const +{ + if ( mNumber != p.mNumber ) return false; + if ( mType != p.mType ) return false; + + return true; +} + +bool PhoneNumber::operator!=( const PhoneNumber &p ) const +{ + return !( p == *this ); +} + +void PhoneNumber::setId( const QString &id ) +{ + mId = id; +} + +QString PhoneNumber::id() const +{ + return mId; +} + +void PhoneNumber::setNumber( const QString &number ) +{ + mNumber = number; +} + +QString PhoneNumber::number() const +{ + return mNumber; +} + +void PhoneNumber::setType( int type ) +{ + mType = type; +} + +int PhoneNumber::type() const +{ + return mType; +} + +QString PhoneNumber::typeLabel() const +{ + QString label; + bool first = true; + + TypeList list = typeList(); + + TypeList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + if ( ( type() & (*it) ) && ( (*it) != Pref ) ) { + label.append( ( first ? "" : "/" ) + typeLabel( *it ) ); + if ( first ) + first = false; + } + } + + return label; +} + +QString PhoneNumber::label() const +{ + return typeLabel( type() ); +} + +PhoneNumber::TypeList PhoneNumber::typeList() +{ + TypeList list; + + list << Home << Work << Msg << Pref << Voice << Fax << Cell << Video + << Bbs << Modem << Car << Isdn << Pcs << Pager; + + return list; +} + +QString PhoneNumber::label( int type ) +{ + return typeLabel( type ); +} + +QString PhoneNumber::typeLabel( int type ) +{ + switch ( type ) { + case Home: + return i18n("Home phone", "Home"); + break; + case Work: + return i18n("Work phone", "Work"); + break; + case Msg: + return i18n("Messenger"); + break; + case Pref: + return i18n("Preferred Number"); + break; + case Voice: + return i18n("Voice"); + break; + case Fax: + return i18n("Fax"); + break; + case Cell: + return i18n("Mobile Phone", "Mobile" ); + break; + case Video: + return i18n("Video"); + break; + case Bbs: + return i18n("Mailbox"); + break; + case Modem: + return i18n("Modem"); + break; + case Car: + return i18n("Car Phone", "Car" ); + break; + case Isdn: + return i18n("ISDN"); + break; + case Pcs: + return i18n("PCS"); + break; + case Pager: + return i18n("Pager"); + break; + case Home | Fax: + return i18n("Home Fax"); + break; + case Work | Fax: + return i18n("Work Fax"); + break; + default: + return i18n("Other"); + } +} + +QDataStream &KABC::operator<<( QDataStream &s, const PhoneNumber &phone ) +{ + return s << phone.mId << phone.mType << phone.mNumber; +} + +QDataStream &KABC::operator>>( QDataStream &s, PhoneNumber &phone ) +{ + s >> phone.mId >> phone.mType >> phone.mNumber; + + return s; +} diff --git a/kabc/phonenumber.h b/kabc/phonenumber.h new file mode 100644 index 0000000..6a9c8cb --- a/dev/null +++ b/kabc/phonenumber.h @@ -0,0 +1,165 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_PHONENUMBER_H +#define KABC_PHONENUMBER_H + +#include <qvaluelist.h> +#include <qstring.h> + +namespace KABC { + +/** + @short Phonenumber information. + + This class provides phone number information. A phone number is classified by + a type. The following types are available, it's possible to use multiple types + @ref Types for a number by combining them through a logical or. +*/ +class PhoneNumber +{ + friend QDataStream &operator<<( QDataStream &, const PhoneNumber & ); + friend QDataStream &operator>>( QDataStream &, PhoneNumber & ); + + public: + typedef QValueList<PhoneNumber> List; + typedef QValueList<int> TypeList; + + /** + @li @p Home - Home number + @li @p Work - Office number + @li @p Msg - Messaging + @li @p Pref - Preferred number + @li @p Voice - Voice + @li @p Fax - Fax machine + @li @p Cell - Cell phone + @li @p Video - Video phone + @li @p Bbs - Mailbox + @li @p Modem - Modem + @li @p Car - Car phone + @li @p Isdn - ISDN connection + @li @p Pcs - Personal Communication Service + @li @p Pager - Pager + */ + 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 }; + + /** + Create an empty phone number object. + */ + PhoneNumber(); + + /** + Create a phonenumber object. + + @param number Number + @param type Type as defined in enum. Multiple types can be + specified by combining them by a logical or. + */ + PhoneNumber( const QString &number, int type = Home ); + + /** + Destructor. + */ + ~PhoneNumber(); + + bool operator==( const PhoneNumber & ) const; + bool operator!=( const PhoneNumber & ) const; + + /** + Sets the unique identifier. + */ + void setId( const QString &id ); + + /** + Returns the unique identifier. + */ + QString id() const; + + /** + Sets the number. + */ + void setNumber( const QString & ); + + /** + Returns the number. + */ + QString number() const; + + /** + Sets the type. Multiple types can be specified by combining them by + a logical or. + */ + void setType( int ); + + /** + Returns the type. Can be a multiple types combined by a logical or. + */ + int type() const; + + /** + Returns a translated string of all types the address has. + */ + QString typeLabel() const; + + /** + Returns the translated label for phone number depending on its type. + */ + QString label() const; + + /** + Returns a list of all available types + */ + static TypeList typeList(); + + /** + Returns the translated label for phone number type. + */ + static QString typeLabel( int type ); + + /** + Returns the translated label for phone number type. + @obsolete + */ + static QString label( int type ); + + private: + void init(); + + QString mId; + + int mType; + QString mNumber; +}; + +QDataStream &operator<<( QDataStream &, const PhoneNumber & ); +QDataStream &operator>>( QDataStream &, PhoneNumber & ); + +} + +#endif diff --git a/kabc/picture.cpp b/kabc/picture.cpp new file mode 100644 index 0000000..6a34b98 --- a/dev/null +++ b/kabc/picture.cpp @@ -0,0 +1,141 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include "picture.h" + +using namespace KABC; + +Picture::Picture() + : mIntern( false ) +{ + mUndefined = true; +} + +Picture::Picture( const QString &url ) + : mUrl( url ), mIntern( false ) +{ + mUndefined = false; +} + +Picture::Picture( const QImage &data ) + : mData( data ), mIntern( true ) +{ + mUndefined = false; +} + +Picture::~Picture() +{ +} + +bool Picture::operator==( const Picture &p ) const +{ + if ( mIntern != p.mIntern ) return false; + + if ( mIntern ) { + if ( mData != p.mData ) + return false; + } else { + if ( mUrl != p.mUrl ) + return false; + } + + return true; +} + +bool Picture::operator!=( const Picture &p ) const +{ + return !( p == *this ); +} + +void Picture::setUrl( const QString &url ) +{ + mUrl = url; + mIntern = false; + mUndefined = false; +} + +void Picture::setData( const QImage &data ) +{ + mData = data; + mIntern = true; + mUndefined = false; +} + +void Picture::setType( const QString &type ) +{ + mType = type; +} + +bool Picture::isIntern() const +{ + return mIntern; +} + +QString Picture::url() const +{ + return mUrl; +} + +QImage Picture::data() const +{ + return mData; +} +QPixmap Picture::pixmap() const +{ + QPixmap p; + p.convertFromImage ( mData ); + return p; +} + +QString Picture::type() const +{ + return mType; +} +bool Picture::undefined() const +{ + return mUndefined; +} + + +QString Picture::asString() const +{ + if ( mIntern ) + return "intern picture"; + else + return mUrl; +} + +QDataStream &KABC::operator<<( QDataStream &s, const Picture &picture ) +{ + return s << picture.mIntern << picture.mUrl << picture.mType << picture.mData; +} + +QDataStream &KABC::operator>>( QDataStream &s, Picture &picture ) +{ + s >> picture.mIntern >> picture.mUrl >> picture.mType >> picture.mData; + return s; +} diff --git a/kabc/picture.h b/kabc/picture.h new file mode 100644 index 0000000..714d1e2 --- a/dev/null +++ b/kabc/picture.h @@ -0,0 +1,134 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_PICTURE_H +#define KABC_PICTURE_H + +#include <qimage.h> + +namespace KABC { + +class Picture +{ + friend QDataStream &operator<<( QDataStream &, const Picture & ); + friend QDataStream &operator>>( QDataStream &, Picture & ); + +public: + + /** + * Consturctor. Creates an empty object. + */ + Picture(); + + /** + * Consturctor. + * + * @param url A URL that describes the position of the picture file. + */ + Picture( const QString &url ); + + /** + * Consturctor. + * + * @param data The raw data of the picture. + */ + Picture( const QImage &data ); + + /** + * Destructor. + */ + ~Picture(); + + bool undefined() const; + bool operator==( const Picture & ) const; + bool operator!=( const Picture & ) const; + + /** + * Sets a URL for the location of the picture file. When using this + * function, @ref isIntern() will return 'false' until you use + * @ref setData(). + * + * @param url The location URL of the picture file. + */ + void setUrl( const QString &url ); + + /** + * Sets the raw data of the picture. When using this function, + * @ref isIntern() will return 'true' until you use @ref setUrl(). + * + * @param data The raw data of the picture. + */ + void setData( const QImage &data ); + + /** + * Sets the type of the picture. + */ + void setType( const QString &type ); + + /** + * Returns whether the picture is described by a URL (extern) or + * by the raw data (intern). + * When this method returns 'true' you can use @ref data() to + * get the raw data. Otherwise you can request the URL of this + * picture by @ref url() and load the raw data from that location. + */ + bool isIntern() const; + + /** + * Returns the location URL of this picture. + */ + QString url() const; + + /** + * Returns the raw data of this picture. + */ + QImage data() const; + QPixmap pixmap() const; + /** + * Returns the type of this picture. + */ + QString type() const; + + /** + * Returns string representation of the picture. + */ + QString asString() const; + +private: + QString mUrl; + QString mType; + QImage mData; + bool mUndefined; + + int mIntern; +}; + +QDataStream &operator<<( QDataStream &, const Picture & ); +QDataStream &operator>>( QDataStream &, Picture & ); + +} +#endif diff --git a/kabc/plugin.cpp b/kabc/plugin.cpp new file mode 100644 index 0000000..16c7e86 --- a/dev/null +++ b/kabc/plugin.cpp @@ -0,0 +1,61 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "plugin.h" + +using namespace KABC; + +Plugin::Plugin() +{ +} + +Plugin::~Plugin() +{ +} + +void Plugin::setType( const QString& type ) +{ + mType = type; +} + +QString Plugin::type() const +{ + return mType; +} + +void Plugin::setNameLabel( const QString& label ) +{ + mNameLabel = label; +} + +QString Plugin::nameLabel() const +{ + return mNameLabel; +} + +void Plugin::setDescriptionLabel( const QString& label ) +{ + mDescriptionLabel = label; +} + +QString Plugin::descriptionLabel() const +{ + return mDescriptionLabel; +} diff --git a/kabc/plugin.h b/kabc/plugin.h new file mode 100644 index 0000000..122a995 --- a/dev/null +++ b/kabc/plugin.h @@ -0,0 +1,50 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KABC_PLUGIN_H +#define KABC_PLUGIN_H + +#include <qstring.h> + +namespace KABC { + +class Plugin +{ +public: + Plugin(); + virtual ~Plugin(); + + virtual void setType( const QString& type ); + virtual QString type() const; + + virtual void setNameLabel( const QString& label ); + virtual QString nameLabel() const; + + virtual void setDescriptionLabel( const QString& label ); + virtual QString descriptionLabel() const; + +private: + QString mType; + QString mNameLabel; + QString mDescriptionLabel; +}; + +} +#endif diff --git a/kabc/plugins/dir/resourcedir.cpp b/kabc/plugins/dir/resourcedir.cpp new file mode 100644 index 0000000..f354a9e --- a/dev/null +++ b/kabc/plugins/dir/resourcedir.cpp @@ -0,0 +1,363 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + + +#include <sys/types.h> +#include <sys/stat.h> +#ifndef _WIN32_ +#include <unistd.h> +#endif + +#include <qregexp.h> +#include <qtimer.h> +#include <qwidget.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +//US #include <kgenericfactory.h> +#include <kglobal.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kurlrequester.h> + +#include "addressbook.h" + +//US #include "formatfactory.h" + +#include "resourcedirconfig.h" +#include "stdaddressbook.h" + +//US +#include <qdir.h> +#include <formats/vcardformatplugin2.h> +#include <formats/binaryformat.h> + +#include "resourcedir.h" + +using namespace KABC; + +extern "C" +{ + void *init_kabc_dir() + { + qDebug("resourcedir.cpp : init_kabc_dir has to be changed"); +//US return new KRES::PluginFactory<ResourceDir,ResourceDirConfig>(); + return 0; + } +} + + +ResourceDir::ResourceDir( const KConfig *config ) + : Resource( config ) +{ + QString path; + + KConfig *cfg = (KConfig *)config; + if ( cfg ) { +//US path = config->readEntry( "FilePath" ); + path = cfg->readEntry( "FilePath", StdAddressBook::directoryName() ); +//US mFormatName = config->readEntry( "FileFormat" ); + mFormatName = cfg->readEntry( "FileFormat", "vcard" ); + } else { + path = StdAddressBook::directoryName(); + mFormatName = "vcard"; + } + + +/*US FormatFactory *factory = FormatFactory::self(); + mFormat = factory->format( mFormatName ); + + if ( !mFormat ) { + mFormatName = "vcard"; + mFormat = factory->format( mFormatName ); + } +*/ + +//US qDebug("ResourceDir::ResourceDir initialized with format %s ", mFormatName.latin1()); + if (mFormatName == "vcard") + mFormat = new VCardFormatPlugin2(); + else if (mFormatName == "binary") + mFormat = new BinaryFormat(); + else + qDebug("ResourceFile::init format unknown !!! %s ", mFormatName.latin1()); + + +/*US we have no KDirWatch. SO simulate the signals from inside the apropriate methods + connect( &mDirWatch, SIGNAL( dirty(const QString&) ), SLOT( pathChanged() ) ); + connect( &mDirWatch, SIGNAL( created(const QString&) ), SLOT( pathChanged() ) ); + connect( &mDirWatch, SIGNAL( deleted(const QString&) ), SLOT( pathChanged() ) ); +*/ + + setPath( path ); +} + +ResourceDir::~ResourceDir() +{ + delete mFormat; + mFormat = 0; +} + +void ResourceDir::writeConfig( KConfig *config ) +{ + Resource::writeConfig( config ); + + config->writeEntry( "FilePath", mPath ); + config->writeEntry( "FileFormat", mFormatName ); +} + +Ticket *ResourceDir::requestSaveTicket() +{ + kdDebug(5700) << "ResourceDir::requestSaveTicket()" << endl; + + if ( !addressBook() ) return 0; + + if ( !lock( mPath ) ) { + kdDebug(5700) << "ResourceDir::requestSaveTicket(): Unable to lock path '" + << mPath << "'" << endl; + return 0; + } + return createTicket( this ); +} + + +bool ResourceDir::doOpen() +{ + QDir dir( mPath ); + if ( !dir.exists() ) { // no directory available + return dir.mkdir( dir.path() ); + } else { + QString testName = dir.entryList( QDir::Files )[0]; + if ( testName.isNull() || testName.isEmpty() ) // no file in directory + return true; + + QFile file( mPath + "/" + testName ); + if ( file.open( IO_ReadOnly ) ) + return true; + + if ( file.size() == 0 ) + return true; + + bool ok = mFormat->checkFormat( &file ); + file.close(); + return ok; + } +} + +void ResourceDir::doClose() +{ +} + +bool ResourceDir::load() +{ + kdDebug(5700) << "ResourceDir::load(): '" << mPath << "'" << endl; + + QDir dir( mPath ); + QStringList files = dir.entryList( QDir::Files ); + + QStringList::Iterator it; + bool ok = true; + for ( it = files.begin(); it != files.end(); ++it ) { + QFile file( mPath + "/" + (*it) ); + + if ( !file.open( IO_ReadOnly ) ) { + addressBook()->error( i18n( "Unable to open file '%1' for reading" ).arg( file.name() ) ); + ok = false; + continue; + } + + if ( !mFormat->loadAll( addressBook(), this, &file ) ) + ok = false; + + file.close(); + } + + return ok; +} + +bool ResourceDir::save( Ticket *ticket ) +{ + kdDebug(5700) << "ResourceDir::save(): '" << mPath << "'" << endl; + + AddressBook::Iterator it; + bool ok = true; + + for ( it = addressBook()->begin(); it != addressBook()->end(); ++it ) { + if ( (*it).resource() != this || !(*it).changed() ) + continue; + + QFile file( mPath + "/" + (*it).uid() ); + if ( !file.open( IO_WriteOnly ) ) { + addressBook()->error( i18n( "Unable to open file '%1' for writing" ).arg( file.name() ) ); + continue; + } + + mFormat->save( *it, &file ); + + // mark as unchanged + (*it).setChanged( false ); + + file.close(); + } + + delete ticket; + unlock( mPath ); + + return ok; +} + +bool ResourceDir::lock( const QString &path ) +{ + kdDebug(5700) << "ResourceDir::lock()" << endl; + + QString p = path; +//US change the implementation how the lockfilename is getting created +//US p.replace( QRegExp("/"), "_" ); +//US QString lockName = locateLocal( "data", "kabc/lock/" + p + ".lock" ); + KURL url(p); + QString lockName = locateLocal( "data", "kabc/lock/" + url.fileName() + ".lock" ); + + + kdDebug(5700) << "-- lock name: " << lockName << endl; + + if ( QFile::exists( lockName ) ) return false; + + QString lockUniqueName; + lockUniqueName = p + KApplication::randomString( 8 ); + + url = lockUniqueName; +//US mLockUniqueName = locateLocal( "data", "kabc/lock/" + lockUniqueName ); + mLockUniqueName = locateLocal( "data", "kabc/lock/" + url.fileName() ); + + kdDebug(5700) << "-- lock unique name: " << mLockUniqueName << endl; + + // Create unique file + QFile file( mLockUniqueName ); + file.open( IO_WriteOnly ); + file.close(); + + // Create lock file +#ifdef _WIN32_ + int result = 0; + qDebug("WARNING: ResourceDir::lock cannot link "); +#else + int result = ::link( QFile::encodeName( mLockUniqueName ), + QFile::encodeName( lockName ) ); +#endif + if ( result == 0 ) { + addressBook()->emitAddressBookLocked(); + return true; + } + + // TODO: check stat + + return false; +} + +void ResourceDir::unlock( const QString &path ) +{ + QString p = path; +//US change the implementation how the lockfilename is getting created +//US p.replace( QRegExp( "/" ), "_" ); +//US QString lockName = locate( "data", "kabc/lock/" + p + ".lock" ); + KURL url(p); + QString lockName = locate( "data", "kabc/lock/" + url.fileName() + ".lock" ); + + ::unlink( QFile::encodeName( lockName ) ); + QFile::remove( mLockUniqueName ); + addressBook()->emitAddressBookUnlocked(); +} + +void ResourceDir::setPath( const QString &path ) +{ +/*US ToDo: no synchronization so far. Has to be changed in the future + mDirWatch.stopScan(); + mDirWatch.removeDir( mPath ); +*/ + mPath = path; + +/*US ToDo: no synchronization so far. Has to be changed in the future + mDirWatch.addDir( mPath, true ); + mDirWatch.startScan(); +*/ + +//US simulate KDirWatch event + pathChanged(); + +} + +QString ResourceDir::path() const +{ + return mPath; +} + +void ResourceDir::setFormat( const QString &format ) +{ + mFormatName = format; + + if ( mFormat ) + delete mFormat; + +//US FormatFactory *factory = FormatFactory::self(); +//US mFormat = factory->format( mFormatName ); + +qDebug("ResourceDir::setFormat initialized with format %s ", format.latin1()); + if (mFormatName == "vcard") + mFormat = new VCardFormatPlugin2(); + else if (mFormatName == "binary") + mFormat = new BinaryFormat(); + else + qDebug("ResourceDir::setFormat format unknown !!! %s ", format.latin1()); + + +} + +QString ResourceDir::format() const +{ + return mFormatName; +} + +void ResourceDir::pathChanged() +{ + if ( !addressBook() ) + return; + + load(); + addressBook()->emitAddressBookChanged(); +} + +void ResourceDir::removeAddressee( const Addressee& addr ) +{ + QFile::remove( mPath + "/" + addr.uid() ); +} + +void ResourceDir::cleanUp() +{ + unlock( mPath ); +} + +//US #include "resourcedir.moc" diff --git a/kabc/plugins/dir/resourcedir.h b/kabc/plugins/dir/resourcedir.h new file mode 100644 index 0000000..6e35695 --- a/dev/null +++ b/kabc/plugins/dir/resourcedir.h @@ -0,0 +1,115 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_RESOURCEDIR_H +#define KABC_RESOURCEDIR_H + +#include <kconfig.h> +#include <kdirwatch.h> + +#include <sys/types.h> + +#include "resource.h" + +class QTimer; + +namespace KABC { + +class FormatPlugin; + +/** + @internal +*/ +class ResourceDir : public Resource +{ + Q_OBJECT + +public: + ResourceDir( const KConfig* ); + ~ResourceDir(); + + virtual void writeConfig( KConfig* ); + + virtual bool doOpen(); + virtual void doClose(); + + virtual Ticket *requestSaveTicket(); + + virtual bool load(); + virtual bool save( Ticket * ); + + /** + * Set path to be used for saving. + */ + void setPath( const QString & ); + + /** + * Return path used for loading and saving the address book. + */ + QString path() const; + + /** + * Set the format by name. + */ + void setFormat( const QString &format ); + + /** + * Returns the format name. + */ + QString format() const; + + /** + * Remove a addressee from its source. + * This method is mainly called by KABC::AddressBook. + */ + virtual void removeAddressee( const Addressee& addr ); + + /** + * This method is called by an error handler if the application + * crashed + */ + virtual void cleanUp(); + +protected slots: + void pathChanged(); + +protected: + bool lock( const QString &path ); + void unlock( const QString &path ); + +private: + FormatPlugin *mFormat; + + KDirWatch mDirWatch; + + QString mPath; + QString mFormatName; + QString mLockUniqueName; +}; + +} +#endif diff --git a/kabc/plugins/dir/resourcedirconfig.cpp b/kabc/plugins/dir/resourcedirconfig.cpp new file mode 100644 index 0000000..98d18fe --- a/dev/null +++ b/kabc/plugins/dir/resourcedirconfig.cpp @@ -0,0 +1,123 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qlabel.h> +#include <qlayout.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kdialog.h> + +//US #include "formatfactory.h" +#include "resourcedir.h" +#include "stdaddressbook.h" + +#include "resourcedirconfig.h" + +using namespace KABC; + +ResourceDirConfig::ResourceDirConfig( QWidget* parent, const char* name ) + : KRES::ConfigWidget( parent, name ) +{ + QGridLayout *mainLayout = new QGridLayout( this, 2, 2, 0, + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Format:" ), this ); + mFormatBox = new KComboBox( this ); + + mainLayout->addWidget( label, 0, 0 ); + mainLayout->addWidget( mFormatBox, 0, 1 ); + + label = new QLabel( i18n( "Location:" ), this ); + mFileNameEdit = new KURLRequester( this ); +//US mFileNameEdit->setMode( KFile::Directory ); + + mainLayout->addWidget( label, 1, 0 ); + mainLayout->addWidget( mFileNameEdit, 1, 1 ); + +/*US lets hardcode the formats instead of using a factory + FormatFactory *factory = FormatFactory::self(); + QStringList formats = factory->formats(); + QStringList::Iterator it; + for ( it = formats.begin(); it != formats.end(); ++it ) { + FormatInfo *info = factory->info( *it ); + if ( info ) { + mFormatTypes << (*it); + mFormatBox->insertItem( info->nameLabel ); + } + } +*/ + mFormatTypes << "vcard"; + mFormatTypes << "binary"; + mFormatBox->insertItem( "vcard" ); + mFormatBox->insertItem( "binary" ); + + + mInEditMode = false; +} + +void ResourceDirConfig::setEditMode( bool value ) +{ + mFormatBox->setEnabled( !value ); + mInEditMode = value; +} + +void ResourceDirConfig::loadSettings( KRES::Resource *res ) +{ +//US ResourceDir *resource = dynamic_cast<ResourceDir*>( res ); + ResourceDir *resource = (ResourceDir*)( res ); + + if ( !resource ) { + kdDebug(5700) << "ResourceDirConfig::loadSettings(): cast failed" << endl; + return; + } + + mFormatBox->setCurrentItem( mFormatTypes.findIndex( resource->format() ) ); + + mFileNameEdit->setURL( resource->path() ); + if ( mFileNameEdit->url().isEmpty() ) + mFileNameEdit->setURL( KABC::StdAddressBook::directoryName() ); +} + +void ResourceDirConfig::saveSettings( KRES::Resource *res ) +{ +//US ResourceDir *resource = dynamic_cast<ResourceDir*>( res ); + ResourceDir *resource = (ResourceDir*)( res ); + + if ( !resource ) { + kdDebug(5700) << "ResourceDirConfig::loadSettings(): cast failed" << endl; + return; + } + + if ( mInEditMode ) + resource->setFormat( mFormatTypes[ mFormatBox->currentItem() ] ); + + resource->setPath( mFileNameEdit->url() ); +} + +//US #include "resourcedirconfig.moc" diff --git a/kabc/plugins/dir/resourcedirconfig.h b/kabc/plugins/dir/resourcedirconfig.h new file mode 100644 index 0000000..5af38a5 --- a/dev/null +++ b/kabc/plugins/dir/resourcedirconfig.h @@ -0,0 +1,61 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef RESOURCEDIRCONFIG_H +#define RESOURCEDIRCONFIG_H + +#include <kcombobox.h> +#include <kurlrequester.h> + +#include <kresources/configwidget.h> + +namespace KABC { + +class ResourceDirConfig : public KRES::ConfigWidget +{ + Q_OBJECT + +public: + ResourceDirConfig( QWidget* parent = 0, const char* name = 0 ); + + void setEditMode( bool value ); + +public slots: + void loadSettings( KRES::Resource* ); + void saveSettings( KRES::Resource* ); + +private: + KComboBox* mFormatBox; + KURLRequester* mFileNameEdit; + + QStringList mFormatTypes; + + bool mInEditMode; +}; + +} +#endif diff --git a/kabc/plugins/file/resourcefile.cpp b/kabc/plugins/file/resourcefile.cpp new file mode 100644 index 0000000..d30ed2f --- a/dev/null +++ b/kabc/plugins/file/resourcefile.cpp @@ -0,0 +1,389 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <sys/types.h> +#include <sys/stat.h> +#ifndef _WIN32_ +#include <unistd.h> +#endif + +#include <qfile.h> +#include <qfileinfo.h> +#include <qregexp.h> +#include <qtimer.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> +//US #include <ksavefile.h> +#include <kstandarddirs.h> + +//US #include "formatfactory.h" + +#include "resource.h" +#include "resourcefileconfig.h" +#include "stdaddressbook.h" + +#include <formats/vcardformatplugin2.h> +#include <formats/binaryformat.h> + + +#include "resourcefile.h" + +using namespace KABC; + +extern "C" +{ + void *init_kabc_file() + { + qDebug("!!!resourcefile.cpp : init_kabc_file has to be changed"); +//US return new KRES::PluginFactory<ResourceFile,ResourceFileConfig>(); + return 0; + } +} + + +ResourceFile::ResourceFile( const KConfig *config ) + : Resource( config ) , mFormat( 0 ) +{ + QString fileName, formatName; + + KConfig *cfg = (KConfig *)config; + if ( cfg ) { + fileName = cfg->readEntry( "FileName", StdAddressBook::fileName() ); + formatName = cfg->readEntry( "FileFormat", "vcard" ); +// qDebug("ResourceFile::ResourceFile : 1 %s, %s", fileName.latin1(), formatName.latin1() ); + } else { + fileName = StdAddressBook::fileName(); + formatName = "vcard"; +// qDebug("ResourceFile::ResourceFile : 2 %s, %s", fileName.latin1(), formatName.latin1() ); + } + + init( fileName, formatName ); +} + +ResourceFile::ResourceFile( const QString &fileName, + const QString &formatName ) + : Resource( 0 ) +{ +// qDebug("ResourceFile::ResourceFile : 3 %s, %s", fileName.latin1(), formatName.latin1()); + init( fileName, formatName ); +} + +void ResourceFile::init( const QString &fileName, const QString &formatName ) +{ + mFormatName = formatName; + +/*US FormatFactory *factory = FormatFactory::self(); + mFormat = factory->format( mFormatName ); + + if ( !mFormat ) { + mFormatName = "vcard"; + mFormat = factory->format( mFormatName ); + } +*/ + +//US qDebug("ResourceFile::init initialized with format %s ", formatName.latin1()); + if (mFormatName == "vcard") { + mFormat = new VCardFormatPlugin2(); +// qDebug("ResourceFile::init format VCardFormatPlugin2"); + } + else if (mFormatName == "binary") { + mFormat = new BinaryFormat(); +// qDebug("ResourceFile::init format BinaryFormat"); + } + else + qDebug("ResourceFile::init format unknown !!! %s ", formatName.latin1()); + +/*US we have no KDirWatch. SO simulate the signals from inside the apropriate methods + connect( &mDirWatch, SIGNAL( dirty(const QString&) ), SLOT( fileChanged() ) ); + connect( &mDirWatch, SIGNAL( created(const QString&) ), SLOT( fileChanged() ) ); + connect( &mDirWatch, SIGNAL( deleted(const QString&) ), SLOT( fileChanged() ) ); +*/ + + setFileName( fileName ); +} + +ResourceFile::~ResourceFile() +{ + delete mFormat; + mFormat = 0; +} + +void ResourceFile::writeConfig( KConfig *config ) +{ + Resource::writeConfig( config ); + + config->writeEntry( "FileName", mFileName ); + config->writeEntry( "FileFormat", mFormatName ); + +// qDebug("ResourceFile::writeConfig format %s, %s", mFileName.latin1(), mFormatName.latin1()); + +} + +Ticket *ResourceFile::requestSaveTicket() +{ + kdDebug(5700) << "ResourceFile::requestSaveTicket()" << endl; + + if ( !addressBook() ) return 0; + + if ( !lock( mFileName ) ) { + kdDebug(5700) << "ResourceFile::requestSaveTicket(): Unable to lock file '" + << mFileName << "'" << endl; + return 0; + } + return createTicket( this ); +} + + +bool ResourceFile::doOpen() +{ + QFile file( mFileName ); + + if ( !file.exists() ) { + // try to create the file + bool ok = file.open( IO_WriteOnly ); + if ( ok ) + file.close(); + + return ok; + } else { + if ( !file.open( IO_ReadWrite ) ) + return false; + + if ( file.size() == 0 ) { + file.close(); + return true; + } + + bool ok = mFormat->checkFormat( &file ); + file.close(); + + return ok; + } +} + +void ResourceFile::doClose() +{ +} + +bool ResourceFile::load() +{ + kdDebug(5700) << "ResourceFile::load(): '" << mFileName << "'" << endl; + + QFile file( mFileName ); + if ( !file.open( IO_ReadOnly ) ) { + addressBook()->error( i18n( "Unable to open file '%1'." ).arg( mFileName ) ); + return false; + } + +// qDebug("ResourceFile::load format %s, %s", mFileName.latin1(), mFormatName.latin1()); + + return mFormat->loadAll( addressBook(), this, &file ); +} + +bool ResourceFile::save( Ticket *ticket ) +{ +// qDebug("ResourceFile::save format %s, %s", mFileName.latin1(), mFormatName.latin1()); + kdDebug(5700) << "ResourceFile::save()" << endl; + + // create backup file + QString extension = "_" + QString::number( QDate::currentDate().dayOfWeek() ); + +/*US we use a simpler method to create a backupfile + + (void) KSaveFile::backupFile( mFileName, QString::null /*directory*/ +/*US ,extension ); + + KSaveFile saveFile( mFileName ); + bool ok = false; + if ( saveFile.status() == 0 && saveFile.file() ) + { + mFormat->saveAll( addressBook(), this, saveFile.file() ); + ok = saveFile.close(); + } +*/ + +//US ToDo: write backupfile + QFile info; + info.setName( mFileName ); + bool ok = info.open( IO_WriteOnly ); + if ( ok ) { + mFormat->saveAll( addressBook(), this, &info ); + + info.close(); + ok = true; + } + else { + + } + + if ( !ok ) + addressBook()->error( i18n( "Unable to save file '%1'." ).arg( mFileName ) ); + + delete ticket; + unlock( mFileName ); + + return ok; + + qDebug("ResourceFile::save has to be changed"); + return true; +} + +bool ResourceFile::lock( const QString &fileName ) +{ + kdDebug(5700) << "ResourceFile::lock()" << endl; + + QString fn = fileName; + +//US change the implementation how the lockfilename is getting created +//US fn.replace( QRegExp("/"), "_" ); +//US QString lockName = locateLocal( "data", "kabc/lock/" + fn + ".lock" ); + + KURL url(fn); + QString lockName = locateLocal( "data", "kabc/lock/" + url.fileName() + ".lock" ); + + kdDebug(5700) << "-- lock name: " << lockName << endl; + + if (QFile::exists( lockName )) return false; + + QString lockUniqueName; + lockUniqueName = fn + KApplication::randomString( 8 ); + + url = lockUniqueName; +//US mLockUniqueName = locateLocal( "data", "kabc/lock/" + lockUniqueName ); + mLockUniqueName = locateLocal( "data", "kabc/lock/" + url.fileName() ); + kdDebug(5700) << "-- lock unique name: " << mLockUniqueName << endl; + + // Create unique file + QFile file( mLockUniqueName ); + file.open( IO_WriteOnly ); + file.close(); + + // Create lock file + int result = 0;//::link( QFile::encodeName( mLockUniqueName ), + // QFile::encodeName( lockName ) ); + qDebug("lock files %s, %s needs to be fixed", mLockUniqueName.latin1(), lockName.latin1() ); + + if ( result == 0 ) { + addressBook()->emitAddressBookLocked(); + return true; + } + + // TODO: check stat + + return false; +} + +void ResourceFile::unlock( const QString &fileName ) +{ + QString fn = fileName; +//US change the implementation how the lockfilename is getting created +//US fn.replace( QRegExp( "/" ), "_" ); +//US QString lockName = locateLocal( "data", "kabc/lock/" + fn + ".lock" ); +//US QString lockName = fn + ".lock"; + KURL url(fn); + QString lockName = locateLocal( "data", "kabc/lock/" + url.fileName() + ".lock" ); + + QFile::remove( lockName ); + QFile::remove( mLockUniqueName ); + addressBook()->emitAddressBookUnlocked(); +} + +void ResourceFile::setFileName( const QString &fileName ) +{ +/*US ToDo: no synchronization so far. Has to be changed in the future + mDirWatch.stopScan(); + mDirWatch.removeFile( mFileName ); +*/ + mFileName = fileName; + + +/*US ToDo: no synchronization so far. Has to be changed in the future + mDirWatch.addFile( mFileName ); + mDirWatch.startScan(); +*/ +//US simulate KDirWatch event + fileChanged(); +} + +QString ResourceFile::fileName() const +{ + return mFileName; +} + +void ResourceFile::setFormat( const QString &format ) +{ + mFormatName = format; + delete mFormat; + +//US FormatFactory *factory = FormatFactory::self(); +//US mFormat = factory->format( mFormatName ); + +//qDebug("ResourceFile::setFormat initialized with format %s ", format.latin1()); + if (mFormatName == "vcard") { + mFormat = new VCardFormatPlugin2(); +// qDebug("ResourceFile::setFormat format %s", mFormatName.latin1()); + } + else if (mFormatName == "binary") { + mFormat = new BinaryFormat(); +// qDebug("ResourceFile::setFormat format %s", mFormatName.latin1()); + } + else + qDebug("ResourceFile::setFormat format unknown !!! %s ", format.latin1()); + +} + +QString ResourceFile::format() const +{ + return mFormatName; +} + +void ResourceFile::fileChanged() +{ + // There is a small theoretical chance that KDirWatch calls us before + // we are fully constructed + if (!addressBook()) + return; + load(); + addressBook()->emitAddressBookChanged(); +} + +void ResourceFile::removeAddressee( const Addressee &addr ) +{ + QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/photos/" ) + addr.uid() ) ); + QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/logos/" ) + addr.uid() ) ); + QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/sounds/" ) + addr.uid() ) ); +} + +void ResourceFile::cleanUp() +{ + unlock( mFileName ); +} + +//US #include "resourcefile.moc" diff --git a/kabc/plugins/file/resourcefile.h b/kabc/plugins/file/resourcefile.h new file mode 100644 index 0000000..4522d78 --- a/dev/null +++ b/kabc/plugins/file/resourcefile.h @@ -0,0 +1,162 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + + +#ifndef KABC_RESOURCEFILE_H +#define KABC_RESOURCEFILE_H + +#include <kconfig.h> +#include <kdirwatch.h> + +#include <sys/types.h> + +#include <resource.h> + +class QTimer; +class FormatPlugin; + +namespace KABC { + +//US class FormatPlugin; +class ResourceConfigWidget; + +/** + @internal +*/ +class ResourceFile : public Resource +{ + Q_OBJECT + +public: + + /** + Constructor. + + @param cfg The config object where custom resource settings are stored. + */ + ResourceFile( const KConfig *cfg ); + + /** + Construct file resource on file @arg fileName using format @arg formatName. + */ + ResourceFile( const QString &fileName, const QString &formatName = "vcard" ); + + /** + * Destructor. + */ + ~ResourceFile(); + + /** + Writes the config back. + */ + virtual void writeConfig( KConfig *cfg ); + + /** + * Tries to open the file and checks for the proper format. + * This method should be called before @ref load(). + */ + virtual bool doOpen(); + + /** + * Closes the file again. + */ + virtual void doClose(); + + /** + * Requests a save ticket, that is used by @ref save() + */ + virtual Ticket *requestSaveTicket(); + + /** + * Loads all addressees from file to the address book. + * Returns true if all addressees could be loaded otherwise false. + */ + virtual bool load(); + + /** + * Saves all addresses from address book to file. + * Returns true if all addressees could be saved otherwise false. + * + * @param ticket The ticket returned by @ref requestSaveTicket() + */ + virtual bool save( Ticket *ticket ); + + /** + * Set name of file to be used for saving. + */ + void setFileName( const QString & ); + + /** + * Return name of file used for loading and saving the address book. + */ + QString fileName() const; + + /** + Sets a new format by name. + */ + void setFormat( const QString &name ); + + /** + Returns the format name. + */ + QString format() const; + + /** + * Remove a addressee from its source. + * This method is mainly called by KABC::AddressBook. + */ + virtual void removeAddressee( const Addressee& addr ); + + /** + * This method is called by an error handler if the application + * crashed + */ + virtual void cleanUp(); + +protected slots: + void fileChanged(); + +protected: + void init( const QString &fileName, const QString &format ); + + bool lock( const QString &fileName ); + void unlock( const QString &fileName ); + +private: + QString mFileName; + QString mFormatName; + + FormatPlugin *mFormat; + + QString mLockUniqueName; + + KDirWatch mDirWatch; +}; + +} + +#endif diff --git a/kabc/plugins/file/resourcefileconfig.cpp b/kabc/plugins/file/resourcefileconfig.cpp new file mode 100644 index 0000000..b63775d --- a/dev/null +++ b/kabc/plugins/file/resourcefileconfig.cpp @@ -0,0 +1,144 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qlabel.h> +#include <qlayout.h> +#include <qfileinfo.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kdialog.h> +#ifndef _WIN32_ +#include <unistd.h> +#endif +//US #include "formatfactory.h" +#include <qfile.h> +#include "resourcefile.h" +#include "stdaddressbook.h" + +#include "resourcefileconfig.h" + +using namespace KABC; + +ResourceFileConfig::ResourceFileConfig( QWidget* parent, const char* name ) + : ConfigWidget( parent, name ) +{ +//qDebug("ResourceFileConfig::ResourceFileConfig"); + + QGridLayout *mainLayout = new QGridLayout( this, 2, 2, 0, + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Format:" ), this ); + mFormatBox = new KComboBox( this ); + + mainLayout->addWidget( label, 0, 0 ); + mainLayout->addWidget( mFormatBox, 0, 1 ); + + label = new QLabel( i18n( "Location:" ), this ); + mFileNameEdit = new KURLRequester( this ); + + connect( mFileNameEdit, SIGNAL( textChanged( const QString & ) ), + SLOT( checkFilePermissions( const QString & ) ) ); + + mainLayout->addWidget( label, 1, 0 ); + mainLayout->addWidget( mFileNameEdit, 1, 1 ); + + +/*US lets hardcode the formats instead of using a factory + FormatFactory *factory = FormatFactory::self(); + QStringList formats = factory->formats(); + QStringList::Iterator it; + + for ( it = formats.begin(); it != formats.end(); ++it ) { + FormatInfo *info = factory->info( *it ); + if ( info ) { + mFormatTypes << (*it); + mFormatBox->insertItem( info->nameLabel ); + } + } +*/ + mFormatTypes << "vcard"; + mFormatTypes << "binary"; + mFormatBox->insertItem( "vcard" ); + mFormatBox->insertItem( "binary" ); + + mInEditMode = false; +} + +void ResourceFileConfig::setEditMode( bool value ) +{ + mFormatBox->setEnabled( !value ); + mInEditMode = value; +} + +void ResourceFileConfig::loadSettings( KRES::Resource *res ) +{ +//US ResourceFile *resource = dynamic_cast<ResourceFile*>( res ); + ResourceFile *resource = (ResourceFile*)( res ); + + if ( !resource ) { + kdDebug(5700) << "ResourceFileConfig::loadSettings(): cast failed" << endl; + return; + } + + mFormatBox->setCurrentItem( mFormatTypes.findIndex( resource->format() ) ); + + mFileNameEdit->setURL( resource->fileName() ); + if ( mFileNameEdit->url().isEmpty() ) + mFileNameEdit->setURL( KABC::StdAddressBook::fileName() ); +} + +void ResourceFileConfig::saveSettings( KRES::Resource *res ) +{ +//US ResourceFile *resource = dynamic_cast<ResourceFile*>( res ); + ResourceFile *resource = (ResourceFile*)( res ); + + if ( !resource ) { + kdDebug(5700) << "ResourceFileConfig::saveSettings(): cast failed" << endl; + return; + } + + if ( !mInEditMode ) + resource->setFormat( mFormatTypes[ mFormatBox->currentItem() ] ); + + resource->setFileName( mFileNameEdit->url() ); +} +void ResourceFileConfig::checkFilePermissions( const QString& fileName ) +{ + // If file exist but is not writeable... +#ifdef _WIN32_ + QFileInfo fi ( QFile::encodeName( fileName ) ); + if ( fi.exists() ) + emit setReadOnly(!fi.isReadable() ); +#else + if ( access( QFile::encodeName( fileName ), F_OK ) == 0 ) + emit setReadOnly( access( QFile::encodeName( fileName ), W_OK ) < 0 ); +#endif +} + +//US #include "resourcefileconfig.moc" diff --git a/kabc/plugins/file/resourcefileconfig.h b/kabc/plugins/file/resourcefileconfig.h new file mode 100644 index 0000000..31ccaaf --- a/dev/null +++ b/kabc/plugins/file/resourcefileconfig.h @@ -0,0 +1,65 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef RESOURCEFILECONFIG_H +#define RESOURCEFILECONFIG_H + +#include <kcombobox.h> +#include <kurlrequester.h> + +#include <kresources/configwidget.h> + +namespace KABC { + +class ResourceFileConfig : public KRES::ConfigWidget +{ + Q_OBJECT + +public: + ResourceFileConfig( QWidget* parent = 0, const char* name = 0 ); + + void setEditMode( bool value ); + +public slots: + void loadSettings( KRES::Resource *resource ); + void saveSettings( KRES::Resource *resource ); + +protected slots: + void checkFilePermissions( const QString& fileName ); + +private: + KComboBox* mFormatBox; + KURLRequester* mFileNameEdit; + bool mInEditMode; + + QStringList mFormatTypes; +}; + +} + +#endif diff --git a/kabc/plugins/ldap/resourceldap.cpp b/kabc/plugins/ldap/resourceldap.cpp new file mode 100644 index 0000000..1c54f63 --- a/dev/null +++ b/kabc/plugins/ldap/resourceldap.cpp @@ -0,0 +1,444 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <kdebug.h> +#include <kglobal.h> +#include <klineedit.h> +#include <klocale.h> +#include <kconfig.h> +#include <kstringhandler.h> + +#include <stdlib.h> + +#include "resourceldap.h" +#include "resourceldapconfig.h" + +using namespace KABC; + +extern "C" +{ + void *init_kabc_ldap() + { + qDebug("resourceldap.cpp : init_kabc_ldap has to be changed"); +//US return new KRES::PluginFactory<ResourceLDAP,ResourceLDAPConfig>(); + } +} + +void addModOp( LDAPMod ***pmods, const QString &attr, const QString &value ); + + +ResourceLDAP::ResourceLDAP( const KConfig *config ) + : Resource( config ), mPort( 389 ), mLdap( 0 ) +{ + KConfig *cfg = (KConfig *)config; + if ( cfg ) { + mUser = cfg->readEntry( "LdapUser" ); + mPassword = KStringHandler::obscure( cfg->readEntry( "LdapPassword" ) ); + mDn = cfg->readEntry( "LdapDn" ); + mHost = cfg->readEntry( "LdapHost" ); + mPort = cfg->readNumEntry( "LdapPort", 389 ); + mFilter = cfg->readEntry( "LdapFilter" ); + mAnonymous = cfg->readBoolEntry( "LdapAnonymous" ); + + QStringList attributes = cfg->readListEntry( "LdapAttributes" ); + for ( uint pos = 0; pos < attributes.count(); pos += 2 ) + mAttributes.insert( attributes[ pos ], attributes[ pos + 1 ] ); + } + + /** + If you want to add new attributes, append them here, add a + translation string in the ctor of AttributesDialog and + handle them in the load() method below. + These are the default values from + */ + if ( mAttributes.count() == 0 ) { + mAttributes.insert( "commonName", "cn" ); + mAttributes.insert( "formattedName", "displayName" ); + mAttributes.insert( "familyName", "sn" ); + mAttributes.insert( "givenName", "givenName" ); + mAttributes.insert( "mail", "mail" ); + mAttributes.insert( "mailAlias", "" ); + mAttributes.insert( "phoneNumber", "telephoneNumber" ); + mAttributes.insert( "uid", "uid" ); + } +} + +void ResourceLDAP::writeConfig( KConfig *config ) +{ + Resource::writeConfig( config ); + + config->writeEntry( "LdapUser", mUser ); + config->writeEntry( "LdapPassword", KStringHandler::obscure( mPassword ) ); + config->writeEntry( "LdapDn", mDn ); + config->writeEntry( "LdapHost", mHost ); + config->writeEntry( "LdapPort", mPort ); + config->writeEntry( "LdapFilter", mFilter ); + config->writeEntry( "LdapAnonymous", mAnonymous ); + + QStringList attributes; + QMap<QString, QString>::Iterator it; + for ( it = mAttributes.begin(); it != mAttributes.end(); ++it ) + attributes << it.key() << it.data(); + + config->writeEntry( "LdapAttributes", attributes ); +} + +Ticket *ResourceLDAP::requestSaveTicket() +{ + if ( !addressBook() ) { + kdDebug(5700) << "no addressbook" << endl; + return 0; + } + + return createTicket( this ); +} + +bool ResourceLDAP::doOpen() +{ + if ( mLdap ) + return false; + + if ( !mPort ) + mPort = 389; + + mLdap = ldap_init( mHost.local8Bit(), mPort ); + if ( !mLdap ) { + addressBook()->error( i18n( "Unable to connect to server '%1' on port '%2'" ).arg( mHost ).arg( mPort ) ); + return false; + } + + if ( !mUser.isEmpty() && !mAnonymous ) { + if ( ldap_simple_bind_s( mLdap, mUser.local8Bit(), mPassword.local8Bit() ) != LDAP_SUCCESS ) { + addressBook()->error( i18n( "Unable to bind to server '%1'" ).arg( mHost ) ); + return false; + } + + kdDebug(5700) << "ResourceLDAP: bind to server successfully" << endl; + } else { + if ( ldap_simple_bind_s( mLdap, NULL, NULL ) != LDAP_SUCCESS ) { + addressBook()->error( i18n( "Unable to bind anonymously to server '%1'" ).arg( mHost ) ); + return false; + } + + kdDebug( 5700 ) << "ResourceLDAP: bind anonymously to server successfully" << endl; + } + + int deref = LDAP_DEREF_ALWAYS; + if ( ldap_set_option( mLdap, LDAP_OPT_DEREF, (void *) &deref ) != LDAP_OPT_SUCCESS ) { + kdDebug(5700) << "ResourceLDAP: can't set 'deref' option" << endl; + return false; + } + + if ( ldap_set_option( mLdap, LDAP_OPT_REFERRALS, LDAP_OPT_ON ) != LDAP_OPT_SUCCESS ) { + kdDebug(5700) << "ResourceLDAP: can't set 'referrals' option" << endl; + return false; + } + + return true; +} + +void ResourceLDAP::doClose() +{ + if ( ldap_unbind_s( mLdap ) != LDAP_SUCCESS ) { + kdDebug(5700) << "ResourceLDAP: can't unbind from server" << endl; + return; + } + + mLdap = 0; +} + +bool ResourceLDAP::load() +{ + LDAPMessage *res; + LDAPMessage *msg; + BerElement *track; + char *names; + char **values; + + char **LdapSearchAttr = new char*[ mAttributes.count() + 1 ]; + + QMap<QString, QString>::Iterator it; + int i = 0; + for ( it = mAttributes.begin(); it != mAttributes.end(); ++it ) { + if ( !it.data().isEmpty() ) { + unsigned int len = it.data().utf8().length(); + LdapSearchAttr[ i ] = new char[ len+1 ]; + memcpy( LdapSearchAttr[ i ], it.data().utf8(), len ); + LdapSearchAttr[ i ][ len ] = 0; + ++i; + } + } + LdapSearchAttr[ i ] = 0; + + QString filter = mFilter; + if ( filter.isEmpty() ) + filter = "cn=*"; + + int result; + if ( ( result = ldap_search_s( mLdap, mDn.local8Bit(), LDAP_SCOPE_SUBTREE, QString( "(%1)" ).arg( filter ).local8Bit(), + LdapSearchAttr, 0, &res ) != LDAP_SUCCESS ) ) { + addressBook()->error( i18n( "Unable to search on server '%1': %2" ) + .arg( mHost ) + .arg( ldap_err2string( result ) ) ); + + for ( i = 0; LdapSearchAttr[ i ]; ++i ) + delete [] LdapSearchAttr[ i ]; + delete [] LdapSearchAttr; + + return false; + } + + for ( msg = ldap_first_entry( mLdap, res ); msg; msg = ldap_next_entry( mLdap, msg ) ) { + Addressee addr; + addr.setResource( this ); + for ( names = ldap_first_attribute( mLdap, msg, &track ); names; names = ldap_next_attribute( mLdap, msg, track ) ) { + values = ldap_get_values( mLdap, msg, names ); + for ( int i = 0; i < ldap_count_values( values ); ++i ) { + QString name = QString::fromUtf8( names ).lower(); + QString value = QString::fromUtf8( values[ i ] ); + + if ( name == mAttributes[ "commonName" ].lower() ) { + if ( !addr.formattedName().isEmpty() ) { + QString fn = addr.formattedName(); + addr.setNameFromString( value ); + addr.setFormattedName( fn ); + } else + addr.setNameFromString( value ); + } else if ( name == mAttributes[ "formattedName" ].lower() ) { + addr.setFormattedName( value ); + } else if ( name == mAttributes[ "givenName" ].lower() ) { + addr.setGivenName( value ); + } else if ( name == mAttributes[ "mail" ].lower() ) { + addr.insertEmail( value, true ); + } else if ( name == mAttributes[ "mailAlias" ].lower() ) { + addr.insertEmail( value, false ); + } else if ( name == mAttributes[ "phoneNumber" ].lower() ) { + PhoneNumber phone; + phone.setNumber( value ); + addr.insertPhoneNumber( phone ); + break; // read only the home number + } else if ( name == mAttributes[ "familyName" ].lower() ) { + addr.setFamilyName( value ); + } else if ( name == mAttributes[ "uid" ].lower() ) { + addr.setUid( value ); + } + } + ldap_value_free( values ); + } + ber_free( track, 0 ); + + addressBook()->insertAddressee( addr ); + } + + ldap_msgfree( res ); + + for ( i = 0; LdapSearchAttr[ i ]; ++i ) + delete [] LdapSearchAttr[ i ]; + delete [] LdapSearchAttr; + + return true; +} + +bool ResourceLDAP::save( Ticket * ) +{ + AddressBook::Iterator it; + for ( it = addressBook()->begin(); it != addressBook()->end(); ++it ) { + if ( (*it).resource() == this && (*it).changed() ) { + LDAPMod **mods = NULL; + + addModOp( &mods, "objectClass", "organizationalPerson" ); + addModOp( &mods, "objectClass", "person" ); + addModOp( &mods, "objectClass", "Top" ); + addModOp( &mods, mAttributes[ "commonName" ].utf8(), (*it).assembledName() ); + addModOp( &mods, mAttributes[ "formattedName" ].utf8(), (*it).formattedName() ); + addModOp( &mods, mAttributes[ "givenName" ].utf8(), (*it).givenName() ); + addModOp( &mods, mAttributes[ "familyName" ].utf8(), (*it).familyName() ); + addModOp( &mods, mAttributes[ "uid" ].utf8(), (*it).uid() ); + + QStringList emails = (*it).emails(); + QStringList::ConstIterator mailIt; + bool first = true; + for ( mailIt = emails.begin(); mailIt != emails.end(); ++mailIt ) { + if ( first ) { + addModOp( &mods, mAttributes[ "mail" ].utf8(), (*mailIt) ); + first = false; + } else + addModOp( &mods, mAttributes[ "mailAlias" ].utf8(), (*mailIt) ); + } + + PhoneNumber number = (*it).phoneNumber( PhoneNumber::Home ); + addModOp( &mods, mAttributes[ "phoneNumber" ].utf8(), number.number() ); + + QString dn = "cn=" + (*it).assembledName() + "," + mDn; + + int retval; + if ( (retval = ldap_add_s( mLdap, dn.local8Bit(), mods )) != LDAP_SUCCESS ) + addressBook()->error( i18n( "Unable to modify '%1' on server '%2'" ).arg( (*it).uid() ).arg( mHost ) ); + + ldap_mods_free( mods, 1 ); + + // mark as unchanged + (*it).setChanged( false ); + } + } + + return true; +} + +void ResourceLDAP::removeAddressee( const Addressee &addr ) +{ + LDAPMessage *res; + LDAPMessage *msg; + + QString filter = QString( "(&(uid=%1)(%2))" ).arg( addr.uid() ).arg( mFilter ); + + kdDebug(5700) << "ldap:removeAddressee" << filter << endl; + + ldap_search_s( mLdap, mDn.local8Bit(), LDAP_SCOPE_SUBTREE, filter.local8Bit(), + 0, 0, &res ); + + for ( msg = ldap_first_entry( mLdap, res ); msg; msg = ldap_next_entry( mLdap, msg ) ) { + char *dn = ldap_get_dn( mLdap, msg ); + kdDebug(5700) << "found " << dn << endl; + if ( ldap_delete_s( mLdap, dn ) != LDAP_SUCCESS ) + addressBook()->error( i18n( "Unable to delete '%1' on server '%2'" ).arg( dn ).arg( mHost ) ); + ldap_memfree( dn ); + } + + ldap_msgfree( res ); +} + +void ResourceLDAP::setUser( const QString &user ) +{ + mUser = user; +} + +QString ResourceLDAP::user() const +{ + return mUser; +} + +void ResourceLDAP::setPassword( const QString &password ) +{ + mPassword = password; +} + +QString ResourceLDAP::password() const +{ + return mPassword; +} + +void ResourceLDAP::setDn( const QString &dn ) +{ + mDn = dn; +} + +QString ResourceLDAP::dn() const +{ + return mDn; +} + +void ResourceLDAP::setHost( const QString &host ) +{ + mHost = host; +} + +QString ResourceLDAP::host() const +{ + return mHost; +} + +void ResourceLDAP::setPort( int port ) +{ + mPort = port; +} + +int ResourceLDAP::port() const +{ + return mPort; +} + +void ResourceLDAP::setFilter( const QString &filter ) +{ + mFilter = filter; +} + +QString ResourceLDAP::filter() const +{ + return mFilter; +} + +void ResourceLDAP::setIsAnonymous( bool value ) +{ + mAnonymous = value; +} + +bool ResourceLDAP::isAnonymous() const +{ + return mAnonymous; +} + +void ResourceLDAP::setAttributes( const QMap<QString, QString> &attributes ) +{ + mAttributes = attributes; +} + +QMap<QString, QString> ResourceLDAP::attributes() const +{ + return mAttributes; +} + +void addModOp( LDAPMod ***pmods, const QString &attr, const QString &value ) +{ + if ( value.isNull() ) + return; + + LDAPMod **mods; + + mods = *pmods; + + uint i = 0; + if ( mods != 0 ) + for ( ; mods[ i ] != 0; ++i ); + + if (( mods = (LDAPMod **)realloc( mods, (i + 2) * sizeof( LDAPMod * ))) == 0 ) { + kdError() << "ResourceLDAP: realloc" << endl; + return; + } + + *pmods = mods; + mods[ i + 1 ] = 0; + + mods[ i ] = new LDAPMod; + + mods[ i ]->mod_op = 0; + mods[ i ]->mod_type = strdup( attr.utf8() ); + mods[ i ]->mod_values = new char*[ 2 ]; + mods[ i ]->mod_values[ 0 ] = strdup( value.utf8() ); + mods[ i ]->mod_values[ 1 ] = 0; +} + diff --git a/kabc/plugins/ldap/resourceldap.h b/kabc/plugins/ldap/resourceldap.h new file mode 100644 index 0000000..0625f30 --- a/dev/null +++ b/kabc/plugins/ldap/resourceldap.h @@ -0,0 +1,99 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_RESOURCELDAP_H +#define KABC_RESOURCELDAP_H + + +#include <lber.h> +#include <ldap.h> + +#include "addressbook.h" +#include "resource.h" + +class KConfig; + +namespace KABC { + +class ResourceLDAP : public Resource +{ +public: + + ResourceLDAP( const KConfig* ); + + virtual void writeConfig( KConfig* ); + + virtual bool doOpen(); + virtual void doClose(); + + virtual Ticket *requestSaveTicket(); + + virtual bool load(); + virtual bool save( Ticket * ); + + virtual void removeAddressee( const Addressee& addr ); + + void setUser( const QString &user ); + QString user() const; + + void setPassword( const QString &password ); + QString password() const; + + void setDn( const QString &dn ); + QString dn() const; + + void setHost( const QString &host ); + QString host() const; + + void setPort( int port ); + int port() const; + + void setFilter( const QString &filter ); + QString filter() const; + + void setIsAnonymous( bool value ); + bool isAnonymous() const; + + void setAttributes( const QMap<QString, QString> &attributes ); + QMap<QString, QString> attributes() const; + +private: + QString mUser; + QString mPassword; + QString mDn; + QString mHost; + QString mFilter; + int mPort; + bool mAnonymous; + QMap<QString, QString> mAttributes; + + LDAP *mLdap; +}; + +} + +#endif diff --git a/kabc/plugins/ldap/resourceldapconfig.cpp b/kabc/plugins/ldap/resourceldapconfig.cpp new file mode 100644 index 0000000..2c0d030 --- a/dev/null +++ b/kabc/plugins/ldap/resourceldapconfig.cpp @@ -0,0 +1,254 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qspinbox.h> +#include <qvbox.h> + +//US #include <kaccelmanager.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <klocale.h> +#include <klineedit.h> + +#include "resourceldap.h" + +#include "resourceldapconfig.h" + +using namespace KABC; + +ResourceLDAPConfig::ResourceLDAPConfig( QWidget* parent, const char* name ) + : KRES::ConfigWidget( parent, name ) +{ + QGridLayout *mainLayout = new QGridLayout( this, 8, 2, 0, + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "User:" ), this ); + mUser = new KLineEdit( this ); + + mainLayout->addWidget( label, 0, 0 ); + mainLayout->addWidget( mUser, 0, 1 ); + + label = new QLabel( i18n( "Password:" ), this ); + mPassword = new KLineEdit( this ); + mPassword->setEchoMode( KLineEdit::Password ); + + mainLayout->addWidget( label, 1, 0 ); + mainLayout->addWidget( mPassword, 1, 1 ); + + label = new QLabel( i18n( "Host:" ), this ); + mHost = new KLineEdit( this ); + + mainLayout->addWidget( label, 2, 0 ); + mainLayout->addWidget( mHost, 2, 1 ); + + label = new QLabel( i18n( "Port:" ), this ); + QVBox *box = new QVBox( this ); + mPort = new QSpinBox( 0, 65535, 1, box ); + mPort->setSizePolicy( QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred ) ); + mPort->setValue( 389 ); + new QWidget( box, "dummy" ); + + mainLayout->addWidget( label, 3, 0 ); + mainLayout->addWidget( box, 3, 1 ); + + label = new QLabel( i18n( "Dn:" ), this ); + mDn = new KLineEdit( this ); + + mainLayout->addWidget( label, 4, 0 ); + mainLayout->addWidget( mDn, 4, 1 ); + + label = new QLabel( i18n( "Filter:" ), this ); + mFilter = new KLineEdit( this ); + + mainLayout->addWidget( label, 5, 0 ); + mainLayout->addWidget( mFilter, 5, 1 ); + + mAnonymous = new QCheckBox( i18n( "Anonymous login" ), this ); + mainLayout->addMultiCellWidget( mAnonymous, 6, 6, 0, 1 ); + + mEditButton = new QPushButton( i18n( "Edit Attributes..." ), this ); + mainLayout->addMultiCellWidget( mEditButton, 7, 7, 0, 1 ); + + connect( mAnonymous, SIGNAL( toggled(bool) ), mUser, SLOT( setDisabled(bool) ) ); + connect( mAnonymous, SIGNAL( toggled(bool) ), mPassword, SLOT( setDisabled(bool) ) ); + connect( mEditButton, SIGNAL( clicked() ), SLOT( editAttributes() ) ); +} + +void ResourceLDAPConfig::loadSettings( KRES::Resource *res ) +{ +//US ResourceLDAP *resource = dynamic_cast<ResourceLDAP*>( res ); + ResourceLDAP *resource = (ResourceLDAP*)( res ); + + if ( !resource ) { + kdDebug(5700) << "ResourceLDAPConfig::loadSettings(): cast failed" << endl; + return; + } + + mUser->setText( resource->user() ); + mPassword->setText( resource->password() ); + mHost->setText( resource->host() ); + mPort->setValue( resource->port() ); + mDn->setText( resource->dn() ); + mFilter->setText( resource->filter() ); + mAnonymous->setChecked( resource->isAnonymous() ); + mAttributes = resource->attributes(); +} + +void ResourceLDAPConfig::saveSettings( KRES::Resource *res ) +{ +//US ResourceLDAP *resource = dynamic_cast<ResourceLDAP*>( res ); + ResourceLDAP *resource = (ResourceLDAP*)( res ); + + if ( !resource ) { + kdDebug(5700) << "ResourceLDAPConfig::saveSettings(): cast failed" << endl; + return; + } + + resource->setUser( mUser->text() ); + resource->setPassword( mPassword->text() ); + resource->setHost( mHost->text() ); + resource->setPort( mPort->value() ); + resource->setDn( mDn->text() ); + resource->setFilter( mFilter->text() ); + resource->setIsAnonymous( mAnonymous->isChecked() ); + resource->setAttributes( mAttributes ); +} + +void ResourceLDAPConfig::editAttributes() +{ + AttributesDialog dlg( mAttributes, this ); + if ( dlg.exec() ) + mAttributes = dlg.attributes(); +} + +AttributesDialog::AttributesDialog( const QMap<QString, QString> &attributes, + QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Attributes Configuration" ), Ok | Cancel, + Ok, parent, name, true, true ) +{ + mNameDict.setAutoDelete( true ); + mNameDict.insert( "commonName", new QString( i18n( "Common name" ) ) ); + mNameDict.insert( "formattedName", new QString( i18n( "Formatted name" ) ) ); + mNameDict.insert( "familyName", new QString( i18n( "Family name" ) ) ); + mNameDict.insert( "givenName", new QString( i18n( "Given name" ) ) ); + mNameDict.insert( "mail", new QString( i18n( "Email" ) ) ); + mNameDict.insert( "mailAlias", new QString( i18n( "Email alias" ) ) ); + mNameDict.insert( "phoneNumber", new QString( i18n( "Telephone number" ) ) ); + mNameDict.insert( "uid", new QString( i18n( "UID" ) ) ); + + // overwrite the default values here + QMap<QString, QString> kolabMap, netscapeMap, evolutionMap, outlookMap; + + // kolab + kolabMap.insert( "formattedName", "display-name" ); + kolabMap.insert( "mailAlias", "mailalias" ); + + // evolution + evolutionMap.insert( "formattedName", "fileAs" ); + + mMapList.append( attributes ); + mMapList.append( kolabMap ); + mMapList.append( netscapeMap ); + mMapList.append( evolutionMap ); + mMapList.append( outlookMap ); + + QFrame *page = plainPage(); + QGridLayout *layout = new QGridLayout( page, 2, attributes.count() + 1, + 0, spacingHint() ); + + QLabel *label = new QLabel( i18n( "Template:" ), page ); + layout->addWidget( label, 0, 0 ); + mMapCombo = new KComboBox( page ); + layout->addWidget( mMapCombo, 0, 1 ); + + mMapCombo->insertItem( i18n( "User Defined" ) ); + mMapCombo->insertItem( i18n( "Kolab" ) ); + mMapCombo->insertItem( i18n( "Netscape" ) ); + mMapCombo->insertItem( i18n( "Evolution" ) ); + mMapCombo->insertItem( i18n( "Outlook" ) ); + connect( mMapCombo, SIGNAL( activated( int ) ), SLOT( mapChanged( int ) ) ); + + QMap<QString, QString>::ConstIterator it; + int i; + for ( i = 1, it = attributes.begin(); it != attributes.end(); ++it, ++i ) { + label = new QLabel( *mNameDict[ it.key() ] + ":", page ); + KLineEdit *lineedit = new KLineEdit( page ); + mLineEditDict.insert( it.key(), lineedit ); + lineedit->setText( it.data() ); + label->setBuddy( lineedit ); + layout->addWidget( label, i, 0 ); + layout->addWidget( lineedit, i, 1 ); + } + +//US KAcceleratorManager::manage( this ); +} + +AttributesDialog::~AttributesDialog() +{ +} + +QMap<QString, QString> AttributesDialog::attributes() const +{ + QMap<QString, QString> map; + + QDictIterator<KLineEdit> it( mLineEditDict ); + for ( ; it.current(); ++it ) + map.insert( it.currentKey(), it.current()->text() ); + + return map; +} + +void AttributesDialog::mapChanged( int pos ) +{ + // default map + QMap<QString, QString> defaultMap; + defaultMap.insert( "commonName", "cn" ); + defaultMap.insert( "formattedName", "displayName" ); + defaultMap.insert( "familyName", "sn" ); + defaultMap.insert( "givenName", "givenName" ); + defaultMap.insert( "mail", "mail" ); + defaultMap.insert( "mailAlias", "" ); + defaultMap.insert( "phoneNumber", "telephoneNumber" ); + defaultMap.insert( "uid", "uid" ); + + // apply first the default and than the spezific changes + QMap<QString, QString>::Iterator it; + for ( it = defaultMap.begin(); it != defaultMap.end(); ++it ) + mLineEditDict[ it.key() ]->setText( it.data() ); + + for ( it = mMapList[ pos ].begin(); it != mMapList[ pos ].end(); ++it ) { + if ( !it.data().isEmpty() ) + mLineEditDict[ it.key() ]->setText( it.data() ); + } +} + +//US #include "resourceldapconfig.moc" diff --git a/kabc/plugins/ldap/resourceldapconfig.h b/kabc/plugins/ldap/resourceldapconfig.h new file mode 100644 index 0000000..42d30ff --- a/dev/null +++ b/kabc/plugins/ldap/resourceldapconfig.h @@ -0,0 +1,100 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef RESOURCELDAPCONFIG_H +#define RESOURCELDAPCONFIG_H + +#include <qmap.h> +//US +#include <qdict.h> + +#include <kdialogbase.h> +#include <kresources/configwidget.h> + +class QCheckBox; +class QPushButton; +class QSpinBox; +class QString; + +class KComboBox; +class KLineEdit; + +namespace KABC { + +class ResourceLDAPConfig : public KRES::ConfigWidget +{ + Q_OBJECT + + public: + ResourceLDAPConfig( QWidget* parent = 0, const char* name = 0 ); + + public slots: + void loadSettings( KRES::Resource* ); + void saveSettings( KRES::Resource* ); + + private slots: + void editAttributes(); + + private: + KLineEdit *mUser; + KLineEdit *mPassword; + KLineEdit *mHost; + QSpinBox *mPort; + KLineEdit *mDn; + KLineEdit *mFilter; + QCheckBox *mAnonymous; + QPushButton *mEditButton; + QMap<QString, QString> mAttributes; +}; + +class AttributesDialog : public KDialogBase +{ + Q_OBJECT + + public: + AttributesDialog( const QMap<QString, QString> &attributes, QWidget *parent, + const char *name = 0 ); + ~AttributesDialog(); + + QMap<QString, QString> attributes() const; + + private slots: + void mapChanged( int pos ); + + private: + enum { UserMap, KolabMap, NetscapeMap, EvolutionMap, OutlookMap }; + + KComboBox *mMapCombo; + QValueList< QMap<QString, QString> > mMapList; + + QDict<KLineEdit> mLineEditDict; + QDict<QString> mNameDict; +}; + +} + +#endif diff --git a/kabc/resource.cpp b/kabc/resource.cpp new file mode 100644 index 0000000..9a1a5f8 --- a/dev/null +++ b/kabc/resource.cpp @@ -0,0 +1,95 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <kdebug.h> + +#include "resource.h" + +using namespace KABC; + +Resource::Resource( const KConfig *config ) + : KRES::Resource( config ), mAddressBook( 0 ) +{ +} + +Resource::~Resource() +{ +} + +void Resource::writeConfig( KConfig *config ) +{ + KRES::Resource::writeConfig( config ); +} + +void Resource::setAddressBook( AddressBook *ab ) +{ + mAddressBook = ab; +} + +AddressBook *Resource::addressBook() +{ + return mAddressBook; +} + +bool Resource::doOpen() +{ + return true; +} + +void Resource::doClose() +{ +} + +Ticket *Resource::requestSaveTicket() +{ + return 0; +} + +bool Resource::load() +{ + return true; +} + +bool Resource::save( Ticket * ) +{ + return false; +} + +Ticket *Resource::createTicket( Resource *resource ) +{ + return new Ticket( resource ); +} + +void Resource::removeAddressee( const Addressee& ) +{ + // do nothing +} + +void Resource::cleanUp() +{ + // do nothing +} diff --git a/kabc/resource.h b/kabc/resource.h new file mode 100644 index 0000000..c363125 --- a/dev/null +++ b/kabc/resource.h @@ -0,0 +1,134 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_RESOURCE_H +#define KABC_RESOURCE_H + +#include <kresources/resource.h> + +#include "addressbook.h" + +namespace KABC { + +/** + * @short Helper class for handling coordinated save of address books. + * + * This class is used as helper class for saving address book. + * @see requestSaveTicket(), save(). + */ +class Ticket +{ + friend class Resource; + public: + Resource *resource() { return mResource; } + + private: + Ticket( Resource *resource ) : mResource( resource ) {} + + Resource *mResource; +}; + +/** + * @internal + */ +class Resource : public KRES::Resource +{ +public: + /** + * Constructor + */ + Resource( const KConfig *config ); + + /** + * Destructor. + */ + virtual ~Resource(); + + /** + * Sets the address book of the resource. + */ + void setAddressBook( AddressBook* ); + + /** + * Returns a pointer to the addressbook. + */ + AddressBook *addressBook(); + + /** + * Writes the resource specific config to file. + */ + virtual void writeConfig( KConfig *config ); + + /** + * Open the resource and returns if it was successfully + */ + virtual bool doOpen(); + + /** + * Close the resource and returns if it was successfully + */ + virtual void doClose(); + + /** + * Request a ticket, you have to pass through @ref save() to + * allow locking. + */ + virtual Ticket *requestSaveTicket(); + + /** + * Load all addressees to the addressbook + */ + virtual bool load(); + + /** + * Save all addressees to the addressbook. + * + * @param ticket The ticket you get by @ref requestSaveTicket() + */ + virtual bool save( Ticket *ticket ); + + /** + * Removes a addressee from resource. This method is mainly + * used by record-based resources like LDAP or SQL. + */ + virtual void removeAddressee( const Addressee& addr ); + + /** + * This method is called by an error handler if the application + * crashed + */ + virtual void cleanUp(); + +protected: + Ticket *createTicket( Resource * ); + +private: + AddressBook *mAddressBook; +}; + +} +#endif diff --git a/kabc/secrecy.cpp b/kabc/secrecy.cpp new file mode 100644 index 0000000..f4bcb51 --- a/dev/null +++ b/kabc/secrecy.cpp @@ -0,0 +1,107 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <klocale.h> + +#include "secrecy.h" + +using namespace KABC; + +Secrecy::Secrecy( int type ) + : mType( type ) +{ +} + +bool Secrecy::operator==( const Secrecy &s ) const +{ + return ( mType == s.mType ); +} + +bool Secrecy::operator!=( const Secrecy &s ) const +{ + return !( *this == s ); +} + +bool Secrecy::isValid() const +{ + return mType != Invalid; +} + +void Secrecy::setType( int type ) +{ + mType = type; +} + +int Secrecy::type() const +{ + return mType; +} + +Secrecy::TypeList Secrecy::typeList() +{ + TypeList list; + list << Public; + list << Private; + list << Confidential; + + return list; +} + +QString Secrecy::typeLabel( int type ) +{ + switch ( type ) { + case Public: + return i18n( "Public" ); + break; + case Private: + return i18n( "Private" ); + break; + case Confidential: + return i18n( "Confidential" ); + break; + default: + return i18n( "Unknown type" ); + break; + } +} + +QString Secrecy::asString() const +{ + return typeLabel( mType ); +} + +QDataStream &KABC::operator<<( QDataStream &s, const Secrecy &secrecy ) +{ + return s << secrecy.mType; +} + +QDataStream &KABC::operator>>( QDataStream &s, Secrecy &secrecy ) +{ + s >> secrecy.mType; + + return s; +} diff --git a/kabc/secrecy.h b/kabc/secrecy.h new file mode 100644 index 0000000..8f2f736 --- a/dev/null +++ b/kabc/secrecy.h @@ -0,0 +1,102 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_SECRECY_H +#define KABC_SECRECY_H + +#include <qvaluelist.h> + +namespace KABC { + +class Secrecy +{ + friend QDataStream &operator<<( QDataStream &, const Secrecy & ); + friend QDataStream &operator>>( QDataStream &, Secrecy & ); + +public: + typedef QValueList<int> TypeList; + + /** + * Secrecy types + * + * @li Public - for public access + * @li Private - only private access + * @li Confidential - access for confidential persons + */ + enum Types { + Public, + Private, + Confidential, + Invalid + }; + + /** + * Constructor. + * + * @param type The secrecy type, @see Types. + */ + Secrecy( int type = Invalid ); + + bool operator==( const Secrecy & ) const; + bool operator!=( const Secrecy & ) const; + + /** + Returns if the Secrecy object has a valid value. + */ + bool isValid() const; + + /** + * Sets the type, @see Types. + */ + void setType( int type ); + + /** + * Returns the type, @see Types. + */ + int type() const; + + /** + * Returns a list of all available secrecy types. + */ + static TypeList typeList(); + + /** + * Returns a translated label for a given secrecy type. + */ + static QString typeLabel( int type ); + + /** + * For debug. + */ + QString asString() const; + +private: + int mType; +}; + +} +#endif diff --git a/kabc/sound.cpp b/kabc/sound.cpp new file mode 100644 index 0000000..b2e5254 --- a/dev/null +++ b/kabc/sound.cpp @@ -0,0 +1,117 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk changes + +$Id$ +*/ + +#include "sound.h" + +#include <qdatastream.h> + +using namespace KABC; + +Sound::Sound() + : mIntern( false ) +{ +} + +Sound::Sound( const QString &url ) + : mUrl( url ), mIntern( false ) +{ +} + +Sound::Sound( const QByteArray &data ) + : mData( data ), mIntern( true ) +{ +} + +Sound::~Sound() +{ +} + +bool Sound::operator==( const Sound &s ) const +{ + if ( mIntern != s.mIntern ) return false; + + if ( mIntern ) { + if ( mData != s.mData ) + return false; + } else { + if ( mUrl != s.mUrl ) + return false; + } + + return true; +} + +bool Sound::operator!=( const Sound &s ) const +{ + return !( s == *this ); +} + +void Sound::setUrl( const QString &url ) +{ + mUrl = url; + mIntern = false; +} + +void Sound::setData( const QByteArray &data ) +{ + mData = data; + mIntern = true; +} + +bool Sound::isIntern() const +{ + return mIntern; +} + +QString Sound::url() const +{ + return mUrl; +} + +QByteArray Sound::data() const +{ + return mData; +} + +QString Sound::asString() const +{ + if ( mIntern ) + return "intern sound"; + else + return mUrl; +} + +QDataStream &KABC::operator<<( QDataStream &s, const Sound &sound ) +{ + return s << sound.mIntern << sound.mUrl << sound.mData; +} + +QDataStream &KABC::operator>>( QDataStream &s, Sound &sound ) +{ + s >> sound.mIntern >> sound.mUrl >> sound.mData; + return s; +} diff --git a/kabc/sound.h b/kabc/sound.h new file mode 100644 index 0000000..0ec5ec8 --- a/dev/null +++ b/kabc/sound.h @@ -0,0 +1,123 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_SOUND_H +#define KABC_SOUND_H + +#include <qcstring.h> +#include <qstring.h> + +namespace KABC { + +class Sound +{ + friend QDataStream &operator<<( QDataStream &, const Sound & ); + friend QDataStream &operator>>( QDataStream &, Sound & ); + +public: + + /** + * Consturctor. Creates an empty object. + */ + Sound(); + + /** + * Consturctor. + * + * @param url A URL that describes the position of the sound file. + */ + Sound( const QString &url ); + + /** + * Consturctor. + * + * @param data The raw data of the sound. + */ + Sound( const QByteArray &data ); + + /** + * Destructor. + */ + ~Sound(); + + + bool operator==( const Sound & ) const; + bool operator!=( const Sound & ) const; + + /** + * Sets a URL for the location of the sound file. When using this + * function, @ref isIntern() will return 'false' until you use + * @ref setData(). + * + * @param url The location URL of the sound file. + */ + void setUrl( const QString &url ); + + /** + * Sets the raw data of the sound. When using this function, + * @ref isIntern() will return 'true' until you use @ref setUrl(). + * + * @param data The raw data of the sound. + */ + void setData( const QByteArray &data ); + + /** + * Returns whether the sound is described by a URL (extern) or + * by the raw data (intern). + * When this method returns 'true' you can use @ref data() to + * get the raw data. Otherwise you can request the URL of this + * sound by @ref url() and load the raw data from that location. + */ + bool isIntern() const; + + /** + * Returns the location URL of this sound. + */ + QString url() const; + + /** + * Returns the raw data of this sound. + */ + QByteArray data() const; + + /** + * Returns string representation of the sound. + */ + QString asString() const; + +private: + QString mUrl; + QByteArray mData; + + int mIntern; +}; + +QDataStream &operator<<( QDataStream &, const Sound & ); +QDataStream &operator>>( QDataStream &, Sound & ); + +} +#endif diff --git a/kabc/stdaddressbook.cpp b/kabc/stdaddressbook.cpp new file mode 100644 index 0000000..f9fc70b --- a/dev/null +++ b/kabc/stdaddressbook.cpp @@ -0,0 +1,249 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ +#ifndef DESKTOP_VERSION +#include <qpe/global.h> +#else + +#include <qdir.h> +#endif +#ifdef KAB_EMBEDDED + +#include <stdlib.h> +#else //KAB_EMBEDDED + +#include <stdlib.h> + +//US#include <kresources/manager.h> +#include <kapplication.h> +#include <kcrash.h> +#include <ksimpleconfig.h> + + +#endif //KAB_EMBEDDED + +#include "resource.h" +#include <kresources/manager.h> +#include <kdebug.h> +#include <klocale.h> +#include <kstaticdeleter.h> +#include <kstandarddirs.h> + +#include "stdaddressbook.h" + +using namespace KABC; + +StdAddressBook *StdAddressBook::mSelf = 0; +bool StdAddressBook::mAutomaticSave = true; + +static KStaticDeleter<StdAddressBook> addressBookDeleter; + +QString StdAddressBook::fileName() +{ + return locateLocal( "data", "kabc/std.vcf" ); +} + +QString StdAddressBook::directoryName() +{ + qDebug("StdAddressBook::directoryName() WILL FAIL OR NOT" ); + return locateLocal( "data", "kabc/stdvcf" ); +} + +void StdAddressBook::handleCrash() +{ + StdAddressBook::self()->cleanUp(); +} + +StdAddressBook *StdAddressBook::self() +{ + + if ( !mSelf ) + { + QString appdir = StdAddressBook::setTempAppDir(); + + kdDebug(5700) << "StdAddressBook::self()" << endl; +// US im am not sure why I have to use the other format here?? +#ifdef KAB_EMBEDDED + mSelf = addressBookDeleter.setObject( new StdAddressBook ); +#else //KAB_EMBEDDED + addressBookDeleter.setObject( mSelf, new StdAddressBook ); +#endif //KAB_EMBEDDED + KStandardDirs::setAppDir( appdir ); + } + + return mSelf; +} + +QString StdAddressBook::setTempAppDir() +{ + QString appDIR = KStandardDirs::appDir(); +#ifdef DESKTOP_VERSION + QString appdir = QDir::homeDirPath(); + if ( appdir.right(1) == "\\" || appdir.right(1) == "/" ) + appdir += "kaddressbook/"; + else + appdir += "/kaddressbook/"; + KStandardDirs::setAppDir( QDir::convertSeparators( appdir )); +#else + KStandardDirs::setAppDir( Global::applicationFileName( "kaddressbook", "" ) ); +#endif + + return appDIR; +} +StdAddressBook *StdAddressBook::self( bool onlyFastResources ) +{ + + if ( !mSelf ) + { + QString appdir =StdAddressBook::setTempAppDir(); +#ifdef KAB_EMBEDDED + mSelf = addressBookDeleter.setObject( new StdAddressBook( onlyFastResources ) ); +#else //KAB_EMBEDDED + addressBookDeleter.setObject( mSelf, new StdAddressBook( onlyFastResources ) ); +#endif //KAB_EMBEDDED + KStandardDirs::setAppDir( appdir ); + } + return mSelf; +} + +StdAddressBook::StdAddressBook() +//US : AddressBook( "kabcrc" ) + : AddressBook( locateLocal( "config", "kabcrc") ) +{ + + init( false ); +} + +StdAddressBook::StdAddressBook( bool onlyFastResources ) +//US : AddressBook( "kabcrc" ) + : AddressBook( locateLocal( "config", "kabcrc") ) +{ + + init( onlyFastResources ); +} + +StdAddressBook::~StdAddressBook() +{ + if ( mAutomaticSave ) + save(); +} + +void StdAddressBook::init( bool ) +{ + KRES::Manager<Resource> *manager = resourceManager(); + KRES::Manager<Resource>::ActiveIterator it; + + for ( it = manager->activeBegin(); it != manager->activeEnd(); ++it ) { + (*it)->setAddressBook( this ); + if ( !(*it)->open() ) + error( QString( "Unable to open resource '%1'!" ).arg( (*it)->resourceName() ) ); + } + + Resource *res = standardResource(); + if ( !res ) { + res = manager->createResource( "file" ); + if ( res ) + { + addResource( res ); + } + else + kdDebug(5700) << "No resource available!!!" << endl; + } + + setStandardResource( res ); + manager->writeConfig(); + + load(); +} + +bool StdAddressBook::save() +{ + kdDebug(5700) << "StdAddressBook::save()" << endl; + + bool ok = true; + AddressBook *ab = self(); + + ab->deleteRemovedAddressees(); + + KRES::Manager<Resource>::ActiveIterator it; + KRES::Manager<Resource> *manager = ab->resourceManager(); + for ( it = manager->activeBegin(); it != manager->activeEnd(); ++it ) { + if ( !(*it)->readOnly() && (*it)->isOpen() ) { + Ticket *ticket = ab->requestSaveTicket( *it ); +// qDebug("StdAddressBook::save '%s'", (*it)->resourceName().latin1() ); + if ( !ticket ) { + ab->error( i18n( "Unable to save to resource '%1'. It is locked." ) + .arg( (*it)->resourceName() ) ); + return false; + } + + if ( !ab->save( ticket ) ) + ok = false; + } + } + + return ok; +} + +void StdAddressBook::close() +{ +//US destructObject is not defined on my system???. Is setObject(0) the same ??? +#ifndef KAB_EMBEDDED + addressBookDeleter.destructObject(); +#else //KAB_EMBEDDED + addressBookDeleter.setObject(0); +#endif //KAB_EMBEDDED + +} + +void StdAddressBook::setAutomaticSave( bool enable ) +{ + mAutomaticSave = enable; +} + +bool StdAddressBook::automaticSave() +{ + return mAutomaticSave; +} + +// should get const for 4.X +Addressee StdAddressBook::whoAmI() +{ +//US KConfig config( "kabcrc" ); + KConfig config( locateLocal("config", "kabcrc") ); + config.setGroup( "General" ); + + return findByUid( config.readEntry( "WhoAmI" ) ); +} + +void StdAddressBook::setWhoAmI( const Addressee &addr ) +{ +//US KConfig config( "kabcrc" ); + KConfig config( locateLocal("config", "kabcrc") ); + config.setGroup( "General" ); + + config.writeEntry( "WhoAmI", addr.uid() ); +} diff --git a/kabc/stdaddressbook.h b/kabc/stdaddressbook.h new file mode 100644 index 0000000..9ec53b0 --- a/dev/null +++ b/kabc/stdaddressbook.h @@ -0,0 +1,151 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_STDADDRESSBOOK_H +#define KABC_STDADDRESSBOOK_H + +#include "addressbook.h" + +namespace KABC { + +/** + Standard KDE address book + + This class provides access to the standard KDE address book shared by all + applications. + + It's implemented as a singleton. Use @ref self() to get the address book + object. On the first self() call the address book also gets loaded. + + Example: + + <pre> + KABC::AddressBook *ab = KABC::StdAddressBook::self(); + + KABC::AddressBook::Iterator it; + for ( it = ab->begin(); it != ab->end(); ++it ) { + kdDebug() << "UID=" << (*it).uid() << endl; + + // do some other stuff + } + + KABC::StdAddressBook::save(); + </pre> +*/ +class StdAddressBook : public AddressBook +{ + public: + + /** + Destructor. + */ + ~StdAddressBook(); + + /** + Return the standard addressbook object. It also loads slow resources. + It is the same as self(false); . + */ + static StdAddressBook *self(); + + /** + This is the same as above, but with specified + behaviour of resource loading. + + @param onlyFastResource Only resources marked as 'fast' should be loaded + */ + // FIXME for KDE4 return StdAddressBook and merge with the metod above -zecke + static StdAddressBook *self( bool onlyFastResources ); + + /** + Save the standard address book to disk. + */ + static bool save(); + + /** + Call this method in your crash handler to allow the library clean up + possible locks. + */ + static void handleCrash(); + + /** + Returns the default file name for vcard-based addressbook + */ + static QString fileName(); + + /** + Returns the default directory name for vcard-based addressbook + */ + static QString directoryName(); + + /** + Set the automatic save property of the address book. + If @p enable is TRUE (default) the address book is saved at + destruction time otherwise you have to call @ref save() to + explicitely save it. + */ + static void setAutomaticSave( bool enable ); + + /** + Closes the address book. Depending on @ref automaticSave() it will + save the address book first. + */ + static void close(); + + /** + Returns whether the address book is saved at destruction time. + See also @ref setAutomaticSave(). + */ + static bool automaticSave(); + + /** + Returns the contact, that is associated with the owner of the + address book. This contact should be used by other programs + to access user specific data. + */ + Addressee whoAmI(); + + /** + Sets the users contact. See @ref whoAmI() for more information. + + @param uid The uid of the users contact. + */ + void setWhoAmI( const Addressee &addr ); + + protected: + StdAddressBook(); + StdAddressBook( bool onlyFastResources ); + + void init( bool onlyFastResources ); + + private: + static QString setTempAppDir(); + static StdAddressBook *mSelf; + static bool mAutomaticSave; +}; + +} +#endif diff --git a/kabc/timezone.cpp b/kabc/timezone.cpp new file mode 100644 index 0000000..2018395 --- a/dev/null +++ b/kabc/timezone.cpp @@ -0,0 +1,92 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qdatastream.h> + +#include "timezone.h" + +using namespace KABC; + +TimeZone::TimeZone() : + mOffset( 0 ), mValid( false ) +{ +} + +TimeZone::TimeZone( int offset ) : + mOffset( offset ), mValid( true ) +{ +} + +void TimeZone::setOffset( int offset ) +{ + mOffset = offset; + mValid = true; +} + +int TimeZone::offset() const +{ + return mOffset; +} + +bool TimeZone::isValid() const +{ + return mValid; +} + +bool TimeZone::operator==( const TimeZone &t ) const +{ + if ( !t.isValid() && !isValid() ) return true; + if ( !t.isValid() || !isValid() ) return false; + if ( t.mOffset == mOffset ) return true; + return false; +} + +bool TimeZone::operator!=( const TimeZone &t ) const +{ + if ( !t.isValid() && !isValid() ) return false; + if ( !t.isValid() || !isValid() ) return true; + if ( t.mOffset != mOffset ) return true; + return false; +} + +QString TimeZone::asString() const +{ + return QString::number( mOffset ); +} + +QDataStream &KABC::operator<<( QDataStream &s, const TimeZone &zone ) +{ + return s << zone.mOffset; +} + +QDataStream &KABC::operator>>( QDataStream &s, TimeZone &zone ) +{ + s >> zone.mOffset; + zone.mValid = true; + + return s; +} diff --git a/kabc/timezone.h b/kabc/timezone.h new file mode 100644 index 0000000..8d96e03 --- a/dev/null +++ b/kabc/timezone.h @@ -0,0 +1,94 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_TIMEZONE_H +#define KABC_TIMEZONE_H + +#include <qstring.h> + +namespace KABC { + +/** + * @short Time zone information. + * + * This class stores information about a time zone. + */ +class TimeZone +{ + friend QDataStream &operator<<( QDataStream &, const TimeZone & ); + friend QDataStream &operator>>( QDataStream &, TimeZone & ); + +public: + + /** + * Construct invalid time zone. + */ + TimeZone(); + + /** + * Construct time zone. + * + * @param offset Offset in minutes relative to UTC. + */ + TimeZone( int offset ); + + /** + * Set time zone offset relative to UTC. + * + * @param offset Offset in minutes. + */ + void setOffset( int ); + + /** + * Return offset in minutes relative to UTC. + */ + int offset() const; + + /** + * Return, if this time zone object is valid. + */ + bool isValid() const; + + bool operator==( const TimeZone & ) const; + bool operator!=( const TimeZone & ) const; + + /** + * Return string representation of time zone offset. + */ + QString asString() const; + +private: + int mOffset; // Offset in minutes + + bool mValid; +}; + +QDataStream &operator<<( QDataStream &, const TimeZone & ); +QDataStream &operator>>( QDataStream &, TimeZone & ); + +} +#endif diff --git a/kabc/vcard/AdrParam.cpp b/kabc/vcard/AdrParam.cpp new file mode 100644 index 0000000..fa46499 --- a/dev/null +++ b/kabc/vcard/AdrParam.cpp @@ -0,0 +1,126 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardRToken.h> +#include <VCardAdrParam.h> +#include <VCardParam.h> + +using namespace VCARD; + +AdrParam::AdrParam() + : Param() +{ +} + +AdrParam::AdrParam(const AdrParam & x) + : Param(x), + adrTypeList_ (x.adrTypeList_) +{ +} + +AdrParam::AdrParam(const QCString & s) + : Param(s) +{ +} + + AdrParam & +AdrParam::operator = (AdrParam & x) +{ + if (*this == x) return *this; + + adrTypeList_ = x.adrTypeList(); + textParam_ = x.textParam(); + + Param::operator = (x); + return *this; +} + + AdrParam & +AdrParam::operator = (const QCString & s) +{ + Param::operator = (s); + + adrTypeList_.clear(); + textParam_.truncate(0); + + return *this; +} + + bool +AdrParam::operator == (AdrParam & x) +{ + parse(); + + if (!x.textParam().isEmpty()) + return (x.textParam_ == textParam_); + + if (x.adrTypeList().count() != adrTypeList_.count()) + return false; + + QStrListIterator it(x.adrTypeList_); + + for (; it.current(); ++it) + if (!adrTypeList_.find(it.current())) + return false; + + return true; +} + +AdrParam::~AdrParam() +{ +} + + void +AdrParam::_parse() +{ + adrTypeList_.clear(); + + if (strRep_.left(4) != "TYPE") { + textParam_ = strRep_; + return; + } + + if (!strRep_.contains('=')) + return; + + RTokenise(strRep_, ",", adrTypeList_); +} + + void +AdrParam::_assemble() +{ + if (!textParam_.isEmpty()) { + strRep_ = textParam_; + return; + } + + QStrListIterator it(adrTypeList_); + + for (; it.current(); ++it) { + + strRep_ += it.current(); + + if (it.current() != adrTypeList_.last()) + strRep_ += ','; + } +} diff --git a/kabc/vcard/AdrValue.cpp b/kabc/vcard/AdrValue.cpp new file mode 100644 index 0000000..7ecef33 --- a/dev/null +++ b/kabc/vcard/AdrValue.cpp @@ -0,0 +1,140 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardRToken.h> +#include <VCardAdrValue.h> +#include <VCardValue.h> +#include <VCardDefines.h> + +using namespace VCARD; + +AdrValue::AdrValue() + : Value() +{ +} + +AdrValue::AdrValue(const AdrValue & x) + : Value(x), + poBox_ (x.poBox_), + extAddress_ (x.extAddress_), + street_ (x.street_), + locality_ (x.locality_), + region_ (x.region_), + postCode_ (x.postCode_), + countryName_ (x.countryName_) +{ +} + +AdrValue::AdrValue(const QCString & s) + : Value(s) +{ +} + + AdrValue & +AdrValue::operator = (AdrValue & x) +{ + if (*this == x) return *this; + + poBox_ = x.poBox_; + extAddress_ = x.extAddress_; + street_ = x.street_; + locality_ = x.locality_; + region_ = x.region_; + postCode_ = x.postCode_; + countryName_ = x.countryName_; + + Value::operator = (x); + return *this; +} + + AdrValue & +AdrValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +AdrValue::operator == (AdrValue & x) +{ + parse(); + x.parse(); + + return ( + poBox_ == x.poBox_ && + extAddress_ == x.extAddress_ && + street_ == x.street_ && + locality_ == x.locality_ && + region_ == x.region_ && + postCode_ == x.postCode_ && + countryName_ == x.countryName_); +} + +AdrValue::~AdrValue() +{ +} + + AdrValue * +AdrValue::clone() +{ + return new AdrValue( *this ); +} + + void +AdrValue::_parse() +{ + vDebug("AdrValue::_parse()"); + + QStrList l; + RTokenise(strRep_, ";", l); + + for (unsigned int i = 0; i < l.count(); i++) { + + switch (i) { + + case 0: poBox_ = l.at(0); break; + case 1: extAddress_ = l.at(1); break; + case 2: street_ = l.at(2); break; + case 3: locality_ = l.at(3); break; + case 4: region_ = l.at(4); break; + case 5: postCode_ = l.at(5); break; + case 6: countryName_ = l.at(6); break; + default: break; + } + } +} + + void +AdrValue::_assemble() +{ + vDebug("AdrValue::_assemble"); + + strRep_ = poBox_; + strRep_ += ";" + extAddress_; + strRep_ += ";" + street_; + strRep_ += ";" + locality_; + strRep_ += ";" + region_; + strRep_ += ";" + postCode_; + strRep_ += ";" + countryName_; +} + diff --git a/kabc/vcard/AgentParam.cpp b/kabc/vcard/AgentParam.cpp new file mode 100644 index 0000000..5625e00 --- a/dev/null +++ b/kabc/vcard/AgentParam.cpp @@ -0,0 +1,103 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardAgentParam.h> + +#include <VCardParam.h> + +using namespace VCARD; + +AgentParam::AgentParam() + : Param() +{ +} + +AgentParam::AgentParam(const AgentParam & x) + : Param(x), + refer_ (x.refer_), + uri_ (x.uri_) +{ +} + +AgentParam::AgentParam(const QCString & s) + : Param(s) +{ +} + + AgentParam & +AgentParam::operator = (AgentParam & x) +{ + if (*this == x) return *this; + + refer_ = x.refer_; + uri_ = x.uri_; + + Param::operator = (x); + return *this; +} + + AgentParam & +AgentParam::operator = (const QCString & s) +{ + Param::operator = (s); + return *this; +} + + bool +AgentParam::operator == (AgentParam & x) +{ + parse(); + + if (refer_) + return (x.refer() && uri_ == x.uri_); + + return !x.refer(); +} + +AgentParam::~AgentParam() +{ +} + + void +AgentParam::_parse() +{ + if (strRep_.isEmpty()) { + refer_ = false; + return; + } + + refer_ = true; + uri_ = strRep_; +} + + void +AgentParam::_assemble() +{ + if (!refer_) { + strRep_.truncate(0); + return; + } + + strRep_ = uri_.asString(); + return; +} diff --git a/kabc/vcard/AgentValue.cpp b/kabc/vcard/AgentValue.cpp new file mode 100644 index 0000000..bccde80 --- a/dev/null +++ b/kabc/vcard/AgentValue.cpp @@ -0,0 +1,81 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardAgentValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +AgentValue::AgentValue() + : Value() +{ +} + +AgentValue::AgentValue(const AgentValue & x) + : Value(x) +{ +} + +AgentValue::AgentValue(const QCString & s) + : Value(s) +{ +} + + AgentValue & +AgentValue::operator = (AgentValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + AgentValue & +AgentValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +AgentValue::operator == (AgentValue & x) +{ + x.parse(); + return false; +} + +AgentValue::~AgentValue() +{ +} + + void +AgentValue::_parse() +{ +} + + void +AgentValue::_assemble() +{ +} + diff --git a/kabc/vcard/ClassValue.cpp b/kabc/vcard/ClassValue.cpp new file mode 100644 index 0000000..f01e5a6 --- a/dev/null +++ b/kabc/vcard/ClassValue.cpp @@ -0,0 +1,120 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardClassValue.h> + +#include <VCardValue.h> + +#include <kdebug.h> + +using namespace VCARD; + +ClassValue::ClassValue() + : Value() +{ +} + +ClassValue::ClassValue(const ClassValue & x) + : Value(x), + classType_(x.classType_) +{ +} + +ClassValue::ClassValue(const QCString & s) + : Value(s) +{ +} + + ClassValue & +ClassValue::operator = (ClassValue & x) +{ + if (*this == x) return *this; + x.parse(); + + classType_ = x.classType_; + + Value::operator = (x); + return *this; +} + + ClassValue & +ClassValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +ClassValue::operator == (ClassValue & x) +{ + x.parse(); + return ( classType_ == x.classType_ ); +} + +ClassValue::~ClassValue() +{ +} + + ClassValue * +ClassValue::clone() +{ + return new ClassValue( *this ); +} + + void +ClassValue::_parse() +{ + if (qstricmp(strRep_, "PUBLIC") == 0) + classType_ = Public; + + else if (qstricmp(strRep_, "PRIVATE") == 0) + classType_ = Private; + + else if (qstricmp(strRep_, "CONFIDENTIAL") == 0) + classType_ = Confidential; + + else classType_ = Other; +} + + void +ClassValue::_assemble() +{ + switch (classType_) { + + case Public: + strRep_ = "PUBLIC"; + break; + + case Private: + strRep_ = "PRIVATE"; + break; + + case Confidential: + strRep_ = "CONFIDENTIAL"; + break; + + default: + break; + } +} + diff --git a/kabc/vcard/ContentLine.cpp b/kabc/vcard/ContentLine.cpp new file mode 100644 index 0000000..6fa1a8f --- a/dev/null +++ b/kabc/vcard/ContentLine.cpp @@ -0,0 +1,289 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <qcstring.h> +#include <qstrlist.h> +#include <qregexp.h> + +#include <kdebug.h> + +#include <VCardAdrParam.h> +#include <VCardAgentParam.h> +#include <VCardDateParam.h> +#include <VCardEmailParam.h> +#include <VCardImageParam.h> +#include <VCardSourceParam.h> +#include <VCardTelParam.h> +#include <VCardTextBinParam.h> +#include <VCardTextParam.h> + +#include <VCardAdrValue.h> +#include <VCardAgentValue.h> +#include <VCardDateValue.h> +#include <VCardImageValue.h> +#include <VCardTextValue.h> +#include <VCardTextBinValue.h> +#include <VCardLangValue.h> +#include <VCardNValue.h> +#include <VCardURIValue.h> +#include <VCardSoundValue.h> +#include <VCardClassValue.h> +#include <VCardFloatValue.h> +#include <VCardOrgValue.h> +#include <VCardTelValue.h> +#include <VCardTextListValue.h> +#include <VCardUTCValue.h> +#include <VCardGeoValue.h> + +#include <VCardRToken.h> +#include <VCardContentLine.h> + +#include <VCardEntity.h> +#include <VCardEnum.h> +#include <VCardDefines.h> + +using namespace VCARD; + +ContentLine::ContentLine() + : Entity(), + value_(0) +{ +} + +ContentLine::ContentLine(const ContentLine & x) + : Entity(x), + group_ (x.group_), + name_ (x.name_), + paramList_(x.paramList_), + value_(x.value_->clone()) +{ +} + +ContentLine::ContentLine(const QCString & s) + : Entity(s), + value_(0) +{ +} + + ContentLine & +ContentLine::operator = (ContentLine & x) +{ + if (*this == x) return *this; + + paramList_ = x.paramList(); + value_ = x.value_->clone(); + + Entity::operator = (x); + return *this; +} + + ContentLine & +ContentLine::operator = (const QCString & s) +{ + Entity::operator = (s); + delete value_; + value_ = 0; + return *this; +} + + bool +ContentLine::operator == (ContentLine & x) +{ + x.parse(); + + QPtrListIterator<Param> it(x.paramList()); + + if (!paramList_.find(it.current())) + return false; + + return true; +} + +ContentLine::~ContentLine() +{ + delete value_; + value_ = 0; +} + + void +ContentLine::_parse() +{ + vDebug("parse"); + + // Unqote newlines + strRep_ = strRep_.replace( QRegExp( "\\\\n" ), "\n" ); + + int split = strRep_.find(':'); + + if (split == -1) { // invalid content line + vDebug("No ':'"); + return; + } + + QCString firstPart(strRep_.left(split)); + QCString valuePart(strRep_.mid(split + 1)); + + split = firstPart.find('.'); + + if (split != -1) { + group_ = firstPart.left(split); + firstPart = firstPart.mid(split + 1); + } + + vDebug("Group == " + group_); + vDebug("firstPart == " + firstPart); + vDebug("valuePart == " + valuePart); + + // Now we have the group, the name and param list together and the value. + + QStrList l; + + RTokenise(firstPart, ";", l); + + if (l.count() == 0) {// invalid - no name ! + vDebug("No name for this content line !"); + return; + } + + name_ = l.at(0); + + // Now we have the name, so the rest of 'l' is the params. + // Remove the name part. + l.remove(0u); + + entityType_ = EntityNameToEntityType(name_); + paramType_ = EntityTypeToParamType(entityType_); + + unsigned int i = 0; + + // For each parameter, create a new parameter of the correct type. + + QStrListIterator it(l); + + for (; it.current(); ++it, i++) { + + QCString str = *it; + + split = str.find("="); + if (split < 0 ) { + vDebug("No '=' in paramter."); + continue; + } + + QCString paraName = str.left(split); + QCString paraValue = str.mid(split + 1); + + QStrList paraValues; + RTokenise(paraValue, ",", paraValues); + + QStrListIterator it2( paraValues ); + + for(; it2.current(); ++it2) { + + Param *p = new Param; + p->setName( paraName ); + p->setValue( *it2 ); + + paramList_.append(p); + } + } + + // Create a new value of the correct type. + + valueType_ = EntityTypeToValueType(entityType_); + +// kdDebug(5710) << "valueType: " << valueType_ << endl; + + switch (valueType_) { + + case ValueSound: value_ = new SoundValue; break; + case ValueAgent: value_ = new AgentValue; break; + case ValueAddress: value_ = new AdrValue; break; + case ValueTel: value_ = new TelValue; break; + case ValueTextBin: value_ = new TextBinValue; break; + case ValueOrg: value_ = new OrgValue; break; + case ValueN: value_ = new NValue; break; + case ValueUTC: value_ = new UTCValue; break; + case ValueURI: value_ = new URIValue; break; + case ValueClass: value_ = new ClassValue; break; + case ValueFloat: value_ = new FloatValue; break; + case ValueImage: value_ = new ImageValue; break; + case ValueDate: value_ = new DateValue; break; + case ValueTextList: value_ = new TextListValue; break; + case ValueGeo: value_ = new GeoValue; break; + case ValueText: + case ValueUnknown: + default: value_ = new TextValue; break; + } + + *value_ = valuePart; +} + + void +ContentLine::_assemble() +{ + vDebug("Assemble (argl) - my name is \"" + name_ + "\""); + strRep_.truncate(0); + + QCString line; + + if (!group_.isEmpty()) + line += group_ + '.'; + + line += name_; + + vDebug("Adding parameters"); + ParamListIterator it(paramList_); + + for (; it.current(); ++it) + line += ";" + it.current()->asString(); + + vDebug("Adding value"); + if (value_ != 0) + line += ":" + value_->asString(); + else + vDebug("No value"); + + // Quote newlines + line = line.replace( QRegExp( "\n" ), "\\n" ); + + // Fold lines longer than 72 chars + const int maxLen = 72; + uint cursor = 0; + while( line.length() > ( cursor + 1 ) * maxLen ) { + strRep_ += line.mid( cursor * maxLen, maxLen ); + strRep_ += "\r\n "; + ++cursor; + } + strRep_ += line.mid( cursor * maxLen ); +} + + void +ContentLine::clear() +{ + group_.truncate(0); + name_.truncate(0); + paramList_.clear(); + delete value_; + value_ = 0; +} diff --git a/kabc/vcard/DateParam.cpp b/kabc/vcard/DateParam.cpp new file mode 100644 index 0000000..52af089 --- a/dev/null +++ b/kabc/vcard/DateParam.cpp @@ -0,0 +1,82 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardDateParam.h> + +#include <VCardParam.h> + +using namespace VCARD; + +DateParam::DateParam() + : Param() +{ +} + +DateParam::DateParam(const DateParam & x) + : Param(x) +{ +} + +DateParam::DateParam(const QCString & s) + : Param(s) +{ +} + + DateParam & +DateParam::operator = (DateParam & x) +{ + if (*this == x) return *this; + + Param::operator = (x); + return *this; +} + + DateParam & +DateParam::operator = (const QCString & s) +{ + Param::operator = (s); + return *this; +} + + bool +DateParam::operator == (DateParam & x) +{ + x.parse(); + + return false; +} + +DateParam::~DateParam() +{ +} + + void +DateParam::_parse() +{ +} + + void +DateParam::_assemble() +{ +} + diff --git a/kabc/vcard/DateValue.cpp b/kabc/vcard/DateValue.cpp new file mode 100644 index 0000000..c5c5c85 --- a/dev/null +++ b/kabc/vcard/DateValue.cpp @@ -0,0 +1,434 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <qregexp.h> + +#include <kdebug.h> + +#include <VCardDefines.h> +#include <VCardDateValue.h> +#include <VCardValue.h> + +using namespace VCARD; + +DateValue::DateValue() + : Value() +{ + vDebug("DateValue::DateValue()"); +} + +DateValue::DateValue( + unsigned int year, + unsigned int month, + unsigned int day, + unsigned int hour, + unsigned int minute, + unsigned int second, + double secFrac, + bool zonePositive, + unsigned int zoneHour, + unsigned int zoneMinute) + : Value (), + year_ (year), + month_ (month), + day_ (day), + hour_ (hour), + minute_ (minute), + second_ (second), + zoneHour_ (zoneHour), + zoneMinute_ (zoneMinute), + secFrac_ (secFrac), + zonePositive_ (zonePositive), + hasTime_(true) +{ + parsed_ = true; + assembled_ = false; +} + +DateValue::DateValue(const QDate & d) + : Value (), + year_ (d.year()), + month_ (d.month()), + day_ (d.day()), + hasTime_(false) +{ + parsed_ = true; + assembled_ = false; +} + +DateValue::DateValue(const QDateTime & d) + : Value (), + year_ (d.date().year()), + month_ (d.date().month()), + day_ (d.date().day()), + hour_ (d.time().hour()), + minute_ (d.time().minute()), + second_ (d.time().second()), + hasTime_(true) +{ + parsed_ = true; + assembled_ = false; +} + +DateValue::DateValue(const DateValue & x) + : Value(x) +{ + year_ = x.year_; + month_ = x.month_; + day_ = x.day_; + hour_ = x.hour_; + minute_ = x.minute_; + second_ = x.second_; + zoneHour_ = x.zoneHour_; + zoneMinute_ = x.zoneMinute_; + secFrac_ = x.secFrac_; + hasTime_ = x.hasTime_; +} + +DateValue::DateValue(const QCString & s) + : Value(s) +{ +} + + DateValue & +DateValue::operator = (DateValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + DateValue & +DateValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +DateValue::operator == (DateValue & x) +{ + x.parse(); + return false; +} + +DateValue::~DateValue() +{ +} + + DateValue * +DateValue::clone() +{ + return new DateValue( *this ); +} + + void +DateValue::_parse() +{ + vDebug("DateValue::_parse()"); + + // date = date-full-year ["-"] date-month ["-"] date-mday + // time = time-hour [":"] time-minute [":"] time-second [":"] + // [time-secfrac] [time-zone] + + int timeSep = strRep_.find('T'); + + QCString dateStr; + QCString timeStr; + + if (timeSep == -1) { + + dateStr = strRep_; + vDebug("Has date string \"" + dateStr + "\""); + + } else { + + dateStr = strRep_.left(timeSep); + vDebug("Has date string \"" + dateStr + "\""); + + timeStr = strRep_.mid(timeSep + 1); + vDebug("Has time string \"" + timeStr + "\""); + } + + /////////////////////////////////////////////////////////////// DATE + + dateStr.replace(QRegExp("-"), ""); + + kdDebug(5710) << "dateStr: " << dateStr << endl; + + year_ = dateStr.left(4).toInt(); + month_ = dateStr.mid(4, 2).toInt(); + day_ = dateStr.right(2).toInt(); + + if (timeSep == -1) { + hasTime_ = false; + return; // No time, done. + } + else + hasTime_ = true; + + /////////////////////////////////////////////////////////////// TIME + + /////////////////////////////////////////////////////////////// ZONE + + int zoneSep = timeStr.find('Z'); + + if (zoneSep != -1 && timeStr.length() - zoneSep > 3) { + + QCString zoneStr(timeStr.mid(zoneSep + 1)); + vDebug("zoneStr == " + zoneStr); + + zonePositive_ = (zoneStr[0] == '+'); + zoneHour_ = zoneStr.mid(1, 2).toInt(); + zoneMinute_ = zoneStr.right(2).toInt(); + + timeStr.remove(zoneSep, timeStr.length() - zoneSep); + } + + //////////////////////////////////////////////////// SECOND FRACTION + + int secFracSep = timeStr.findRev(','); + + if (secFracSep != -1 && zoneSep != -1) { // zoneSep checked to avoid errors. + QCString quirkafleeg = "0." + timeStr.mid(secFracSep + 1, zoneSep); + secFrac_ = quirkafleeg.toDouble(); + } + + /////////////////////////////////////////////////////////////// HMS + + timeStr.replace(QRegExp(":"), ""); + + hour_ = timeStr.left(2).toInt(); + minute_ = timeStr.mid(2, 2).toInt(); + second_ = timeStr.mid(4, 2).toInt(); +} + + void +DateValue::_assemble() +{ + vDebug("DateValue::_assemble"); + + QCString year; + QCString month; + QCString day; + + year.setNum( year_ ); + month.setNum( month_ ); + day.setNum( day_ ); + + if ( month.length() < 2 ) month.prepend( "0" ); + if ( day.length() < 2 ) day.prepend( "0" ); + + strRep_ = year + '-' + month + '-' + day; + + if ( hasTime_ ) { + QCString hour; + QCString minute; + QCString second; + + hour.setNum( hour_ ); + minute.setNum( minute_ ); + second.setNum( second_ ); + + if ( hour.length() < 2 ) hour.prepend( "0" ); + if ( minute.length() < 2 ) minute.prepend( "0" ); + if ( second.length() < 2 ) second.prepend( "0" ); + + strRep_ += 'T' + hour + ':' + minute + ':' + second + 'Z'; + } +} + + unsigned int +DateValue::year() +{ + parse(); + return year_; +} + + unsigned int +DateValue::month() +{ + parse(); + return month_; +} + + unsigned int +DateValue::day() +{ + parse(); + return day_; +} + unsigned int +DateValue::hour() +{ + parse(); + return hour_; +} + + unsigned int +DateValue::minute() +{ + parse(); + return minute_; +} + + unsigned int +DateValue::second() +{ + parse(); + return second_; +} + + double +DateValue::secondFraction() +{ + parse(); + return secFrac_; +} + + bool +DateValue::zonePositive() +{ + parse(); + return zonePositive_; +} + + unsigned int +DateValue::zoneHour() +{ + parse(); + return zoneHour_; +} + + unsigned int +DateValue::zoneMinute() +{ + parse(); + return zoneMinute_; +} + + void +DateValue::setYear(unsigned int i) +{ + year_ = i; + assembled_ = false; +} + + void +DateValue::setMonth(unsigned int i) +{ + month_ = i; + assembled_ = false; +} + + void +DateValue::setDay(unsigned int i) +{ + day_ = i; + assembled_ = false; +} + + void +DateValue::setHour(unsigned int i) +{ + hour_ = i; + assembled_ = false; +} + + void +DateValue::setMinute(unsigned int i) +{ + minute_ = i; + assembled_ = false; +} + + void +DateValue::setSecond(unsigned int i) +{ + second_ = i; + assembled_ = false; +} + + void +DateValue::setSecondFraction(double d) +{ + secFrac_ = d; + assembled_ = false; +} + + void +DateValue::setZonePositive(bool b) +{ + zonePositive_ = b; + assembled_ = false; +} + + void +DateValue::setZoneHour(unsigned int i) +{ + zoneHour_ = i; + assembled_ = false; +} + + void +DateValue::setZoneMinute(unsigned int i) +{ + zoneMinute_ = i; + assembled_ = false; +} + + QDate +DateValue::qdate() +{ + parse(); + QDate d(year_, month_, day_); + return d; +} + + QTime +DateValue::qtime() +{ + parse(); + QTime t(hour_, minute_, second_); +// t.setMs(1 / secFrac_); + return t; +} + + QDateTime +DateValue::qdt() +{ + parse(); + QDateTime dt; + dt.setDate(qdate()); + dt.setTime(qtime()); + return dt; +} + + bool +DateValue::hasTime() +{ + parse(); + return hasTime_; +} + diff --git a/kabc/vcard/EmailParam.cpp b/kabc/vcard/EmailParam.cpp new file mode 100644 index 0000000..8c87477 --- a/dev/null +++ b/kabc/vcard/EmailParam.cpp @@ -0,0 +1,116 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardEmailParam.h> +#include <VCardParam.h> +#include <VCardDefines.h> + +using namespace VCARD; + +EmailParam::EmailParam() + : Param() +{ + vDebug("ctor"); +} + +EmailParam::EmailParam(const EmailParam & x) + : Param(x), + emailType_ (x.emailType_), + pref_ (x.pref_) +{ +} + +EmailParam::EmailParam(const QCString & s) + : Param(s) +{ +} + + EmailParam & +EmailParam::operator = (EmailParam & x) +{ + if (*this == x) return *this; + + emailType_ = x.emailType(); + pref_ = x.pref_; + + Param::operator = (x); + return *this; +} + + EmailParam & +EmailParam::operator = (const QCString & s) +{ + Param::operator = (s); + return *this; +} + + bool +EmailParam::operator == (EmailParam & x) +{ + parse(); + + if (pref_) + return (x.pref_ && x.emailType() == emailType_); + + return !x.pref(); +} + +EmailParam::~EmailParam() +{ +} + + void +EmailParam::_parse() +{ +#if 0 + Param::parseToList(); + + SubParamListIterator it(subParamList_); + + pref_ = true; + emailType_ = ""; + + for (; it.current(); ++it) { + + if (qstricmp(it.current()->name(), "TYPE") == 0) { + emailType_ = it.current()->value(); + continue; + } + + if (qstricmp(it.current()->name(), "PREF") == 0) { + pref_ = true; + } + } +#endif +} + + void +EmailParam::_assemble() +{ + strRep_ = "TYPE="; + strRep_ += emailType_; + + if (pref_) + strRep_ += ",PREF"; +} + diff --git a/kabc/vcard/Entity.cpp b/kabc/vcard/Entity.cpp new file mode 100644 index 0000000..b7d09e0 --- a/dev/null +++ b/kabc/vcard/Entity.cpp @@ -0,0 +1,134 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardEntity.h> + +using namespace VCARD; + +Entity::Entity() + : parsed_ (false), + assembled_ (true) +{ + // empty +} + +Entity::Entity(const Entity & e) + : strRep_ (e.strRep_), + parsed_ (e.parsed_), + assembled_ (e.assembled_) +{ + // empty +} + +Entity::Entity(const QCString & s) + : strRep_ (s), + parsed_ (false), + assembled_ (true) +{ + // empty +} + + Entity & +Entity::operator = (const Entity & e) +{ + if (this == &e) return *this; + + strRep_ = e.strRep_; + parsed_ = e.parsed_; + assembled_ = e.assembled_; + + return *this; +} + + Entity & +Entity::operator = (const QCString & s) +{ + strRep_ = s; + parsed_ = false; + assembled_ = true; + + return *this; +} + + bool +Entity::operator == (Entity & e) +{ + return asString() == e.asString(); +} + + bool +Entity::operator != (Entity & e) +{ + return !(*this == e); +} + + bool +Entity::operator == (const QCString & s) +{ + return asString() == s; +} + + bool +Entity::operator != (const QCString & s) +{ + return !(*this == s); +} + +Entity::~Entity() +{ + // empty +} + + QCString +Entity::asString() +{ +// vDebug("Entity::asString()"); + assemble(); + + return strRep_; +} + + void +Entity::parse() +{ +// vDebug( "Entity::parse()" ); + + if (!parsed_) _parse(); + + parsed_ = true; + assembled_ = false; +} + + void +Entity::assemble() +{ +// vDebug( "Entity::assemble()" ); + + if (assembled_) return; + + parse(); + _assemble(); + + assembled_ = true; +} + diff --git a/kabc/vcard/Enum.cpp b/kabc/vcard/Enum.cpp new file mode 100644 index 0000000..cc48b5a --- a/dev/null +++ b/kabc/vcard/Enum.cpp @@ -0,0 +1,482 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <qcstring.h> +#include <ctype.h> + +#include <VCardEnum.h> + +using namespace VCARD; + +// There are 31 possible types, not including extensions. + const QCString +VCARD::paramNames [] = +{ + "NAME", + "PROFILE", + "SOURCE", + "FN", + "N", + "NICKNAME", + "PHOTO", + "BDAY", + "ADR", + "LABEL", + "TEL", + "EMAIL", + "MAILER", + "TZ", + "GEO", + "TITLE", + "ROLE", + "LOGO", + "AGENT", + "ORG", + "CATEGORIES", + "NOTE", + "PRODID", + "REV", + "SORT-STRING", + "SOUND", + "UID", + "URL", + "VERSION", + "CLASS", + "KEY" +}; + + const ParamType +VCARD::paramTypesTable[] = { + ParamNone, // NAME + ParamNone, // PROFILE + ParamSource, // SOURCE + ParamText, // FN + ParamText, // N + ParamText, // NICKNAME + ParamImage, // PHOTO (inline/refer) + ParamDate, // BDAY ("VALUE = "date-time/date) + ParamAddrText, // ADR (adr-param/text-param) + ParamAddrText, // LABEL (adr-param/text-param) + ParamTel, // TEL + ParamEmail, // EMAIL + ParamText, // MAILER + ParamNone, // TZ + ParamNone, // GEO + ParamText, // TITLE + ParamText, // ROLE + ParamImage, // LOGO + ParamAgent, // AGENT + ParamText, // ORG + ParamText, // CATEGORIES + ParamText, // NOTE + ParamNone, // PRODID + ParamDate, // REV + ParamText, // SORT-STRING + ParamSound, // SOUND + ParamNone, // UID + ParamNone, // URL + ParamNone, // VERSION + ParamNone, // CLASS + ParamTextBin, // KEY + ParamTextNS // X +}; + + ParamType +VCARD::EntityTypeToParamType(EntityType e) +{ + ParamType t(ParamUnknown); + + switch (e) { + + //---------------------------------------------------------------// + case EntityAgent: t = ParamAgent; break; + //---------------------------------------------------------------// + case EntitySound: t = ParamSound; break; + //---------------------------------------------------------------// + case EntitySource: t = ParamSource; break; + //---------------------------------------------------------------// + case EntityTelephone: t = ParamTel; break; + //---------------------------------------------------------------// + case EntityEmail: t = ParamEmail; break; + //---------------------------------------------------------------// + case EntityKey: t = ParamTextBin; break; + //---------------------------------------------------------------// + case EntityExtension: t = ParamTextNS; break; + //---------------------------------------------------------------// + case EntityAddress: + case EntityLabel: t = ParamAddrText; break; + //---------------------------------------------------------------// + case EntityBirthday: + case EntityRevision: t = ParamDate; break; + //---------------------------------------------------------------// + case EntityPhoto: + case EntityLogo: t = ParamImage; break; + //---------------------------------------------------------------// + case EntityOrganisation: + case EntityTitle: + case EntityRole: + case EntityFullName: + case EntityMailer: + case EntityN: + case EntitySortString: + case EntityNickname: + case EntityCategories: + case EntityNote: t = ParamText; break; + //---------------------------------------------------------------// + case EntityProductID: + case EntityTimeZone: + case EntityUID: + case EntityURL: + case EntityClass: + case EntityGeo: + case EntityName: + case EntityVersion: + case EntityProfile: + default: t = ParamNone; break; + //---------------------------------------------------------------// + + } + + return t; +} + + ValueType +VCARD::EntityTypeToValueType(EntityType e) +{ + ValueType t(ValueUnknown); + + switch (e) { + + //---------------------------------------------------------------// + case EntitySound: t = ValueSound; break; + //---------------------------------------------------------------// + case EntityAgent: t = ValueAgent; break; + //---------------------------------------------------------------// + case EntityAddress: t = ValueAddress; break; + //---------------------------------------------------------------// + case EntityTelephone: t = ValueTel; break; + //---------------------------------------------------------------// + case EntityKey: t = ValueTextBin; break; + //---------------------------------------------------------------// + case EntityOrganisation: t = ValueOrg; break; + //---------------------------------------------------------------// + case EntityN: t = ValueN; break; + //---------------------------------------------------------------// + case EntityTimeZone: t = ValueUTC; break; + //---------------------------------------------------------------// + case EntityClass: t = ValueClass; break; + //---------------------------------------------------------------// + case EntityGeo: t = ValueGeo; break; + //---------------------------------------------------------------// + case EntitySource: + case EntityURL: t = ValueURI; break; + //---------------------------------------------------------------// + case EntityPhoto: + case EntityLogo: t = ValueImage; break; + //---------------------------------------------------------------// + case EntityBirthday: + case EntityRevision: t = ValueDate; break; + //---------------------------------------------------------------// + case EntityCategories: + case EntityNickname: t = ValueTextList; break; + //---------------------------------------------------------------// + case EntityLabel: + case EntityExtension: + case EntityEmail: + case EntityTitle: + case EntityRole: + case EntityFullName: + case EntityMailer: + case EntityProductID: + case EntityName: + case EntitySortString: + case EntityVersion: + case EntityProfile: + case EntityUID: + case EntityNote: + default: t = ValueText; break; + //---------------------------------------------------------------// + + } + + return t; +} + + QCString +VCARD::EntityTypeToParamName(EntityType e) +{ + if ( e > EntityUnknown ) e = EntityUnknown; + return paramNames[ int( e ) ]; +} + + EntityType +VCARD::EntityNameToEntityType(const QCString & s) +{ + if (s.isEmpty()) return EntityUnknown; + + EntityType t(EntityUnknown); + + switch (s[0]) { + + case 'A': + if (s == "ADR") + t = EntityAddress; + else if (s == "AGENT") + t = EntityAgent; + break; + + case 'B': + if (s == "BDAY") + t = EntityBirthday; + break; + + case 'C': + if (s == "CATEGORIES") + t = EntityCategories; + else if (s == "CLASS") + t = EntityClass; + break; + + case 'E': + if (s == "EMAIL") + t = EntityEmail; + break; + + case 'F': + if (s == "FN") + t = EntityFullName; + break; + + case 'G': + if (s == "GEO") + t = EntityGeo; + break; + + case 'K': + if (s == "KEY") + t = EntityKey; + break; + + case 'L': + if (s == "LABEL") + t = EntityLabel; + else if (s == "LOGO") + t = EntityLogo; + break; + + case 'M': + if (s == "MAILER") + t = EntityMailer; + break; + + case 'N': + if (s == "N") + t = EntityN; + else if (s == "NAME") + t = EntityName; + else if (s == "NICKNAME") + t = EntityNickname; + else if (s == "NOTE") + t = EntityNote; + break; + + case 'O': + if (s == "ORG") + t = EntityOrganisation; + break; + + case 'P': + if (s == "PHOTO") + t = EntityPhoto; + else if (s == "PRODID") + t = EntityProductID; + else if (s == "PROFILE") + t = EntityProfile; + break; + + case 'R': + if (s == "REV") + t = EntityRevision; + else if (s == "ROLE") + t = EntityRole; + break; + + case 'S': + if (s == "SORT-STRING") + t = EntitySortString; + else if (s == "SOUND") + t = EntitySound; + else if (s == "SOURCE") + t = EntitySource; + break; + + case 'T': + if (s == "TEL") + t = EntityTelephone; + else if (s == "TITLE") + t = EntityTitle; + else if (s == "TZ") + t = EntityTimeZone; + break; + + case 'U': + if (s == "UID") + t = EntityUID; + else if (s == "URL") + t = EntityURL; + case 'V': + if (s == "VERSION") + t = EntityVersion; + break; + + case 'X': + if (s.left(2) == "X-") + t = EntityExtension; + break; + + default: + + t = EntityUnknown; + } + + return t; +} + +// The copyright notice below refers to the base64 codec functions used below, +// which are modified from the original sources. + +/* + * Original version Copyright 1988 by The Leland Stanford Junior University + * Copyright 1998 by the University of Washington + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notices appear in all copies and that both the + * above copyright notices and this permission notice appear in supporting + * documentation, and that the name of the University of Washington or The + * Leland Stanford Junior University not be used in advertising or publicity + * pertaining to distribution of the software without specific, written prior + * permission. This software is made available "as is", and + * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY + * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, + * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF + * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +static char B64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +// the mime base64 disctionary used for decoding +static signed char b64dec[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 30 + -1, -1, -1,-19, -1, -1, -1,-16, -4, -4, // 40 -19 == '+' -16 == '/' + -4, -4, -4, -4, -4, -4, -4, -4, -1, -1, // 50 -4 == '0' + -1, 0, -1, -1, -1, 65, 65, 65, 65, 65, // 60 0 == '=' 65 == 'A' + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, // 70 + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, // 80 + 65, -1, -1, -1, -1, -1, -1, 71, 71, 71, // 90 71 == 'a' + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, // 100 + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, // 110 + 71, 71, 71, -1, -1, -1, -1, -1, -1, -1, // 120 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 130 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 140 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 150 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 170 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 180 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 190 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 200 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 210 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 220 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 230 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 240 + -1, -1, -1, -1, -1, -1, -1 // 250 +}; + + char * +VCARD::decodeBase64(const char * s, unsigned long srcl, unsigned long & len) +{ + register unsigned char c; + register unsigned long e(0); + len = 0; + unsigned const char * src = (unsigned const char *)s; + char * ret = new char[srcl + (srcl / 4 + 1)]; + register char *d = ret; + while (srcl--) { // Critical loop + c = *src++; + int dec = b64dec[c]; + if (dec == -1) continue; + if (c == '=') { + switch (e++) { + case 3: e = 0; break; + case 2: if (*src == '=') break; + default: delete [] ret; ret = 0; return 0; break; + } + continue; + } + c -= dec; + if (e == 0) { *d = c << 2; ++e; continue; } + switch (e) { + case 1: *d |= c >> 4; *++d = c << 4; break; + case 2: *d |= c >> 2; *++d = c << 6; break; + case 3: *d++ |= c; e = 0; continue; break; + } + ++e; + } + len = d - (char *)ret; + return ret; +} + + + char * +VCARD::encodeBase64(const char * src, unsigned long srcl, unsigned long & destl) +{ + register const unsigned char *s = (unsigned char *)src; + register unsigned long i = ((srcl + 2) / 3) * 4; + destl = i += 2 * ((i / 60) + 1); + i = 0; + char * ret = new char[destl]; + register unsigned char *d((unsigned char *)ret); + while (srcl != 0) { // Critical loop + *d++ = B64[s[0] >> 2]; + *d++ = B64[((s[0] << 4) + (--srcl == 0 ? 0 : s[1] >> 4)) & 0x3f]; + *d++ = srcl == 0 ? '=' : + B64[((s[1] << 2) + (--srcl == 0 ? 0 : s[2] >> 6)) & 0x3f]; + *d++ = srcl == 0 ? '=' : B64[s[2] & 0x3f]; + if (srcl != 0) srcl--; + if (++i == 15) { i = 0; *d++ = '\r'; *d++ = '\n'; } + s += 3; + } + *d = '\r'; *++d = '\n'; *++d = '\0'; + return ret; +} + diff --git a/kabc/vcard/FloatValue.cpp b/kabc/vcard/FloatValue.cpp new file mode 100644 index 0000000..15bb664 --- a/dev/null +++ b/kabc/vcard/FloatValue.cpp @@ -0,0 +1,120 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardFloatValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +FloatValue::FloatValue() + : Value() +{ +} + +FloatValue::FloatValue(float f) + : Value (), + value_ (f) +{ + parsed_ = true; +} + +FloatValue::FloatValue(const FloatValue & x) + : Value(x) +{ + value_ = x.value_; +} + +FloatValue::FloatValue(const QCString & s) + : Value(s) +{ +} + + FloatValue & +FloatValue::operator = (FloatValue & x) +{ + if (*this == x) return *this; + + x.parse(); + value_ = x.value_; + + Value::operator = (x); + return *this; +} + + FloatValue & +FloatValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +FloatValue::operator == (FloatValue & x) +{ + x.parse(); + return (value_ == x.value_); +} + +FloatValue::~FloatValue() +{ +} + + void +FloatValue::_parse() +{ + bool negative(false); + + if (strRep_[0] == '-' || strRep_[1] == '+') { + + if (strRep_[0] == '-') + negative = true; + + strRep_.remove(0, 1); + } + + value_ = strRep_.toFloat(); + if (negative) + value_ = -value_; +} + + void +FloatValue::_assemble() +{ + strRep_ = QCString().setNum(value_); +} + + float +FloatValue::value() +{ + parse(); + return value_; +} + + void +FloatValue::setValue(float f) +{ + parsed_ = true; + value_ = f; +} + diff --git a/kabc/vcard/GeoValue.cpp b/kabc/vcard/GeoValue.cpp new file mode 100644 index 0000000..e02b402 --- a/dev/null +++ b/kabc/vcard/GeoValue.cpp @@ -0,0 +1,100 @@ +/* + This file is part of libvcard. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <VCardGeoValue.h> + +#include <VCardValue.h> + +#include <kdebug.h> + +using namespace VCARD; + +GeoValue::GeoValue() + : Value() +{ +} + +GeoValue::GeoValue(const GeoValue & x) + : Value(x), latitude_(x.latitude_), longitude_(x.longitude_) +{ +} + +GeoValue::GeoValue(const QCString & s) + : Value(s) +{ +} + + GeoValue & +GeoValue::operator = (GeoValue & x) +{ + if (*this == x) return *this; + + latitude_ = x.latitude_; + longitude_ = x.longitude_; + + Value::operator = (x); + return *this; +} + + GeoValue & +GeoValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +GeoValue::operator == (GeoValue & x) +{ + x.parse(); + + if ( latitude_ != x.latitude_ ) return false; + if ( longitude_ != x.longitude_ ) return false; + + return true; +} + +GeoValue::~GeoValue() +{ +} + + GeoValue * +GeoValue::clone() +{ + return new GeoValue( *this ); +} + + void +GeoValue::_parse() +{ + int semiColon = strRep_.find( ";" ); + + if ( semiColon == -1 ) // invalid + return; + + latitude_ = strRep_.left( semiColon ).toFloat(); + longitude_ = strRep_.mid( semiColon + 1, strRep_.length() - semiColon ).toFloat(); +} + + void +GeoValue::_assemble() +{ + strRep_.sprintf( "%.6f;%.6f", latitude_, longitude_ ); +} diff --git a/kabc/vcard/ImageParam.cpp b/kabc/vcard/ImageParam.cpp new file mode 100644 index 0000000..c9cf6fd --- a/dev/null +++ b/kabc/vcard/ImageParam.cpp @@ -0,0 +1,81 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardImageParam.h> + +#include <VCardParam.h> + +using namespace VCARD; + +ImageParam::ImageParam() + : Param() +{ +} + +ImageParam::ImageParam(const ImageParam & x) + : Param(x) +{ +} + +ImageParam::ImageParam(const QCString & s) + : Param(s) +{ +} + + ImageParam & +ImageParam::operator = (ImageParam & x) +{ + if (*this == x) return *this; + + Param::operator = (x); + return *this; +} + + ImageParam & +ImageParam::operator = (const QCString & s) +{ + Param::operator = (s); + return *this; +} + + bool +ImageParam::operator == (ImageParam & x) +{ + x.parse(); + return false; +} + +ImageParam::~ImageParam() +{ +} + + void +ImageParam::_parse() +{ +} + + void +ImageParam::_assemble() +{ +} + diff --git a/kabc/vcard/ImageValue.cpp b/kabc/vcard/ImageValue.cpp new file mode 100644 index 0000000..4630fac --- a/dev/null +++ b/kabc/vcard/ImageValue.cpp @@ -0,0 +1,81 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardImageValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +ImageValue::ImageValue() + : Value() +{ +} + +ImageValue::ImageValue(const ImageValue & x) + : Value(x) +{ +} + +ImageValue::ImageValue(const QCString & s) + : Value(s) +{ +} + + ImageValue & +ImageValue::operator = (ImageValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + ImageValue & +ImageValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +ImageValue::operator == (ImageValue & x) +{ + x.parse(); + return false; +} + +ImageValue::~ImageValue() +{ +} + + void +ImageValue::_parse() +{ +} + + void +ImageValue::_assemble() +{ +} + diff --git a/kabc/vcard/ImgValue.cpp b/kabc/vcard/ImgValue.cpp new file mode 100644 index 0000000..7b961f8 --- a/dev/null +++ b/kabc/vcard/ImgValue.cpp @@ -0,0 +1,81 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardImgValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +ImgValue::ImgValue() + : Value() +{ +} + +ImgValue::ImgValue(const ImgValue & x) + : Value(x) +{ +} + +ImgValue::ImgValue(const QCString & s) + : Value(s) +{ +} + + ImgValue & +ImgValue::operator = (ImgValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + ImgValue & +ImgValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +ImgValue::operator == (ImgValue & x) +{ + x.parse(); + return false; +} + +ImgValue::~ImgValue() +{ +} + + void +ImgValue::_parse() +{ +} + + void +ImgValue::_assemble() +{ +} + diff --git a/kabc/vcard/LangValue.cpp b/kabc/vcard/LangValue.cpp new file mode 100644 index 0000000..edf1804 --- a/dev/null +++ b/kabc/vcard/LangValue.cpp @@ -0,0 +1,127 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardRToken.h> + +#include <VCardLangValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +LangValue::LangValue() + : Value() +{ +} + +LangValue::LangValue(const LangValue & x) + : Value(x) +{ +} + +LangValue::LangValue(const QCString & s) + : Value(s) +{ +} + + LangValue & +LangValue::operator = (LangValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + LangValue & +LangValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +LangValue::operator == (LangValue & x) +{ + x.parse(); + return false; +} + +LangValue::~LangValue() +{ +} + + void +LangValue::_parse() +{ + QStrList l; + RTokenise(strRep_, "-", l); + + if (l.count() == 0) return; + + primary_ = l.at(0); + + l.remove(0u); + + subtags_ = l; +} + + void +LangValue::_assemble() +{ + strRep_ = primary_; + + QStrListIterator it(subtags_); + + for (; it.current(); ++it) + strRep_ += QCString('-') + it.current(); +} + + QCString +LangValue::primary() +{ + parse(); + return primary_; +} + + QStrList +LangValue::subtags() +{ + parse(); + return subtags_; +} + + void +LangValue::setPrimary(const QCString & s) +{ + parse(); + primary_ = s; +} + + void +LangValue::setSubTags(const QStrList & l) +{ + parse(); + subtags_ = l; +} + diff --git a/kabc/vcard/NValue.cpp b/kabc/vcard/NValue.cpp new file mode 100644 index 0000000..cdec621 --- a/dev/null +++ b/kabc/vcard/NValue.cpp @@ -0,0 +1,128 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <qstrlist.h> + +#include <VCardRToken.h> +#include <VCardNValue.h> +#include <VCardValue.h> +#include <VCardDefines.h> + +using namespace VCARD; + +NValue::NValue() + : Value() +{ + vDebug("ctor"); +} + +NValue::NValue(const NValue & x) + : Value(x), + family_ (x.family_), + given_ (x.given_), + middle_ (x.middle_), + prefix_ (x.prefix_), + suffix_ (x.suffix_) +{ +} + +NValue::NValue(const QCString & s) + : Value(s) +{ + vDebug("ctor"); +} + + NValue & +NValue::operator = (NValue & x) +{ + if (*this == x) return *this; + + family_ = x.family_; + given_ = x.given_; + middle_ = x.middle_; + prefix_ = x.prefix_; + suffix_ = x.suffix_; + + Value::operator = (x); + return *this; +} + + NValue & +NValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +NValue::operator == (NValue & x) +{ + x.parse(); + + return ( + family_ == x.family_ && + given_ == x.given_ && + middle_ == x.middle_ && + prefix_ == x.prefix_ && + suffix_ == x.suffix_); +} + +NValue::~NValue() +{ +} + + NValue * +NValue::clone() +{ + return new NValue( *this ); +} + + void +NValue::_parse() +{ + QStrList l; + RTokenise(strRep_, ";", l); + + for (unsigned int i = 0; i < l.count(); i++) { + + switch (i) { + case 0: family_ = l.at(0); break; + case 1: given_ = l.at(1); break; + case 2: middle_ = l.at(2); break; + case 3: prefix_ = l.at(3); break; + case 4: suffix_ = l.at(4); break; + default: break; + } + } +} + + void +NValue::_assemble() +{ + strRep_ = family_; + strRep_ += ";" + given_; + strRep_ += ";" + middle_; + strRep_ += ";" + prefix_; + strRep_ += ";" + suffix_; +} + diff --git a/kabc/vcard/OrgValue.cpp b/kabc/vcard/OrgValue.cpp new file mode 100644 index 0000000..c3134c8 --- a/dev/null +++ b/kabc/vcard/OrgValue.cpp @@ -0,0 +1,107 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardRToken.h> + +#include <VCardOrgValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +OrgValue::OrgValue() + : Value() +{ +} + +OrgValue::OrgValue(const OrgValue & x) + : Value(x) +{ +} + +OrgValue::OrgValue(const QCString & s) + : Value(s) +{ +} + + OrgValue & +OrgValue::operator = (OrgValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + OrgValue & +OrgValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +OrgValue::operator == (OrgValue & x) +{ + x.parse(); + return false; +} + +OrgValue::~OrgValue() +{ +} + + void +OrgValue::_parse() +{ + RTokenise(strRep_, ";", valueList_); +} + + void +OrgValue::_assemble() +{ + bool first(true); + + QStrListIterator it(valueList_); + + for (; it.current(); ++it) { + if (!first) strRep_ += ';'; + strRep_ += it.current(); + first = false; + } +} + + unsigned int +OrgValue::numValues() +{ + parse(); + return valueList_.count(); +} + + QCString +OrgValue::value(unsigned int i) +{ + parse(); + return valueList_.at(i); +} + diff --git a/kabc/vcard/Param.cpp b/kabc/vcard/Param.cpp new file mode 100644 index 0000000..c513613 --- a/dev/null +++ b/kabc/vcard/Param.cpp @@ -0,0 +1,129 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardParam.h> + +#include <VCardEntity.h> + +#include <VCardRToken.h> + +using namespace VCARD; + +Param::Param() + : Entity(), + name_(""), + value_("") +{ +} + +Param::Param(const Param & x) + : Entity(x), + name_(x.name_), + value_(x.value_) +{ +} + +Param::Param(const QCString & s) + : Entity(s), + name_(""), + value_("") +{ +} + + Param & +Param::operator = (Param & x) +{ + if (*this == x) return *this; + + Entity::operator = (x); + name_ = x.name_; + value_ = x.value_; + + return *this; +} + + Param & +Param::operator = (const QCString & s) +{ + Entity::operator = (s); + return *this; +} + + bool +Param::operator == (Param & x) +{ + x.parse(); + return false; +} + +Param::~Param() +{ +} + + void +Param::_parse() +{ +} + + void +Param::_assemble() +{ + strRep_ = name_ + "=" + value_; +} + +Param::Param(const QCString &name, const QCString &value) + : Entity(), + name_(name), + value_(value) +{ + parsed_ = true; + assembled_ = false; +} + + void +Param::setName(const QCString & name) +{ + name_ = name; + + assembled_ = false; +} + + void +Param::setValue(const QCString & value) +{ + value_ = value; + + assembled_ = false; +} + + QCString +Param::name() +{ + return name_; +} + + QCString +Param::value() +{ + return value_; +} diff --git a/kabc/vcard/PhoneNumberValue.cpp b/kabc/vcard/PhoneNumberValue.cpp new file mode 100644 index 0000000..17b1400 --- a/dev/null +++ b/kabc/vcard/PhoneNumberValue.cpp @@ -0,0 +1,81 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardPhoneNumberValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +PhoneNumberValue::PhoneNumberValue() + : Value() +{ +} + +PhoneNumberValue::PhoneNumberValue(const PhoneNumberValue & x) + : Value(x) +{ +} + +PhoneNumberValue::PhoneNumberValue(const QCString & s) + : Value(s) +{ +} + + PhoneNumberValue & +PhoneNumberValue::operator = (PhoneNumberValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + PhoneNumberValue & +PhoneNumberValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +PhoneNumberValue::operator == (PhoneNumberValue & x) +{ + x.parse(); + return false; +} + +PhoneNumberValue::~PhoneNumberValue() +{ +} + + void +PhoneNumberValue::_parse() +{ +} + + void +PhoneNumberValue::_assemble() +{ +} + diff --git a/kabc/vcard/README b/kabc/vcard/README new file mode 100644 index 0000000..18a9daf --- a/dev/null +++ b/kabc/vcard/README @@ -0,0 +1,15 @@ +libvcard (C) 1999 Rik Hemsley <rik@kde.org> +Written for the KDE project. + +This software is licensed under the MIT license. + +A vCard 3.0 parser based on the same principles that librmm (from Empath) uses. + +It's small and very fast due to parsing and assembly of object being lazy. + +There is a base64 codec declared in Enum.h + +Feedback welcome. + +Rik <rik@kde.org> + diff --git a/kabc/vcard/RToken.cpp b/kabc/vcard/RToken.cpp new file mode 100644 index 0000000..2a85820 --- a/dev/null +++ b/kabc/vcard/RToken.cpp @@ -0,0 +1,88 @@ +/* + + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <string.h> +#include <stddef.h> +#include <qcstring.h> +#include <qstrlist.h> + +namespace VCARD +{ + + Q_UINT32 +RTokenise(const char * str, const char * delim, QStrList & l) +{ + // FIXME no stderr ! + l.clear(); + + if (!delim || !str || strlen(delim) == 0 || strlen(str) == 0) return 0; + + char * len = (char *)(str + strlen(str)); // End of string. + + register char * rstart = new char[strlen(str) + 1]; + register char * r = rstart; + + + register const char * i = str; // Cursor. + + while (i <= len) { + + if (*i == '\\') { // Escaped chars go straight through. + *r++ = *i++; + if (i <= len) + *r++ = *i++; + continue; + } + + if (strchr(delim, *i) != 0) { + // We hit a delimiter. If we have some text, make a new token. + // This has the effect that multiple delimiters are collapsed. + // cs: We mustn't collapse multiple delimiters, otherwise we + // lose empty fields. + *r = '\0'; +// if (r != rstart) { + l.append(rstart); +// } + r = rstart; + ++i; + continue; + } + + *r++ = *i++; + } + + // Catch last token +// if (r != rstart) { + *r = '\0'; + l.append(rstart); +// } + + r = 0; + + delete [] rstart; + + return l.count(); +} + +} diff --git a/kabc/vcard/SoundValue.cpp b/kabc/vcard/SoundValue.cpp new file mode 100644 index 0000000..81040d1 --- a/dev/null +++ b/kabc/vcard/SoundValue.cpp @@ -0,0 +1,81 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardSoundValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +SoundValue::SoundValue() + : Value() +{ +} + +SoundValue::SoundValue(const SoundValue & x) + : Value(x) +{ +} + +SoundValue::SoundValue(const QCString & s) + : Value(s) +{ +} + + SoundValue & +SoundValue::operator = (SoundValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + SoundValue & +SoundValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +SoundValue::operator == (SoundValue & x) +{ + x.parse(); + return false; +} + +SoundValue::~SoundValue() +{ +} + + void +SoundValue::_parse() +{ +} + + void +SoundValue::_assemble() +{ +} + diff --git a/kabc/vcard/SourceParam.cpp b/kabc/vcard/SourceParam.cpp new file mode 100644 index 0000000..cd51cbd --- a/dev/null +++ b/kabc/vcard/SourceParam.cpp @@ -0,0 +1,112 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardSourceParam.h> + +#include <VCardParam.h> + +using namespace VCARD; + +SourceParam::SourceParam() + : Param(), + type_(SourceParam::TypeUnknown) +{ +} + +SourceParam::SourceParam(const SourceParam & x) + : Param(x), + type_ (x.type_), + par_ (x.par_), + val_ (x.val_) +{ +} + +SourceParam::SourceParam(const QCString & s) + : Param(s), + type_(SourceParam::TypeUnknown) +{ +} + + SourceParam & +SourceParam::operator = (SourceParam & x) +{ + if (*this == x) return *this; + type_ = x.type(); + par_ = x.par(); + val_ = x.val(); + + Param::operator = (x); + return *this; +} + + SourceParam & +SourceParam::operator = (const QCString & s) +{ + Param::operator = (s); + return *this; +} + + bool +SourceParam::operator == (SourceParam & x) +{ + x.parse(); + return false; +} + +SourceParam::~SourceParam() +{ +} + + void +SourceParam::_parse() +{ + int i = strRep_.find('='); + if (i == -1) // Invalid + return; + + par_ = strRep_.left(i); + val_ = strRep_.right(strRep_.length() - i - 1); + + if (qstricmp(par_, "VALUE") == 0 && qstricmp(val_, "uri") == 0) + type_ = TypeValue; + else if (qstricmp(par_, "CONTEXT") == 0 && qstricmp(val_, "word") == 0) + type_ = TypeContext; + else if (qstrnicmp(par_, "X-", 2) == 0) { + type_ = TypeX; + } + else type_ = TypeUnknown; + +} + + void +SourceParam::_assemble() +{ + if (type_ == TypeValue) + strRep_ = "VALUE=uri"; + else if (type_ == TypeContext) + strRep_ = "CONTEXT=word"; + else if (type_ == TypeX) + strRep_ = par_ + "=" + val_; + else strRep_ = ""; +} + diff --git a/kabc/vcard/TelParam.cpp b/kabc/vcard/TelParam.cpp new file mode 100644 index 0000000..9d9fe4d --- a/dev/null +++ b/kabc/vcard/TelParam.cpp @@ -0,0 +1,81 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardTelParam.h> + +#include <VCardParam.h> + +using namespace VCARD; + +TelParam::TelParam() + : Param() +{ +} + +TelParam::TelParam(const TelParam & x) + : Param(x) +{ +} + +TelParam::TelParam(const QCString & s) + : Param(s) +{ +} + + TelParam & +TelParam::operator = (TelParam & x) +{ + if (*this == x) return *this; + + Param::operator = (x); + return *this; +} + + TelParam & +TelParam::operator = (const QCString & s) +{ + Param::operator = (s); + return *this; +} + + bool +TelParam::operator == (TelParam & x) +{ + x.parse(); + return false; +} + +TelParam::~TelParam() +{ +} + + void +TelParam::_parse() +{ +} + + void +TelParam::_assemble() +{ +} + diff --git a/kabc/vcard/TelValue.cpp b/kabc/vcard/TelValue.cpp new file mode 100644 index 0000000..349f99a --- a/dev/null +++ b/kabc/vcard/TelValue.cpp @@ -0,0 +1,81 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardTelValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +TelValue::TelValue() + : Value() +{ +} + +TelValue::TelValue(const TelValue & x) + : Value(x) +{ +} + +TelValue::TelValue(const QCString & s) + : Value(s) +{ +} + + TelValue & +TelValue::operator = (TelValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + TelValue & +TelValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +TelValue::operator == (TelValue & x) +{ + x.parse(); + return false; +} + +TelValue::~TelValue() +{ +} + + void +TelValue::_parse() +{ +} + + void +TelValue::_assemble() +{ +} + diff --git a/kabc/vcard/TextBinParam.cpp b/kabc/vcard/TextBinParam.cpp new file mode 100644 index 0000000..66f2946 --- a/dev/null +++ b/kabc/vcard/TextBinParam.cpp @@ -0,0 +1,81 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardTextBinParam.h> + +#include <VCardParam.h> + +using namespace VCARD; + +TextBinParam::TextBinParam() + : Param() +{ +} + +TextBinParam::TextBinParam(const TextBinParam & x) + : Param(x) +{ +} + +TextBinParam::TextBinParam(const QCString & s) + : Param(s) +{ +} + + TextBinParam & +TextBinParam::operator = (TextBinParam & x) +{ + if (*this == x) return *this; + + Param::operator = (x); + return *this; +} + + TextBinParam & +TextBinParam::operator = (const QCString & s) +{ + Param::operator = (s); + return *this; +} + + bool +TextBinParam::operator == (TextBinParam & x) +{ + x.parse(); + return false; +} + +TextBinParam::~TextBinParam() +{ +} + + void +TextBinParam::_parse() +{ +} + + void +TextBinParam::_assemble() +{ +} + diff --git a/kabc/vcard/TextBinValue.cpp b/kabc/vcard/TextBinValue.cpp new file mode 100644 index 0000000..c584009 --- a/dev/null +++ b/kabc/vcard/TextBinValue.cpp @@ -0,0 +1,104 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <kmdcodec.h> + +#include <VCardTextBinValue.h> +#include <VCardValue.h> + +using namespace VCARD; + +TextBinValue::TextBinValue() + : Value() +{ +} + +TextBinValue::TextBinValue(const TextBinValue & x) + : Value(x) +{ + mIsBinary_ = x.mIsBinary_; + mData_ = x.mData_; + mUrl_ = x.mUrl_; +} + +TextBinValue::TextBinValue(const QCString & s) + : Value(s) +{ +} + + TextBinValue & +TextBinValue::operator = (TextBinValue & x) +{ + if (*this == x) return *this; + + mIsBinary_ = x.mIsBinary_; + mData_ = x.mData_; + mUrl_ = x.mUrl_; + + Value::operator = (x); + return *this; +} + + TextBinValue & +TextBinValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +TextBinValue::operator == (TextBinValue & x) +{ + x.parse(); + + if ( mIsBinary_ != x.mIsBinary_ ) return false; + if ( mData_ != x.mData_ ) return false; + if ( mUrl_ != x.mUrl_ ) return false; + + return true; +} + +TextBinValue::~TextBinValue() +{ +} + + TextBinValue * +TextBinValue::clone() +{ + return new TextBinValue( *this ); +} + + void +TextBinValue::_parse() +{ +} + + void +TextBinValue::_assemble() +{ + if ( mIsBinary_ ) { + strRep_ = KCodecs::base64Encode( mData_ ); + } else + strRep_ = mUrl_.utf8(); +} + diff --git a/kabc/vcard/TextListValue.cpp b/kabc/vcard/TextListValue.cpp new file mode 100644 index 0000000..c4ac1e3 --- a/dev/null +++ b/kabc/vcard/TextListValue.cpp @@ -0,0 +1,107 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardRToken.h> + +#include <VCardTextListValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +TextListValue::TextListValue() + : Value() +{ +} + +TextListValue::TextListValue(const TextListValue & x) + : Value(x) +{ +} + +TextListValue::TextListValue(const QCString & s) + : Value(s) +{ +} + + TextListValue & +TextListValue::operator = (TextListValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + TextListValue & +TextListValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +TextListValue::operator == (TextListValue & x) +{ + x.parse(); + return false; +} + +TextListValue::~TextListValue() +{ +} + + void +TextListValue::_parse() +{ + RTokenise(strRep_, ";", valueList_); +} + + void +TextListValue::_assemble() +{ + bool first(true); + + QStrListIterator it(valueList_); + + for (; it.current(); ++it) { + if (!first) strRep_ += ';'; + strRep_ += it.current(); + first = false; + } +} + + unsigned int +TextListValue::numValues() +{ + parse(); + return valueList_.count(); +} + + QCString +TextListValue::value(unsigned int i) +{ + parse(); + return valueList_.at(i); +} + diff --git a/kabc/vcard/TextParam.cpp b/kabc/vcard/TextParam.cpp new file mode 100644 index 0000000..7c68700 --- a/dev/null +++ b/kabc/vcard/TextParam.cpp @@ -0,0 +1,82 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardTextParam.h> + +#include <VCardParam.h> + +using namespace VCARD; + +TextParam::TextParam() + : Param() +{ +} + +TextParam::TextParam(const TextParam & x) + : Param(x) +{ +} + +TextParam::TextParam(const QCString & s) + : Param(s) +{ +} + + TextParam & +TextParam::operator = (TextParam & x) +{ + if (*this == x) return *this; + + Param::operator = (x); + return *this; +} + + TextParam & +TextParam::operator = (const QCString & s) +{ + Param::operator = (s); + return *this; +} + + bool +TextParam::operator == (TextParam & x) +{ + x.parse(); + + return false; +} + +TextParam::~TextParam() +{ +} + + void +TextParam::_parse() +{ +} + + void +TextParam::_assemble() +{ +} + diff --git a/kabc/vcard/TextValue.cpp b/kabc/vcard/TextValue.cpp new file mode 100644 index 0000000..09934fa --- a/dev/null +++ b/kabc/vcard/TextValue.cpp @@ -0,0 +1,86 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardTextValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +TextValue::TextValue() + : Value() +{ +} + +TextValue::TextValue(const TextValue & x) + : Value(x) +{ +} + +TextValue::TextValue(const QCString & s) + : Value(s) +{ +} + + TextValue & +TextValue::operator = (TextValue & x) +{ + if (*this == x) return *this; + + Value::operator = (x); + return *this; +} + + TextValue & +TextValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +TextValue::operator == (TextValue & x) +{ + return strRep_ = x.strRep_; +} + +TextValue::~TextValue() +{ +} + + TextValue * +TextValue::clone() +{ + return new TextValue( *this ); +} + + void +TextValue::_parse() +{ +} + + void +TextValue::_assemble() +{ +} + diff --git a/kabc/vcard/URIValue.cpp b/kabc/vcard/URIValue.cpp new file mode 100644 index 0000000..c1d1022 --- a/dev/null +++ b/kabc/vcard/URIValue.cpp @@ -0,0 +1,133 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardURIValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +URIValue::URIValue() + : Value() +{ +} + +URIValue::URIValue(const QCString & scheme, const QCString & schemeSpecificPart) + : Value(), + scheme_ (scheme), + schemeSpecificPart_ (schemeSpecificPart) +{ + parsed_ = true; +} + +URIValue::URIValue(const URIValue & x) + : Value (x), + scheme_ (x.scheme_), + schemeSpecificPart_ (x.schemeSpecificPart_) +{ +} + +URIValue::URIValue(const QCString & s) + : Value(s) +{ +} + + URIValue & +URIValue::operator = (URIValue & x) +{ + if (*this == x) return *this; + + scheme_ = x.scheme_; + schemeSpecificPart_ = x.schemeSpecificPart_; + + Value::operator = (x); + return *this; +} + + URIValue & +URIValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +URIValue::operator == (URIValue & x) +{ + x.parse(); + return ( + (scheme_ == x.scheme_) && + (schemeSpecificPart_ == x.schemeSpecificPart_)); + + return false; +} + +URIValue::~URIValue() +{ +} + + void +URIValue::_parse() +{ + int split = strRep_.find(':'); + if (split == -1) + return; + + scheme_ = strRep_.left(split); + schemeSpecificPart_ = strRep_.mid(split + 1); +} + + void +URIValue::_assemble() +{ + strRep_ = scheme_ + ':' + schemeSpecificPart_; +} + + QCString +URIValue::scheme() +{ + parse(); + return scheme_; +} + + QCString +URIValue::schemeSpecificPart() +{ + parse(); + return schemeSpecificPart_; +} + + void +URIValue::setScheme(const QCString & s) +{ + parse(); + scheme_ = s; +} + + void +URIValue::setSchemeSpecificPart(const QCString & s) +{ + parse(); + schemeSpecificPart_ = s; +} + diff --git a/kabc/vcard/UTCValue.cpp b/kabc/vcard/UTCValue.cpp new file mode 100644 index 0000000..374306c --- a/dev/null +++ b/kabc/vcard/UTCValue.cpp @@ -0,0 +1,110 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardUTCValue.h> + +#include <VCardValue.h> + +using namespace VCARD; + +UTCValue::UTCValue() + : Value() +{ +} + +UTCValue::UTCValue(const UTCValue & x) + : Value(x), positive_(x.positive_), hour_(x.hour_), minute_(x.minute_) + +{ +} + +UTCValue::UTCValue(const QCString & s) + : Value(s) +{ +} + + UTCValue & +UTCValue::operator = (UTCValue & x) +{ + if (*this == x) return *this; + + positive_ = x.positive_; + hour_ = x.hour_; + minute_ = x.minute_; + + Value::operator = (x); + return *this; +} + + UTCValue & +UTCValue::operator = (const QCString & s) +{ + Value::operator = (s); + return *this; +} + + bool +UTCValue::operator == (UTCValue & x) +{ + x.parse(); + + if (positive_ != x.positive_) return false; + if (hour_ != x.hour_) return false; + if (minute_ != x.minute_) return false; + + return true; +} + +UTCValue::~UTCValue() +{ +} + + UTCValue * +UTCValue::clone() +{ + return new UTCValue( *this ); +} + + void +UTCValue::_parse() +{ + if ( strRep_.isEmpty() ) + return; + + positive_ = ( strRep_[0] == '+' ); + + int colon = strRep_.find( ':' ); + + if ( colon == -1 ) // Not valid. + return; + + hour_ = strRep_.mid( 1, 2 ).toInt(); + minute_ = strRep_.right( 2 ).toInt(); +} + + void +UTCValue::_assemble() +{ + strRep_.sprintf( "%c%.2i:%.2i", (positive_ ? '+' : '-'), hour_, minute_ ); +} + diff --git a/kabc/vcard/VCardEntity.cpp b/kabc/vcard/VCardEntity.cpp new file mode 100644 index 0000000..0c21e2f --- a/dev/null +++ b/kabc/vcard/VCardEntity.cpp @@ -0,0 +1,119 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <qregexp.h> + +#include <VCardDefines.h> +#include <VCardVCardEntity.h> + +using namespace VCARD; + +VCardEntity::VCardEntity() + : Entity() +{ +} + +VCardEntity::VCardEntity(const VCardEntity & x) + : Entity(x) +{ +} + +VCardEntity::VCardEntity(const QCString & s) + : Entity(s) +{ +} + + VCardEntity & +VCardEntity::operator = (VCardEntity & x) +{ + if (*this == x) return *this; + + Entity::operator = (x); + return *this; +} + + VCardEntity & +VCardEntity::operator = (const QCString & s) +{ + Entity::operator = (s); + return *this; +} + + bool +VCardEntity::operator == (VCardEntity & x) +{ + x.parse(); + return false; +} + +VCardEntity::~VCardEntity() +{ +} + + void +VCardEntity::_parse() +{ + vDebug("parse"); + QCString s(strRep_); + + int i = s.find(QRegExp("BEGIN:VCARD", false)); + + while (i != -1) { + + i = s.find(QRegExp("BEGIN:VCARD", false), 11); + + QCString cardStr(s.left(i)); + + VCard * v = new VCard(cardStr); + + cardList_.append(v); + + v->parse(); + + s.remove(0, i); + } +} + + void +VCardEntity::_assemble() +{ + VCardListIterator it(cardList_); + + for (; it.current(); ++it) + strRep_ += it.current()->asString() + "\r\n"; // One CRLF for luck. +} + + VCardList & +VCardEntity::cardList() +{ + parse(); + return cardList_; +} + + void +VCardEntity::setCardList(const VCardList & l) +{ + parse(); + cardList_ = l; +} + diff --git a/kabc/vcard/VCardv.cpp b/kabc/vcard/VCardv.cpp new file mode 100644 index 0000000..8d271f4 --- a/dev/null +++ b/kabc/vcard/VCardv.cpp @@ -0,0 +1,282 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <qcstring.h> +#include <qstrlist.h> + +#include <VCardEntity.h> +#include <VCardVCard.h> +#include <VCardContentLine.h> +#include <VCardRToken.h> + +#include <VCardDefines.h> + +using namespace VCARD; + +VCard::VCard() + : Entity() +{ +} + +VCard::VCard(const VCard & x) + : Entity(x), + group_(x.group_), + contentLineList_(x.contentLineList_) +{ +} + +VCard::VCard(const QCString & s) + : Entity(s) +{ +} + + VCard & +VCard::operator = (VCard & x) +{ + if (*this == x) return *this; + + group_ = x.group(); + contentLineList_ = x.contentLineList_; + + Entity::operator = (x); + return *this; +} + + VCard & +VCard::operator = (const QCString & s) +{ + Entity::operator = (s); + return *this; +} + + bool +VCard::operator == (VCard & x) +{ + x.parse(); + return false; +} + +VCard::~VCard() +{ +} + + void +VCard::_parse() +{ + vDebug("parse() called"); + QStrList l; + + RTokenise(strRep_, "\r\n", l); + + if (l.count() < 3) { // Invalid VCARD ! + vDebug("Invalid vcard"); + return; + } + + // Get the first line + QCString beginLine = QCString(l.at(0)).stripWhiteSpace(); + + vDebug("Begin line == \"" + beginLine + "\""); + + // Remove extra blank lines + while (QCString(l.last()).isEmpty()) + l.remove(l.last()); + + // Now we know this is the last line + QCString endLine = l.last(); + + // Trash the first and last lines as we have seen them. + l.remove(0u); + l.remove(l.last()); + + /////////////////////////////////////////////////////////////// + // FIRST LINE + + int split = beginLine.find(':'); + + if (split == -1) { // invalid, no BEGIN + vDebug("No split"); + return; + } + + QCString firstPart(beginLine.left(split)); + QCString valuePart(beginLine.mid(split + 1)); + + split = firstPart.find('.'); + + if (split != -1) { + group_ = firstPart.left(split); + firstPart = firstPart.right(firstPart.length() - split - 1); + } + + if (qstrnicmp(firstPart, "BEGIN", 5) != 0) { // No BEGIN ! + vDebug("No BEGIN"); + return; + } + + if (qstrnicmp(valuePart, "VCARD", 5) != 0) { // Not a vcard ! + vDebug("No VCARD"); + return; + } + + /////////////////////////////////////////////////////////////// + // CONTENT LINES + // + vDebug("Content lines"); + + // Handle folded lines. + + QStrList refolded; + + QStrListIterator it(l); + + QCString cur; + + for (; it.current(); ++it) { + + cur = it.current(); + + ++it; + + while ( + it.current() && + it.current()[0] == ' ' && + strlen(it.current()) != 1) + { + cur += it.current() + 1; + ++it; + } + + --it; + + refolded.append(cur); + } + + QStrListIterator it2(refolded); + + for (; it2.current(); ++it2) { + + vDebug("New contentline using \"" + QCString(it2.current()) + "\""); + ContentLine * cl = new ContentLine(it2.current()); + + cl->parse(); + + contentLineList_.append(cl); + } + + /////////////////////////////////////////////////////////////// + // LAST LINE + + split = endLine.find(':'); + + if (split == -1) // invalid, no END + return; + + firstPart = endLine.left(split); + valuePart = endLine.right(firstPart.length() - split - 1); + + split = firstPart.find('.'); + + if (split != -1) { + group_ = firstPart.left(split); + firstPart = firstPart.right(firstPart.length() - split - 1); + } + + if (qstricmp(firstPart, "END") != 0) // No END ! + return; + + if (qstricmp(valuePart, "VCARD") != 0) // Not a vcard ! + return; +} + + void +VCard::_assemble() +{ + vDebug("Assembling vcard"); + strRep_ = "BEGIN:VCARD\r\n"; + strRep_ += "VERSION:3.0\r\n"; + + QPtrListIterator<ContentLine> it(contentLineList_); + + for (; it.current(); ++it) + strRep_ += it.current()->asString() + "\r\n"; + + strRep_ += "END:VCARD\r\n"; +} + + bool +VCard::has(EntityType t) +{ + parse(); + return contentLine(t) == 0 ? false : true; +} + + bool +VCard::has(const QCString & s) +{ + parse(); + return contentLine(s) == 0 ? false : true; +} + + void +VCard::add(const ContentLine & cl) +{ + parse(); + ContentLine * c = new ContentLine(cl); + contentLineList_.append(c); +} + + void +VCard::add(const QCString & s) +{ + parse(); + ContentLine * c = new ContentLine(s); + contentLineList_.append(c); +} + + ContentLine * +VCard::contentLine(EntityType t) +{ + parse(); + QPtrListIterator<ContentLine> it(contentLineList_); + + for (; it.current(); ++it) + if (it.current()->entityType() == t) + return it.current(); + + return 0; +} + + ContentLine * +VCard::contentLine(const QCString & s) +{ + parse(); + QPtrListIterator<ContentLine> it(contentLineList_); + + for (; it.current(); ++it) + if (it.current()->entityType() == EntityNameToEntityType(s)) + return it.current(); + + return 0; +} + diff --git a/kabc/vcard/Value.cpp b/kabc/vcard/Value.cpp new file mode 100644 index 0000000..1978af2 --- a/dev/null +++ b/kabc/vcard/Value.cpp @@ -0,0 +1,82 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <VCardEntity.h> +#include <VCardValue.h> + +using namespace VCARD; + +Value::Value() + : Entity() +{ +} + +Value::Value(const Value & x) + : Entity(x) +{ +} + +Value::Value(const QCString & s) + : Entity(s) +{ +} + + Value & +Value::operator = (Value & x) +{ + if (*this == x) return *this; + + Entity::operator = (x); + return *this; +} + + Value & +Value::operator = (const QCString & s) +{ + Entity::operator = (s); + return *this; +} + + bool +Value::operator == (Value & x) +{ + x.parse(); + return false; +} + +Value::~Value() +{ +} + + void +Value::_parse() +{ +} + + void +Value::_assemble() +{ +//US vDebug("Value::_assemble()"); + qDebug("Value::_assemble()"); +} + diff --git a/kabc/vcard/include/VCard.h b/kabc/vcard/include/VCard.h new file mode 100644 index 0000000..17b50e8 --- a/dev/null +++ b/kabc/vcard/include/VCard.h @@ -0,0 +1,43 @@ +#ifndef VCARD_H +#define VCARD_H + +#include "VCardAdrParam.h" +#include "VCardAdrValue.h" +#include "VCardAgentParam.h" +#include "VCardAgentValue.h" +#include "VCardClassValue.h" +#include "VCardContentLine.h" +#include "VCardDateParam.h" +#include "VCardDateValue.h" +#include "VCardDefines.h" +#include "VCardEmailParam.h" +#include "VCardEntity.h" +#include "VCardEnum.h" +#include "VCardFloatValue.h" +#include "VCardGeoValue.h" +#include "VCardGroup.h" +#include "VCardImageParam.h" +#include "VCardImageValue.h" +#include "VCardImgValue.h" +#include "VCardLangValue.h" +#include "VCardNValue.h" +#include "VCardOrgValue.h" +#include "VCardParam.h" +#include "VCardPhoneNumberValue.h" +#include "VCardRToken.h" +#include "VCardSoundValue.h" +#include "VCardSourceParam.h" +#include "VCardTelParam.h" +#include "VCardTelValue.h" +#include "VCardTextBinParam.h" +#include "VCardTextBinValue.h" +#include "VCardTextListValue.h" +#include "VCardTextParam.h" +#include "VCardTextValue.h" +#include "VCardURIValue.h" +#include "VCardUTCValue.h" +#include "VCardVCard.h" +#include "VCardVCardEntity.h" +#include "VCardValue.h" + +#endif diff --git a/kabc/vcard/include/VCardAdrParam.h b/kabc/vcard/include/VCardAdrParam.h new file mode 100644 index 0000000..89dcb64 --- a/dev/null +++ b/kabc/vcard/include/VCardAdrParam.h @@ -0,0 +1,64 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef ADRPARAM_H +#define ADRPARAM_H + +#include <qcstring.h> +#include <qstrlist.h> + +#include <VCardParam.h> + +namespace VCARD +{ + +class AdrParam : public Param +{ + +#include "AdrParam-generated.h" + + QStrList adrTypeList() + { parse(); return adrTypeList_; } + + QCString textParam() + { parse(); return textParam_; } + + void setAdrTypeList(const QStrList & l) + { adrTypeList_ = l; assembled_ = false; } + + void setTextParam(const QCString & s) + { textParam_ = s; assembled_ = false; } + + enum AdrType { + AdrDom, AdrIntl, AdrPostal, AdrParcel, AdrHome, AdrWork, AdrPref, + AdrIANA, AdrX + }; + + private: + + QStrList adrTypeList_; + QCString textParam_; +}; +} + +#endif diff --git a/kabc/vcard/include/VCardAdrValue.h b/kabc/vcard/include/VCardAdrValue.h new file mode 100644 index 0000000..0731924 --- a/dev/null +++ b/kabc/vcard/include/VCardAdrValue.h @@ -0,0 +1,83 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef ADRVALUE_H +#define ADRVALUE_H + +#include <qstrlist.h> +#include <VCardValue.h> + +namespace VCARD +{ + +class AdrValue : public Value +{ + +#include "AdrValue-generated.h" + + AdrValue *clone(); + + void setPOBox(const QCString & s) + { poBox_ = s; assembled_ = false; } + + void setExtAddress(const QCString & s) + { extAddress_ = s; assembled_ = false; } + + void setStreet(const QCString & s) + { street_ = s; assembled_ = false; } + + void setLocality(const QCString & s) + { locality_ = s; assembled_ = false; } + + void setRegion(const QCString & s) + { region_ = s; assembled_ = false; } + + void setPostCode(const QCString & s) + { postCode_ = s; assembled_ = false; } + + void setCountryName(const QCString & s) + { countryName_ = s; assembled_ = false; } + + QCString poBox() { parse(); return poBox_; } + QCString extAddress() { parse(); return extAddress_; } + QCString street() { parse(); return street_; } + QCString locality() { parse(); return locality_; } + QCString region() { parse(); return region_; } + QCString postCode() { parse(); return postCode_; } + QCString countryName() { parse(); return countryName_; } + + private: + + QCString poBox_; + QCString extAddress_; + QCString street_; + QCString locality_; + QCString region_; + QCString postCode_; + QCString countryName_; +}; + +} + +#endif + diff --git a/kabc/vcard/include/VCardAgentParam.h b/kabc/vcard/include/VCardAgentParam.h new file mode 100644 index 0000000..72a05db --- a/dev/null +++ b/kabc/vcard/include/VCardAgentParam.h @@ -0,0 +1,60 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef AGENTPARAM_H +#define AGENTPARAM_H + +#include <qcstring.h> + +#include <VCardParam.h> +#include <VCardURIValue.h> + +namespace VCARD +{ + +class AgentParam : public Param +{ + +#include "AgentParam-generated.h" + + bool refer() + { parse(); return refer_; } + + URIValue uri() + { parse(); return uri_; } + + void setRefer(bool b) + { refer_ = b; assembled_ = false; } + + void setURI(const QCString & s) + { uri_ = s; assembled_ = false; } + + private: + + bool refer_; + URIValue uri_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardAgentValue.h b/kabc/vcard/include/VCardAgentValue.h new file mode 100644 index 0000000..f655836 --- a/dev/null +++ b/kabc/vcard/include/VCardAgentValue.h @@ -0,0 +1,44 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef AGENTVALUE_H +#define AGENTVALUE_H + +#include <qcstring.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class AgentValue : public Value +{ + +#include "AgentValue-generated.h" + + private: +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardClassValue.h b/kabc/vcard/include/VCardClassValue.h new file mode 100644 index 0000000..ff133c2 --- a/dev/null +++ b/kabc/vcard/include/VCardClassValue.h @@ -0,0 +1,56 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef CLASSVALUE_H +#define CLASSVALUE_H + +#include <qcstring.h> + +#include <VCardValue.h> + +#include <kdebug.h> + +namespace VCARD +{ + +class ClassValue : public Value +{ + +#include "ClassValue-generated.h" + + enum ClassType { + Public, Private, Confidential, Other + }; + + ClassValue *clone(); + + void setType( int type ) { classType_ = type; assembled_ = false; parsed_ = true; } + int type() { parse(); return classType_; } + + private: + int classType_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardContentLine.h b/kabc/vcard/include/VCardContentLine.h new file mode 100644 index 0000000..1c5f5be --- a/dev/null +++ b/kabc/vcard/include/VCardContentLine.h @@ -0,0 +1,77 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef CONTENTLINE_H +#define CONTENTLINE_H + +#include <qptrlist.h> + +#include "VCardEnum.h" +#include "VCardEntity.h" +#include "VCardParam.h" +#include "VCardValue.h" + +namespace VCARD +{ + +class ContentLine : public Entity +{ + +#include "ContentLine-generated.h" + + QCString group() { parse(); return group_; } + QCString name() { parse(); return name_; } + Value * value() { parse(); return value_; } + ParamList paramList() { parse(); return paramList_; } + ParamType paramType() { parse(); return paramType_; } + ValueType valueType() { parse(); return valueType_; } + EntityType entityType() { parse(); return entityType_; } + + void setGroup (const QCString & s) + { group_ = s; assembled_ = false; } + + void setName (const QCString & s) + { name_ = s; assembled_ = false; } + + void setValue (Value *s) + { value_ = s; assembled_ = false; } + + void setParamList (const ParamList & l) + { paramList_ = l; assembled_ = false; } + + void clear (); + + private: + + QCString group_; + QCString name_; + QPtrList<Param> paramList_; + Value * value_; + + ParamType paramType_; + ValueType valueType_; + EntityType entityType_; +}; +} + +#endif diff --git a/kabc/vcard/include/VCardDateParam.h b/kabc/vcard/include/VCardDateParam.h new file mode 100644 index 0000000..21ac1f1 --- a/dev/null +++ b/kabc/vcard/include/VCardDateParam.h @@ -0,0 +1,44 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef DATEPARAM_H +#define DATEPARAM_H + +#include <qcstring.h> + +#include <VCardParam.h> + +namespace VCARD +{ + +class DateParam : public Param +{ + +#include "DateParam-generated.h" + + private: +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardDateValue.h b/kabc/vcard/include/VCardDateValue.h new file mode 100644 index 0000000..c248966 --- a/dev/null +++ b/kabc/vcard/include/VCardDateValue.h @@ -0,0 +1,99 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef DATEVALUE_H +#define DATEVALUE_H + +#include <qcstring.h> +#include <qdatetime.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class DateValue : public Value +{ +#include "DateValue-generated.h" + + DateValue( + unsigned int year, + unsigned int month, + unsigned int day, + unsigned int hour = 0, + unsigned int minute = 0, + unsigned int second = 0, + double secFrac = 0, + bool zonePositive = true, + unsigned int zoneHour = 0, + unsigned int zoneMinute = 0); + + DateValue(const QDate &); + DateValue(const QDateTime &); + + DateValue *clone(); + + bool hasTime(); + + unsigned int year(); + unsigned int month(); + unsigned int day(); + unsigned int hour(); + unsigned int minute(); + unsigned int second(); + double secondFraction(); + bool zonePositive(); + unsigned int zoneHour(); + unsigned int zoneMinute(); + + void setYear (unsigned int); + void setMonth (unsigned int); + void setDay (unsigned int); + void setHour (unsigned int); + void setMinute (unsigned int); + void setSecond (unsigned int); + void setSecondFraction (double); + void setZonePositive (bool); + void setZoneHour (unsigned int); + void setZoneMinute (unsigned int); + + QDate qdate(); + QTime qtime(); + QDateTime qdt(); + + private: + + unsigned int year_, month_, day_, + hour_, minute_, second_, + zoneHour_, zoneMinute_; + + double secFrac_; + + bool zonePositive_; + + bool hasTime_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardDefines.h b/kabc/vcard/include/VCardDefines.h new file mode 100644 index 0000000..dd38ae2 --- a/dev/null +++ b/kabc/vcard/include/VCardDefines.h @@ -0,0 +1,52 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1998 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef VCARD_DEFINES_H +#define VCARD_DEFINES_H + +#include <kdebug.h> + +#ifdef VCARD_DEBUG +#define vDebug(a) kdDebug(5710) << a << endl; +#else +#define vDebug(a) +#endif + +#if 0 +#ifndef NDEBUG +# include <qcstring.h> +# include <iostream> +# ifdef __GNUG__ +# define vDebug(a) cerr << className() << ":" << __FUNCTION__ << " (" \ + << __LINE__ << "): " << QCString((a)).data() << endl; +# else +# define vDebug(a) cerr << className() << ": " \ + << QCString((a)).data() << endl; +# endif +#else +# define vDebug(a) +#endif +#endif + +#endif // Included this file + diff --git a/kabc/vcard/include/VCardEmailParam.h b/kabc/vcard/include/VCardEmailParam.h new file mode 100644 index 0000000..98d1b30 --- a/dev/null +++ b/kabc/vcard/include/VCardEmailParam.h @@ -0,0 +1,56 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef EMAILPARAM_H +#define EMAILPARAM_H + +#include <qcstring.h> + +#include <VCardParam.h> + +namespace VCARD +{ + +class EmailParam : public Param +{ + +#include "EmailParam-generated.h" + + QCString emailType() { parse(); return emailType_; } + bool pref() { parse(); return pref_; } + + void setEmailType(const QCString & s) + { emailType_ = s; assembled_ = false; } + + void setPref(bool b) + { pref_ = b; assembled_ = false; } + + private: + + QCString emailType_; + bool pref_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardEntity.h b/kabc/vcard/include/VCardEntity.h new file mode 100644 index 0000000..3c945b5 --- a/dev/null +++ b/kabc/vcard/include/VCardEntity.h @@ -0,0 +1,67 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef ENTITY_H +#define ENTITY_H + +#include <qcstring.h> + +namespace VCARD +{ + +class Entity +{ + public: + + Entity(); + Entity(const Entity & e); + Entity(const QCString & s); + + virtual Entity & operator = (const Entity & e); + virtual Entity & operator = (const QCString & s); + + virtual bool operator == (Entity & e); + virtual bool operator != (Entity & e); + virtual bool operator == (const QCString & s); + virtual bool operator != (const QCString & s); + + virtual ~Entity(); + + QCString asString(); + + virtual void parse(); + virtual void assemble(); + + virtual void _parse() = 0; + virtual void _assemble() = 0; + + protected: + + QCString strRep_; + bool parsed_; + bool assembled_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardEnum.h b/kabc/vcard/include/VCardEnum.h new file mode 100644 index 0000000..b4e4094 --- a/dev/null +++ b/kabc/vcard/include/VCardEnum.h @@ -0,0 +1,120 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef ENUM_H +#define ENUM_H + +#include <qcstring.h> + +namespace VCARD +{ + +extern const QCString paramNames []; + +enum EntityType { + EntityName, + EntityProfile, + EntitySource, + EntityFullName, + EntityN, + EntityNickname, + EntityPhoto, + EntityBirthday, + EntityAddress, + EntityLabel, + EntityTelephone, + EntityEmail, + EntityMailer, + EntityTimeZone, + EntityGeo, + EntityTitle, + EntityRole, + EntityLogo, + EntityAgent, + EntityOrganisation, + EntityCategories, + EntityNote, + EntityProductID, + EntityRevision, + EntitySortString, + EntitySound, + EntityUID, + EntityURL, + EntityVersion, + EntityClass, + EntityKey, + EntityExtension, + EntityUnknown +}; + +enum ValueType { + ValueSound, + ValueAgent, + ValueAddress, + ValueTel, + ValueTextBin, + ValueOrg, + ValueN, + ValueUTC, + ValueURI, + ValueClass, + ValueFloat, + ValueImage, + ValueDate, + ValueTextList, + ValueText, + ValueGeo, + ValueUnknown +}; + +enum ParamType { + ParamUnknown, + ParamNone, + ParamSource, + ParamText, + ParamImage, + ParamDate, + ParamAddrText, + ParamTel, + ParamEmail, + ParamMailer, + ParamAgent, + ParamTextBin, + ParamTextNS, + ParamSound +}; + +extern const ParamType paramTypesTable[]; + +ParamType EntityTypeToParamType(EntityType); +ValueType EntityTypeToValueType(EntityType); +QCString EntityTypeToParamName(EntityType); +EntityType EntityNameToEntityType(const QCString &); + +char * encodeBase64(const char *, unsigned long, unsigned long &); +char * decodeBase64(const char *, unsigned long, unsigned long &); + +} + +#endif + diff --git a/kabc/vcard/include/VCardFloatValue.h b/kabc/vcard/include/VCardFloatValue.h new file mode 100644 index 0000000..69fdc22 --- a/dev/null +++ b/kabc/vcard/include/VCardFloatValue.h @@ -0,0 +1,51 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef FLOATVALUE_H +#define FLOATVALUE_H + +#include <qcstring.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class FloatValue : public Value +{ + +#include "FloatValue-generated.h" + + FloatValue(float); + + float value(); + void setValue(float); + + private: + + float value_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardGeoValue.h b/kabc/vcard/include/VCardGeoValue.h new file mode 100644 index 0000000..662761c --- a/dev/null +++ b/kabc/vcard/include/VCardGeoValue.h @@ -0,0 +1,49 @@ +/* + This file is part of libvcard. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef GEOVALUE_H +#define GEOVALUE_H + +#include <VCardValue.h> + +namespace VCARD +{ + +class GeoValue : public Value +{ + +#include "GeoValue-generated.h" + + GeoValue *clone(); + + void setLatitude( float lat ) { latitude_ = lat; assembled_ = false; } + void setLongitude( float lon ) { longitude_ = lon; assembled_ = false; } + + float latitude() { parse(); return latitude_; } + float longitude() { parse(); return longitude_; } + + private: + float latitude_; + float longitude_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardGroup.h b/kabc/vcard/include/VCardGroup.h new file mode 100644 index 0000000..ff775fb --- a/dev/null +++ b/kabc/vcard/include/VCardGroup.h @@ -0,0 +1,39 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef GROUP_H +#define GROUP_H + +#include <VCardEntity.h> + +namespace VCARD +{ + +class Group : public Entity +{ +#include "Group-generated.h" +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardImageParam.h b/kabc/vcard/include/VCardImageParam.h new file mode 100644 index 0000000..ce99ccc --- a/dev/null +++ b/kabc/vcard/include/VCardImageParam.h @@ -0,0 +1,44 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef IMGPARAM_H +#define IMGPARAM_H + +#include <qcstring.h> + +#include <VCardParam.h> + +namespace VCARD +{ + +class ImageParam : public Param +{ + +#include "ImageParam-generated.h" + + private: +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardImageValue.h b/kabc/vcard/include/VCardImageValue.h new file mode 100644 index 0000000..6ce0371 --- a/dev/null +++ b/kabc/vcard/include/VCardImageValue.h @@ -0,0 +1,44 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef IMAGEVALUE_H +#define IMAGEVALUE_H + +#include <qcstring.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class ImageValue : public Value +{ + +#include "ImageValue-generated.h" + + private: +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardImgValue.h b/kabc/vcard/include/VCardImgValue.h new file mode 100644 index 0000000..b09ad64 --- a/dev/null +++ b/kabc/vcard/include/VCardImgValue.h @@ -0,0 +1,39 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef IMGVALUE_H +#define IMGVALUE_H + +#include <VCardValue.h> + +namespace VCARD +{ + +class ImgValue : public Value +{ +#include "ImgValue-generated.h" +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardLangValue.h b/kabc/vcard/include/VCardLangValue.h new file mode 100644 index 0000000..991ceed --- a/dev/null +++ b/kabc/vcard/include/VCardLangValue.h @@ -0,0 +1,51 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef LANGVALUE_H +#define LANGVALUE_H + +#include <qcstring.h> +#include <qstrlist.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class LangValue : public Value +{ +#include "LangValue-generated.h" + + QCString primary(); + QStrList subtags(); + + void setPrimary(const QCString &); + void setSubTags(const QStrList &); + + QCString primary_; + QStrList subtags_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardNValue.h b/kabc/vcard/include/VCardNValue.h new file mode 100644 index 0000000..306821b --- a/dev/null +++ b/kabc/vcard/include/VCardNValue.h @@ -0,0 +1,56 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef NVALUE_H +#define NVALUE_H + +#include <VCardValue.h> + +namespace VCARD +{ + +class NValue : public Value +{ +#include "NValue-generated.h" + NValue *clone(); + + QCString family() { parse(); return family_; } + QCString given() { parse(); return given_; } + QCString middle() { parse(); return middle_; } + QCString prefix() { parse(); return prefix_; } + QCString suffix() { parse(); return suffix_; } + + void setFamily (const QCString & s) { family_ = s; assembled_ = false; } + void setGiven (const QCString & s) { given_ = s; assembled_ = false; } + void setMiddle (const QCString & s) { middle_ = s; assembled_ = false; } + void setPrefix (const QCString & s) { prefix_ = s; assembled_ = false; } + void setSuffix (const QCString & s) { suffix_ = s; assembled_ = false; } + + private: + + QCString family_, given_, middle_, prefix_, suffix_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardOrgValue.h b/kabc/vcard/include/VCardOrgValue.h new file mode 100644 index 0000000..c4f3f25 --- a/dev/null +++ b/kabc/vcard/include/VCardOrgValue.h @@ -0,0 +1,50 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef ORGVALUE_H +#define ORGVALUE_H + +#include <qcstring.h> +#include <qstrlist.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class OrgValue : public Value +{ + +#include "OrgValue-generated.h" + + unsigned int numValues(); + QCString value(unsigned int); + + private: + + QStrList valueList_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardParam.h b/kabc/vcard/include/VCardParam.h new file mode 100644 index 0000000..b61ce5c --- a/dev/null +++ b/kabc/vcard/include/VCardParam.h @@ -0,0 +1,59 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef PARAM_H +#define PARAM_H + +#include <qcstring.h> +#include <qptrlist.h> + +#include <VCardEntity.h> + +namespace VCARD +{ + +class Param : public Entity +{ + +#include "Param-generated.h" + + Param(const QCString &name, const QCString &value); + + void setName(const QCString &); + void setValue(const QCString &); + + QCString name(); + QCString value(); + + private: + + QCString name_; + QCString value_; +}; + +typedef QPtrList<Param> ParamList; +typedef QPtrListIterator<Param> ParamListIterator; + +} + +#endif diff --git a/kabc/vcard/include/VCardPhoneNumberValue.h b/kabc/vcard/include/VCardPhoneNumberValue.h new file mode 100644 index 0000000..a567bdc --- a/dev/null +++ b/kabc/vcard/include/VCardPhoneNumberValue.h @@ -0,0 +1,39 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef PHONENUMBERVALUE_H +#define PHONENUMBERVALUE_H + +#include <VCardValue.h> + +namespace VCARD +{ + +class PhoneNumberValue : public Value +{ +#include "PhoneNumberValue-generated.h" +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardRToken.h b/kabc/vcard/include/VCardRToken.h new file mode 100644 index 0000000..2f95f1b --- a/dev/null +++ b/kabc/vcard/include/VCardRToken.h @@ -0,0 +1,38 @@ +/* + + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef RTOKEN_H +#define RTOKEN_H + +#include <qstrlist.h> + +namespace VCARD +{ + +Q_UINT32 RTokenise(const char * str, const char * delim, QStrList & l); + +} + +#endif + diff --git a/kabc/vcard/include/VCardSndValue.h b/kabc/vcard/include/VCardSndValue.h new file mode 100644 index 0000000..ce56221 --- a/dev/null +++ b/kabc/vcard/include/VCardSndValue.h @@ -0,0 +1,39 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef SNDVALUE_H +#define SNDVALUE_H + +#include <VCardValue.h> + +namespace VCARD +{ + +class SndValue : public Value +{ +#include "SndValue-generated.h" +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardSoundValue.h b/kabc/vcard/include/VCardSoundValue.h new file mode 100644 index 0000000..994f55e --- a/dev/null +++ b/kabc/vcard/include/VCardSoundValue.h @@ -0,0 +1,44 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef SOUNDVALUE_H +#define SOUNDVALUE_H + +#include <qcstring.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class SoundValue : public Value +{ + +#include "SoundValue-generated.h" + + private: +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardSourceParam.h b/kabc/vcard/include/VCardSourceParam.h new file mode 100644 index 0000000..887ea20 --- a/dev/null +++ b/kabc/vcard/include/VCardSourceParam.h @@ -0,0 +1,58 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef SOURCEPARAM_H +#define SOURCEPARAM_H + +#include <qcstring.h> + +#include <VCardParam.h> + +namespace VCARD +{ + +class SourceParam : public Param +{ + +#include "SourceParam-generated.h" + + enum SourceParamType { TypeUnknown, TypeValue, TypeContext, TypeX }; + + SourceParamType type() { parse(); return type_;} + QCString par() { parse(); return par_; } + QCString val() { parse(); return val_; } + + void setType(SourceParamType t) { type_ = t; assembled_ = false; } + void setPar(const QCString & s) { par_ = s; assembled_ = false; } + void setVal(const QCString & s) { val_ = s; assembled_ = false; } + + private: + + SourceParamType type_; + // May be "VALUE = uri" or "CONTEXT = word" or "x-name = *SAFE-CHAR" + QCString par_, val_; // Sub-parameter, value +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardTelParam.h b/kabc/vcard/include/VCardTelParam.h new file mode 100644 index 0000000..27d7dcc --- a/dev/null +++ b/kabc/vcard/include/VCardTelParam.h @@ -0,0 +1,51 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef TELPARAM_H +#define TELPARAM_H + +#include <qcstring.h> + +#include <VCardParam.h> + +namespace VCARD +{ + +class TelParam : public Param +{ +#include "TelParam-generated.h" + + enum TelType { + TelHome, TelWork, TelPref, TelVoice, TelFex, TelMsg, TelCell, + TelPager, TelBBS, TelModem, TelCar, TelISDN, TelVideo, TelPCS, + TelIANA, TelX + }; + + private: + + QPtrList<TelType> types_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardTelValue.h b/kabc/vcard/include/VCardTelValue.h new file mode 100644 index 0000000..9cf5a98 --- a/dev/null +++ b/kabc/vcard/include/VCardTelValue.h @@ -0,0 +1,44 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef TELVALUE_H +#define TELVALUE_H + +#include <qcstring.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class TelValue : public Value +{ + +#include "TelValue-generated.h" + + private: +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardTextBinParam.h b/kabc/vcard/include/VCardTextBinParam.h new file mode 100644 index 0000000..31dec86 --- a/dev/null +++ b/kabc/vcard/include/VCardTextBinParam.h @@ -0,0 +1,44 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef TEXTBINPARAM_H +#define TEXTBINPARAM_H + +#include <qcstring.h> + +#include <VCardParam.h> + +namespace VCARD +{ + +class TextBinParam : public Param +{ + +#include "TextBinParam-generated.h" + + private: +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardTextBinValue.h b/kabc/vcard/include/VCardTextBinValue.h new file mode 100644 index 0000000..8d44fdf --- a/dev/null +++ b/kabc/vcard/include/VCardTextBinValue.h @@ -0,0 +1,67 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef TEXTBINVALUE_H +#define TEXTBINVALUE_H + +#include <qcstring.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class TextBinValue : public Value +{ + +#include "TextBinValue-generated.h" + + TextBinValue *clone(); + + bool isBinary() { parse(); return mIsBinary_; } + QByteArray data() { parse(); return mData_; } + QString url() { parse(); return mUrl_; } + + void setData( const QByteArray &data ) + { + mData_ = data; + mIsBinary_ = true; + assembled_ = false; + } + + void setUrl( const QString &url ) + { + mUrl_ = url; + mIsBinary_ = false; + assembled_ = false; + } + + private: + int mIsBinary_; + QByteArray mData_; + QString mUrl_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardTextListValue.h b/kabc/vcard/include/VCardTextListValue.h new file mode 100644 index 0000000..8e47af5 --- a/dev/null +++ b/kabc/vcard/include/VCardTextListValue.h @@ -0,0 +1,51 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef TEXTLISTVALUE_H +#define TEXTLISTVALUE_H + +#include <qstrlist.h> + +#include <qcstring.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class TextListValue : public Value +{ + +#include "TextListValue-generated.h" + + unsigned int numValues(); + QCString value(unsigned int); + + private: + + QStrList valueList_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardTextParam.h b/kabc/vcard/include/VCardTextParam.h new file mode 100644 index 0000000..08b5f57 --- a/dev/null +++ b/kabc/vcard/include/VCardTextParam.h @@ -0,0 +1,44 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef TEXTPARAM_H +#define TEXTPARAM_H + +#include <qcstring.h> + +#include <VCardParam.h> + +namespace VCARD +{ + +class TextParam : public Param +{ + +#include "TextParam-generated.h" + + private: +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardTextValue.h b/kabc/vcard/include/VCardTextValue.h new file mode 100644 index 0000000..afe8753 --- a/dev/null +++ b/kabc/vcard/include/VCardTextValue.h @@ -0,0 +1,41 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef TEXTVALUE_H +#define TEXTVALUE_H + +#include <VCardValue.h> + +namespace VCARD +{ + +class TextValue : public Value +{ +#include "TextValue-generated.h" + + TextValue *clone(); +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardURIValue.h b/kabc/vcard/include/VCardURIValue.h new file mode 100644 index 0000000..5fd7184 --- a/dev/null +++ b/kabc/vcard/include/VCardURIValue.h @@ -0,0 +1,52 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef URIVALUE_H +#define URIVALUE_H + +#include <VCardValue.h> + +namespace VCARD +{ + +class URIValue : public Value +{ +#include "URIValue-generated.h" + + URIValue(const QCString & scheme, const QCString & schemeSpecificPart); + + QCString scheme(); + QCString schemeSpecificPart(); + + void setScheme (const QCString &); + void setSchemeSpecificPart (const QCString &); + + private: + + QCString scheme_; + QCString schemeSpecificPart_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardUTCValue.h b/kabc/vcard/include/VCardUTCValue.h new file mode 100644 index 0000000..ff695e0 --- a/dev/null +++ b/kabc/vcard/include/VCardUTCValue.h @@ -0,0 +1,58 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef UTCVALUE_H +#define UTCVALUE_H + +#include <qcstring.h> + +#include <VCardValue.h> + +namespace VCARD +{ + +class UTCValue : public Value +{ + +#include "UTCValue-generated.h" + + UTCValue *clone(); + + void setPositive( int p ) { positive_ = p; assembled_ = false; } + void setHour( int h ) { hour_ = h; assembled_ = false; } + void setMinute( int m ) { minute_ = m; assembled_ = false; } + + bool positive() { parse(); return positive_; } + unsigned int hour() { parse(); return hour_; } + unsigned int minute() { parse(); return minute_; } + + private: + + bool positive_; + unsigned int hour_; + unsigned int minute_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardVCard.h b/kabc/vcard/include/VCardVCard.h new file mode 100644 index 0000000..5dec166 --- a/dev/null +++ b/kabc/vcard/include/VCardVCard.h @@ -0,0 +1,63 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef VCARD_VCARD_H +#define VCARD_VCARD_H + +#include <qstring.h> +#include <qptrlist.h> + +#include <VCardEnum.h> +#include <VCardEntity.h> +#include <VCardContentLine.h> + +namespace VCARD +{ + +class VCard : public Entity +{ + +#include "VCard-generated.h" + + bool has(EntityType); + bool has(const QCString &); + + void add(const ContentLine &); + void add(const QCString &); + + ContentLine * contentLine(EntityType); + ContentLine * contentLine(const QCString &); + + QCString group() { parse(); return group_; } + + QPtrList<ContentLine> contentLineList() { parse(); return contentLineList_; } + + private: + + QCString group_; + QPtrList<ContentLine> contentLineList_; +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardVCardEntity.h b/kabc/vcard/include/VCardVCardEntity.h new file mode 100644 index 0000000..47ba370 --- a/dev/null +++ b/kabc/vcard/include/VCardVCardEntity.h @@ -0,0 +1,56 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef VCARD_ENTITY_H +#define VCARD_ENTITY_H + +#include <qstring.h> +#include <qptrlist.h> + +#include <VCardEnum.h> +#include <VCardVCard.h> +#include <VCardEntity.h> + +namespace VCARD +{ + +typedef QPtrList<VCard> VCardList; +typedef QPtrListIterator<VCard> VCardListIterator; + +class VCardEntity : public Entity +{ + +#include "VCardEntity-generated.h" + + void setCardList(const VCardList & l); + VCardList & cardList(); + + private: + + VCardList cardList_; + +}; + +} + +#endif diff --git a/kabc/vcard/include/VCardValue.h b/kabc/vcard/include/VCardValue.h new file mode 100644 index 0000000..7cfe4a0 --- a/dev/null +++ b/kabc/vcard/include/VCardValue.h @@ -0,0 +1,46 @@ +/* + libvcard - vCard parsing library for vCard version 3.0 + + Copyright (C) 1999 Rik Hemsley rik@kde.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef VALUE_H +#define VALUE_H + +#include <qptrlist.h> + +#include <VCardEntity.h> + +namespace VCARD +{ + +class Value : public Entity +{ +#include "Value-generated.h" + + virtual Value *clone() { return new Value( *this ); } +}; + +typedef QPtrList<Value> ValueList; +typedef QPtrListIterator<Value> ValueListIterator; + +} + +#endif diff --git a/kabc/vcard/include/generated/AdrParam-generated.h b/kabc/vcard/include/generated/AdrParam-generated.h new file mode 100644 index 0000000..3e265d8 --- a/dev/null +++ b/kabc/vcard/include/generated/AdrParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +AdrParam(); +AdrParam(const AdrParam&); +AdrParam(const QCString&); +AdrParam & operator = (AdrParam&); +AdrParam & operator = (const QCString&); +bool operator ==(AdrParam&); +bool operator !=(AdrParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {AdrParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~AdrParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "AdrParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/AdrValue-generated.h b/kabc/vcard/include/generated/AdrValue-generated.h new file mode 100644 index 0000000..e1d93e4 --- a/dev/null +++ b/kabc/vcard/include/generated/AdrValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +AdrValue(); +AdrValue(const AdrValue&); +AdrValue(const QCString&); +AdrValue & operator = (AdrValue&); +AdrValue & operator = (const QCString&); +bool operator ==(AdrValue&); +bool operator !=(AdrValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {AdrValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~AdrValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "AdrValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/AgentParam-generated.h b/kabc/vcard/include/generated/AgentParam-generated.h new file mode 100644 index 0000000..6423867 --- a/dev/null +++ b/kabc/vcard/include/generated/AgentParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +AgentParam(); +AgentParam(const AgentParam&); +AgentParam(const QCString&); +AgentParam & operator = (AgentParam&); +AgentParam & operator = (const QCString&); +bool operator ==(AgentParam&); +bool operator !=(AgentParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {AgentParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~AgentParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "AgentParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/AgentValue-generated.h b/kabc/vcard/include/generated/AgentValue-generated.h new file mode 100644 index 0000000..76bb81c --- a/dev/null +++ b/kabc/vcard/include/generated/AgentValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +AgentValue(); +AgentValue(const AgentValue&); +AgentValue(const QCString&); +AgentValue & operator = (AgentValue&); +AgentValue & operator = (const QCString&); +bool operator ==(AgentValue&); +bool operator !=(AgentValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {AgentValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~AgentValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "AgentValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/ClassValue-generated.h b/kabc/vcard/include/generated/ClassValue-generated.h new file mode 100644 index 0000000..df4ed5f --- a/dev/null +++ b/kabc/vcard/include/generated/ClassValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +ClassValue(); +ClassValue(const ClassValue&); +ClassValue(const QCString&); +ClassValue & operator = (ClassValue&); +ClassValue & operator = (const QCString&); +bool operator ==(ClassValue&); +bool operator !=(ClassValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {ClassValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~ClassValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "ClassValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/ContentLine-generated.h b/kabc/vcard/include/generated/ContentLine-generated.h new file mode 100644 index 0000000..9efe273 --- a/dev/null +++ b/kabc/vcard/include/generated/ContentLine-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +ContentLine(); +ContentLine(const ContentLine&); +ContentLine(const QCString&); +ContentLine & operator = (ContentLine&); +ContentLine & operator = (const QCString&); +bool operator ==(ContentLine&); +bool operator !=(ContentLine& x) {return !(*this==x);} +bool operator ==(const QCString& s) {ContentLine a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~ContentLine(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "ContentLine"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/DateParam-generated.h b/kabc/vcard/include/generated/DateParam-generated.h new file mode 100644 index 0000000..ff1da58 --- a/dev/null +++ b/kabc/vcard/include/generated/DateParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +DateParam(); +DateParam(const DateParam&); +DateParam(const QCString&); +DateParam & operator = (DateParam&); +DateParam & operator = (const QCString&); +bool operator ==(DateParam&); +bool operator !=(DateParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {DateParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~DateParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "DateParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/DateValue-generated.h b/kabc/vcard/include/generated/DateValue-generated.h new file mode 100644 index 0000000..a382823 --- a/dev/null +++ b/kabc/vcard/include/generated/DateValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +DateValue(); +DateValue(const DateValue&); +DateValue(const QCString&); +DateValue & operator = (DateValue&); +DateValue & operator = (const QCString&); +bool operator ==(DateValue&); +bool operator !=(DateValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {DateValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~DateValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "DateValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/EmailParam-generated.h b/kabc/vcard/include/generated/EmailParam-generated.h new file mode 100644 index 0000000..428a6fc --- a/dev/null +++ b/kabc/vcard/include/generated/EmailParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +EmailParam(); +EmailParam(const EmailParam&); +EmailParam(const QCString&); +EmailParam & operator = (EmailParam&); +EmailParam & operator = (const QCString&); +bool operator ==(EmailParam&); +bool operator !=(EmailParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {EmailParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~EmailParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "EmailParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/FloatValue-generated.h b/kabc/vcard/include/generated/FloatValue-generated.h new file mode 100644 index 0000000..cac55cf --- a/dev/null +++ b/kabc/vcard/include/generated/FloatValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +FloatValue(); +FloatValue(const FloatValue&); +FloatValue(const QCString&); +FloatValue & operator = (FloatValue&); +FloatValue & operator = (const QCString&); +bool operator ==(FloatValue&); +bool operator !=(FloatValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {FloatValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~FloatValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "FloatValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/GeoValue-generated.h b/kabc/vcard/include/generated/GeoValue-generated.h new file mode 100644 index 0000000..594f3ad --- a/dev/null +++ b/kabc/vcard/include/generated/GeoValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +GeoValue(); +GeoValue(const GeoValue&); +GeoValue(const QCString&); +GeoValue & operator = (GeoValue&); +GeoValue & operator = (const QCString&); +bool operator ==(GeoValue&); +bool operator !=(GeoValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {GeoValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~GeoValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "GeoValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/Group-generated.h b/kabc/vcard/include/generated/Group-generated.h new file mode 100644 index 0000000..f39302d --- a/dev/null +++ b/kabc/vcard/include/generated/Group-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +Group(); +Group(const Group&); +Group(const QCString&); +Group & operator = (Group&); +Group & operator = (const QCString&); +bool operator ==(Group&); +bool operator !=(Group& x) {return !(*this==x);} +bool operator ==(const QCString& s) {Group a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~Group(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "Group"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/ImageParam-generated.h b/kabc/vcard/include/generated/ImageParam-generated.h new file mode 100644 index 0000000..81edfd2 --- a/dev/null +++ b/kabc/vcard/include/generated/ImageParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +ImageParam(); +ImageParam(const ImageParam&); +ImageParam(const QCString&); +ImageParam & operator = (ImageParam&); +ImageParam & operator = (const QCString&); +bool operator ==(ImageParam&); +bool operator !=(ImageParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {ImageParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~ImageParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "ImageParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/ImageValue-generated.h b/kabc/vcard/include/generated/ImageValue-generated.h new file mode 100644 index 0000000..5a2c493 --- a/dev/null +++ b/kabc/vcard/include/generated/ImageValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +ImageValue(); +ImageValue(const ImageValue&); +ImageValue(const QCString&); +ImageValue & operator = (ImageValue&); +ImageValue & operator = (const QCString&); +bool operator ==(ImageValue&); +bool operator !=(ImageValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {ImageValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~ImageValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "ImageValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/ImgParam-generated.h b/kabc/vcard/include/generated/ImgParam-generated.h new file mode 100644 index 0000000..46a6ca0 --- a/dev/null +++ b/kabc/vcard/include/generated/ImgParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +ImgParam(); +ImgParam(const ImgParam&); +ImgParam(const QCString&); +ImgParam & operator = (ImgParam&); +ImgParam & operator = (const QCString&); +bool operator ==(ImgParam&); +bool operator !=(ImgParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {ImgParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~ImgParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +virtual const char * className() const { return "ImgParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/ImgValue-generated.h b/kabc/vcard/include/generated/ImgValue-generated.h new file mode 100644 index 0000000..d75d545 --- a/dev/null +++ b/kabc/vcard/include/generated/ImgValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +ImgValue(); +ImgValue(const ImgValue&); +ImgValue(const QCString&); +ImgValue & operator = (ImgValue&); +ImgValue & operator = (const QCString&); +bool operator ==(ImgValue&); +bool operator !=(ImgValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {ImgValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~ImgValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +virtual const char * className() const { return "ImgValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/LangValue-generated.h b/kabc/vcard/include/generated/LangValue-generated.h new file mode 100644 index 0000000..23e138b --- a/dev/null +++ b/kabc/vcard/include/generated/LangValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +LangValue(); +LangValue(const LangValue&); +LangValue(const QCString&); +LangValue & operator = (LangValue&); +LangValue & operator = (const QCString&); +bool operator ==(LangValue&); +bool operator !=(LangValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {LangValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~LangValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "LangValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/NValue-generated.h b/kabc/vcard/include/generated/NValue-generated.h new file mode 100644 index 0000000..082c253 --- a/dev/null +++ b/kabc/vcard/include/generated/NValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +NValue(); +NValue(const NValue&); +NValue(const QCString&); +NValue & operator = (NValue&); +NValue & operator = (const QCString&); +bool operator ==(NValue&); +bool operator !=(NValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {NValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~NValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "NValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/Name-generated.h b/kabc/vcard/include/generated/Name-generated.h new file mode 100644 index 0000000..0e69abd --- a/dev/null +++ b/kabc/vcard/include/generated/Name-generated.h @@ -0,0 +1,22 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +V_Name(); +V_Name(const V_Name&); +V_Name(const QCString&); +V_Name & operator = (V_Name&); +V_Name & operator = (const QCString&); +bool operator ==(V_Name&); +bool operator !=(V_Name& x) {return !(*this==x);} +bool operator ==(const QCString& s) {V_Name a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~V_Name(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/OrgValue-generated.h b/kabc/vcard/include/generated/OrgValue-generated.h new file mode 100644 index 0000000..51eb1b7 --- a/dev/null +++ b/kabc/vcard/include/generated/OrgValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +OrgValue(); +OrgValue(const OrgValue&); +OrgValue(const QCString&); +OrgValue & operator = (OrgValue&); +OrgValue & operator = (const QCString&); +bool operator ==(OrgValue&); +bool operator !=(OrgValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {OrgValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~OrgValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "OrgValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/Param-generated.h b/kabc/vcard/include/generated/Param-generated.h new file mode 100644 index 0000000..cf4666a --- a/dev/null +++ b/kabc/vcard/include/generated/Param-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +Param(); +Param(const Param&); +Param(const QCString&); +Param & operator = (Param&); +Param & operator = (const QCString&); +bool operator ==(Param&); +bool operator !=(Param& x) {return !(*this==x);} +bool operator ==(const QCString& s) {Param a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~Param(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "Param"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/ParamName-generated.h b/kabc/vcard/include/generated/ParamName-generated.h new file mode 100644 index 0000000..ef673c3 --- a/dev/null +++ b/kabc/vcard/include/generated/ParamName-generated.h @@ -0,0 +1,22 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +V_ParamName(); +V_ParamName(const V_ParamName&); +V_ParamName(const QCString&); +V_ParamName & operator = (V_ParamName&); +V_ParamName & operator = (const QCString&); +bool operator ==(V_ParamName&); +bool operator !=(V_ParamName& x) {return !(*this==x);} +bool operator ==(const QCString& s) {V_ParamName a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~V_ParamName(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/ParamValue-generated.h b/kabc/vcard/include/generated/ParamValue-generated.h new file mode 100644 index 0000000..e73500f --- a/dev/null +++ b/kabc/vcard/include/generated/ParamValue-generated.h @@ -0,0 +1,22 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +V_ParamValue(); +V_ParamValue(const V_ParamValue&); +V_ParamValue(const QCString&); +V_ParamValue & operator = (V_ParamValue&); +V_ParamValue & operator = (const QCString&); +bool operator ==(V_ParamValue&); +bool operator !=(V_ParamValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {V_ParamValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~V_ParamValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/PhoneNumberValue-generated.h b/kabc/vcard/include/generated/PhoneNumberValue-generated.h new file mode 100644 index 0000000..1320f18 --- a/dev/null +++ b/kabc/vcard/include/generated/PhoneNumberValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +PhoneNumberValue(); +PhoneNumberValue(const PhoneNumberValue&); +PhoneNumberValue(const QCString&); +PhoneNumberValue & operator = (PhoneNumberValue&); +PhoneNumberValue & operator = (const QCString&); +bool operator ==(PhoneNumberValue&); +bool operator !=(PhoneNumberValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {PhoneNumberValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~PhoneNumberValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "PhoneNumberValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/SoundValue-generated.h b/kabc/vcard/include/generated/SoundValue-generated.h new file mode 100644 index 0000000..a9ab2e8 --- a/dev/null +++ b/kabc/vcard/include/generated/SoundValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +SoundValue(); +SoundValue(const SoundValue&); +SoundValue(const QCString&); +SoundValue & operator = (SoundValue&); +SoundValue & operator = (const QCString&); +bool operator ==(SoundValue&); +bool operator !=(SoundValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {SoundValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~SoundValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "SoundValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/SourceParam-generated.h b/kabc/vcard/include/generated/SourceParam-generated.h new file mode 100644 index 0000000..75fefb8 --- a/dev/null +++ b/kabc/vcard/include/generated/SourceParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +SourceParam(); +SourceParam(const SourceParam&); +SourceParam(const QCString&); +SourceParam & operator = (SourceParam&); +SourceParam & operator = (const QCString&); +bool operator ==(SourceParam&); +bool operator !=(SourceParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {SourceParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~SourceParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "SourceParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/TelParam-generated.h b/kabc/vcard/include/generated/TelParam-generated.h new file mode 100644 index 0000000..3ee77cc --- a/dev/null +++ b/kabc/vcard/include/generated/TelParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +TelParam(); +TelParam(const TelParam&); +TelParam(const QCString&); +TelParam & operator = (TelParam&); +TelParam & operator = (const QCString&); +bool operator ==(TelParam&); +bool operator !=(TelParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {TelParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~TelParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "TelParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/TelValue-generated.h b/kabc/vcard/include/generated/TelValue-generated.h new file mode 100644 index 0000000..3213e1c --- a/dev/null +++ b/kabc/vcard/include/generated/TelValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +TelValue(); +TelValue(const TelValue&); +TelValue(const QCString&); +TelValue & operator = (TelValue&); +TelValue & operator = (const QCString&); +bool operator ==(TelValue&); +bool operator !=(TelValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {TelValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~TelValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "TelValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/TextBinParam-generated.h b/kabc/vcard/include/generated/TextBinParam-generated.h new file mode 100644 index 0000000..d075c10 --- a/dev/null +++ b/kabc/vcard/include/generated/TextBinParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +TextBinParam(); +TextBinParam(const TextBinParam&); +TextBinParam(const QCString&); +TextBinParam & operator = (TextBinParam&); +TextBinParam & operator = (const QCString&); +bool operator ==(TextBinParam&); +bool operator !=(TextBinParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {TextBinParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~TextBinParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "TextBinParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/TextBinValue-generated.h b/kabc/vcard/include/generated/TextBinValue-generated.h new file mode 100644 index 0000000..e9553ac --- a/dev/null +++ b/kabc/vcard/include/generated/TextBinValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +TextBinValue(); +TextBinValue(const TextBinValue&); +TextBinValue(const QCString&); +TextBinValue & operator = (TextBinValue&); +TextBinValue & operator = (const QCString&); +bool operator ==(TextBinValue&); +bool operator !=(TextBinValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {TextBinValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~TextBinValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "TextBinValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/TextListValue-generated.h b/kabc/vcard/include/generated/TextListValue-generated.h new file mode 100644 index 0000000..9f46124 --- a/dev/null +++ b/kabc/vcard/include/generated/TextListValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +TextListValue(); +TextListValue(const TextListValue&); +TextListValue(const QCString&); +TextListValue & operator = (TextListValue&); +TextListValue & operator = (const QCString&); +bool operator ==(TextListValue&); +bool operator !=(TextListValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {TextListValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~TextListValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "TextListValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/TextNSParam-generated.h b/kabc/vcard/include/generated/TextNSParam-generated.h new file mode 100644 index 0000000..d7f58ca --- a/dev/null +++ b/kabc/vcard/include/generated/TextNSParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +TextNSParam(); +TextNSParam(const TextNSParam&); +TextNSParam(const QCString&); +TextNSParam & operator = (TextNSParam&); +TextNSParam & operator = (const QCString&); +bool operator ==(TextNSParam&); +bool operator !=(TextNSParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {TextNSParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~TextNSParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "TextNSParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/TextParam-generated.h b/kabc/vcard/include/generated/TextParam-generated.h new file mode 100644 index 0000000..154e1bf --- a/dev/null +++ b/kabc/vcard/include/generated/TextParam-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +TextParam(); +TextParam(const TextParam&); +TextParam(const QCString&); +TextParam & operator = (TextParam&); +TextParam & operator = (const QCString&); +bool operator ==(TextParam&); +bool operator !=(TextParam& x) {return !(*this==x);} +bool operator ==(const QCString& s) {TextParam a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~TextParam(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "TextParam"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/TextValue-generated.h b/kabc/vcard/include/generated/TextValue-generated.h new file mode 100644 index 0000000..e1c4dcc --- a/dev/null +++ b/kabc/vcard/include/generated/TextValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +TextValue(); +TextValue(const TextValue&); +TextValue(const QCString&); +TextValue & operator = (TextValue&); +TextValue & operator = (const QCString&); +bool operator ==(TextValue&); +bool operator !=(TextValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {TextValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~TextValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "TextValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/URIValue-generated.h b/kabc/vcard/include/generated/URIValue-generated.h new file mode 100644 index 0000000..dbcb5c1 --- a/dev/null +++ b/kabc/vcard/include/generated/URIValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +URIValue(); +URIValue(const URIValue&); +URIValue(const QCString&); +URIValue & operator = (URIValue&); +URIValue & operator = (const QCString&); +bool operator ==(URIValue&); +bool operator !=(URIValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {URIValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~URIValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "URIValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/UTCValue-generated.h b/kabc/vcard/include/generated/UTCValue-generated.h new file mode 100644 index 0000000..46e447b --- a/dev/null +++ b/kabc/vcard/include/generated/UTCValue-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +UTCValue(); +UTCValue(const UTCValue&); +UTCValue(const QCString&); +UTCValue & operator = (UTCValue&); +UTCValue & operator = (const QCString&); +bool operator ==(UTCValue&); +bool operator !=(UTCValue& x) {return !(*this==x);} +bool operator ==(const QCString& s) {UTCValue a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~UTCValue(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "UTCValue"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/VCard-generated.h b/kabc/vcard/include/generated/VCard-generated.h new file mode 100644 index 0000000..4d7d96d --- a/dev/null +++ b/kabc/vcard/include/generated/VCard-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +VCard(); +VCard(const VCard&); +VCard(const QCString&); +VCard & operator = (VCard&); +VCard & operator = (const QCString&); +bool operator ==(VCard&); +bool operator !=(VCard& x) {return !(*this==x);} +bool operator ==(const QCString& s) {VCard a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~VCard(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "VCard"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/VCardEntity-generated.h b/kabc/vcard/include/generated/VCardEntity-generated.h new file mode 100644 index 0000000..9f2dfbc --- a/dev/null +++ b/kabc/vcard/include/generated/VCardEntity-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +VCardEntity(); +VCardEntity(const VCardEntity&); +VCardEntity(const QCString&); +VCardEntity & operator = (VCardEntity&); +VCardEntity & operator = (const QCString&); +bool operator ==(VCardEntity&); +bool operator !=(VCardEntity& x) {return !(*this==x);} +bool operator ==(const QCString& s) {VCardEntity a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~VCardEntity(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "VCardEntity"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/Value-generated.h b/kabc/vcard/include/generated/Value-generated.h new file mode 100644 index 0000000..7afac34 --- a/dev/null +++ b/kabc/vcard/include/generated/Value-generated.h @@ -0,0 +1,23 @@ +// XXX Automatically generated. DO NOT EDIT! XXX // + +public: +Value(); +Value(const Value&); +Value(const QCString&); +Value & operator = (Value&); +Value & operator = (const QCString&); +bool operator ==(Value&); +bool operator !=(Value& x) {return !(*this==x);} +bool operator ==(const QCString& s) {Value a(s);return(*this==a);} +bool operator != (const QCString& s) {return !(*this == s);} + +virtual ~Value(); +void parse() {if(!parsed_) _parse();parsed_=true;assembled_=false;} + +void assemble() {if(assembled_) return;parse();_assemble();assembled_=true;} + +void _parse(); +void _assemble(); +const char * className() const { return "Value"; } + +// End of automatically generated code // diff --git a/kabc/vcard/include/generated/generate b/kabc/vcard/include/generated/generate new file mode 100644 index 0000000..926dbf1 --- a/dev/null +++ b/kabc/vcard/include/generated/generate @@ -0,0 +1,2 @@ +#!/bin/sh +cat headerBodies | awk -f generateHeaders.awk diff --git a/kabc/vcard/include/generated/generateHeaders.awk b/kabc/vcard/include/generated/generateHeaders.awk new file mode 100644 index 0000000..1053144 --- a/dev/null +++ b/kabc/vcard/include/generated/generateHeaders.awk @@ -0,0 +1,40 @@ +#!/bin/awk -f + +{ + outfile = $1 "-generated.h" + name = $1 + + OFS="" + + print "// XXX Automatically generated. DO NOT EDIT! XXX //\n" > outfile + + if ($2 == "v") { pre = "virtual " } else { pre = "" } + + print "public:" >> outfile + print name "();" >> outfile + print name "(const " name "&);" >> outfile + print name "(const QCString&);" >> outfile + print pre name " & operator = (" name "&);" >> outfile + print pre name " & operator = (const QCString&);" >> outfile + print pre "bool operator ==(" name "&);" >> outfile + print pre "bool operator !=(" name "& x) {return !(*this==x);}" \ + >> outfile + print pre "bool operator ==(const QCString& s) {" name " a(s);" \ + "return(*this==a);} " >> outfile + print pre "bool operator != (const QCString& s) {return !(*this == s);}\n" \ + >> outfile + print "virtual ~" name "();" >> outfile + print pre "void parse() " \ + "{if(!parsed_) _parse();parsed_=true;assembled_=false;}\n" \ + >> outfile + print pre "void assemble() " \ + "{if(assembled_) return;parse();_assemble();assembled_=true;}\n" \ + >> outfile + print pre "void _parse();" >> outfile + print pre "void _assemble();" >> outfile + print pre "const char * className() const { return \"" name "\"; }" \ + >> outfile + + print "\n// End of automatically generated code //" >> outfile +} + diff --git a/kabc/vcard/include/generated/headerBodies b/kabc/vcard/include/generated/headerBodies new file mode 100644 index 0000000..5e77b2b --- a/dev/null +++ b/kabc/vcard/include/generated/headerBodies @@ -0,0 +1,34 @@ +AdrParam Param +AdrValue Value +AgentParam Param +ContentLine Entity +DateParam Param +DateValue Value +EmailParam Param +GeoValue Value +Group Entity +ImageParam Param +ImageValue Value +LangValue Value +NValue Value +Param Entity +PhoneNumberValue Value +SourceParam Param +TelParam Param +TextParam Param +TextNSParam Param +TextValue Value +TextBinParam Param +URIValue Value +VCard Entity +VCardEntity Entity +Value Entity +SoundValue Value +AgentValue Value +TelValue Value +TextBinValue Value +OrgValue Value +UTCValue Value +ClassValue Value +FloatValue Value +TextListValue Value diff --git a/kabc/vcard/testread.cpp b/kabc/vcard/testread.cpp new file mode 100644 index 0000000..919c661 --- a/dev/null +++ b/kabc/vcard/testread.cpp @@ -0,0 +1,129 @@ +#include <iostream> +#include <stdlib.h> +#include <assert.h> + +#include <qfile.h> +#include <qtextstream.h> + +#include <VCard.h> + +using namespace std; + +int main(int argc, char * argv[]) +{ + if (argc != 2) { + cerr << "Usage: " << argv[0] << " <filename>" << endl; + exit(1); + } + + QFile f(argv[1]); + + QCString str; + + if (!f.open(IO_ReadOnly)) { + cerr << "Couldn't open file \"" << argv[1] << endl; + exit(1); + } + + QTextStream t(&f); + + while (!t.eof()) + str += t.readLine().utf8() + '\n'; + + using namespace VCARD; + + // Iterate through all vCards in the file. + + cout << "--------- begin ----------" << endl; + cout << str.data(); + cout << "--------- end ----------" << endl; + + VCardEntity e(str); + + VCardListIterator it(e.cardList()); + + for (; it.current(); ++it) { + + cerr << "****************** VCARD ********************" << endl; + + // Create a vcard using the string representation. + VCard & v (*it.current()); + + if (v.has(EntityEmail)) { + cerr << "Email parameter found" << endl; + + QCString s = v.contentLine(EntityEmail)->value()->asString(); + + cerr << "Email value == " << s << endl; + } + + if (v.has(EntityNickname)) { + cerr << "Nickname parameter found" << endl; + + cerr << "Nickname value == " << + v.contentLine(EntityNickname)->value()->asString() << + endl; + } + + if (v.has(EntityRevision)) { + + cerr << "Revision parameter found" << endl; + + DateValue * d = + (DateValue *) + v.contentLine(EntityRevision)->value(); + + assert(d != 0); + + cerr << "Revision date: " << endl; + cerr << "Day : " << d->day() << endl; + cerr << "Month : " << d->month() << endl; + cerr << "Year : " << d->year() << endl; + + if (d->hasTime()) { + cerr << "Revision date has a time component" << endl; + cerr << "Revision time: " << endl; + cerr << "Hour : " << d->hour() << endl; + cerr << "Minute : " << d->minute() << endl; + cerr << "Second : " << d->second() << endl; + + } + else cerr << "Revision date does NOT have a time component" << endl; + } + + if (v.has(EntityURL)) { + cerr << "URL Parameter found" << endl; + + cerr << "URL Value == " << + v.contentLine(EntityURL)->value()->asString() << + endl; + + URIValue * urlVal = + (URIValue *)v.contentLine(EntityURL)->value(); + + assert(urlVal != 0); + + cerr << "URL scheme == " << + urlVal->scheme() << endl; + + cerr << "URL scheme specific part == " << + urlVal->schemeSpecificPart() << endl; + } + + if (v.has(EntityN)) { + cerr << "N Parameter found" << endl; + + NValue * n = + (NValue *)(v.contentLine(EntityN)->value()); + + cerr << "Family name == " << n->family() << endl; + cerr << "Given name == " << n->given() << endl; + cerr << "Middle name == " << n->middle() << endl; + cerr << "Prefix == " << n->prefix() << endl; + cerr << "Suffix == " << n->suffix() << endl; + } + + cerr << "***************** END VCARD ******************" << endl; + } +} + diff --git a/kabc/vcard/testwrite.cpp b/kabc/vcard/testwrite.cpp new file mode 100644 index 0000000..e4bbe7b --- a/dev/null +++ b/kabc/vcard/testwrite.cpp @@ -0,0 +1,41 @@ +#include <kaboutdata.h> +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> +#include <kcmdlineargs.h> + +#include <VCard.h> + +int main(int argc,char **argv) +{ + KAboutData aboutData("testwrite",I18N_NOOP("TestWritevCard"),"0.1"); + KCmdLineArgs::init(argc,argv,&aboutData); + + KApplication app; + + kdDebug() << "Test Write VCard" << endl; + + using namespace VCARD; + + VCard v; + + ContentLine cl1; + cl1.setName(EntityTypeToParamName(EntityName)); + cl1.setValue(new TextValue("Hans Wurst")); + v.add(cl1); + + ContentLine cl2; + cl2.setName(EntityTypeToParamName(EntityTelephone)); + cl2.setValue(new TelValue("12345")); + ParamList p; + p.append( new TelParam("home") ); + p.append( new TelParam("fax") ); + cl2.setParamList( p ); + v.add(cl2); + + QCString str = v.asString(); + + kdDebug() << "--- VCard begin ---" << endl + << str + << "--- VCard end ---" << endl; +} diff --git a/kabc/vcard/vCard-all.cpp b/kabc/vcard/vCard-all.cpp new file mode 100644 index 0000000..07bbcd2 --- a/dev/null +++ b/kabc/vcard/vCard-all.cpp @@ -0,0 +1,37 @@ +#include "AdrParam.cpp" +#include "AdrValue.cpp" +#include "AgentParam.cpp" +#include "AgentValue.cpp" +#include "ClassValue.cpp" +#include "ContentLine.cpp" +#include "DateParam.cpp" +#include "DateValue.cpp" +#include "EmailParam.cpp" +#include "Entity.cpp" +#include "Enum.cpp" +#include "FloatValue.cpp" +#include "GeoValue.cpp" +#include "ImageParam.cpp" +#include "ImageValue.cpp" +#include "ImgValue.cpp" +#include "LangValue.cpp" +#include "NValue.cpp" +#include "OrgValue.cpp" +#include "Param.cpp" +#include "PhoneNumberValue.cpp" +#include "RToken.cpp" +#include "SoundValue.cpp" +#include "SourceParam.cpp" +#include "TelParam.cpp" +#include "TelValue.cpp" +#include "TextBinParam.cpp" +#include "TextBinValue.cpp" +#include "TextListValue.cpp" +#include "TextParam.cpp" +#include "TextValue.cpp" +#include "URIValue.cpp" +#include "UTCValue.cpp" +#include "VCard.cpp" +#include "VCardEntity.cpp" +#include "Value.cpp" + diff --git a/kabc/vcard21parser.cpp b/kabc/vcard21parser.cpp new file mode 100644 index 0000000..b02aac4 --- a/dev/null +++ b/kabc/vcard21parser.cpp @@ -0,0 +1,606 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Mark Westcott <mark@houseoffish.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qmap.h> +#include <qregexp.h> +#include <kmdcodec.h> + +#include "vcard21parser.h" +#include "vcardconverter.h" + +using namespace KABC; + +bool VCardLineX::isValid() const +{ + // Invalid: if it is "begin:vcard" or "end:vcard" + if ( name == VCARD_BEGIN_N || name == VCARD_END_N ) + return false; + + if ( name[0] == 'x' && name[1] == '-' ) // A custom x- line + return true; + + // This is long but it makes it a bit faster (and saves me from using + // a tree which is probably the ideal situation, but a bit memory heavy) + switch( name[0] ) { + case 'a': + if ( name == VCARD_ADR && qualified && + (qualifiers.contains(VCARD_ADR_DOM) || + qualifiers.contains(VCARD_ADR_INTL) || + qualifiers.contains(VCARD_ADR_POSTAL) || + qualifiers.contains(VCARD_ADR_HOME) || + qualifiers.contains(VCARD_ADR_WORK) || + qualifiers.contains(VCARD_ADR_PREF) + ) ) + return true; + + if ( name == VCARD_AGENT ) + return true; + break; + + case 'b': + if ( name == VCARD_BDAY ) + return true; + break; + + case 'c': + if ( name == VCARD_CATEGORIES ) + return true; + if ( name == VCARD_CLASS && qualified && + (qualifiers.contains(VCARD_CLASS_PUBLIC) || + qualifiers.contains(VCARD_CLASS_PRIVATE) || + qualifiers.contains(VCARD_CLASS_CONFIDENTIAL) + ) ) + return true; + break; + + case 'e': + if ( name == VCARD_EMAIL && qualified && + (qualifiers.contains(VCARD_EMAIL_INTERNET) || + qualifiers.contains(VCARD_EMAIL_PREF) || + qualifiers.contains(VCARD_EMAIL_X400) + ) ) + return true; + break; + + case 'f': + if ( name == VCARD_FN ) + return true; + break; + + case 'g': + if ( name == VCARD_GEO ) + return true; + break; + + case 'k': + if ( name == VCARD_KEY && qualified && + (qualifiers.contains(VCARD_KEY_X509) || + qualifiers.contains(VCARD_KEY_PGP) + ) ) + return true; + break; + + case 'l': + if ( name == VCARD_LABEL ) + return true; + if ( name == VCARD_LOGO ) + return true; + break; + + case 'm': + if ( name == VCARD_MAILER ) + return true; + break; + + case 'n': + if ( name == VCARD_N ) + return true; + if ( name == VCARD_NAME ) + return true; + if ( name == VCARD_NICKNAME ) + return true; + if ( name == VCARD_NOTE ) + return true; + break; + + case 'o': + if ( name == VCARD_ORG ) + return true; + break; + + case 'p': + if ( name == VCARD_PHOTO ) + return true; + if ( name == VCARD_PROFILE ) + return true; + if ( name == VCARD_PRODID ) + return true; + break; + + case 'r': + if ( name == VCARD_ROLE ) + return true; + if ( name == VCARD_REV ) + return true; + break; + + case 's': + if ( name == VCARD_SOURCE ) + return true; + if ( name == VCARD_SOUND ) + return true; + break; + + case 't': + if ( name == VCARD_TEL && qualified && + (qualifiers.contains(VCARD_TEL_HOME) || + qualifiers.contains(VCARD_TEL_WORK) || + qualifiers.contains(VCARD_TEL_PREF) || + qualifiers.contains(VCARD_TEL_VOICE) || + qualifiers.contains(VCARD_TEL_FAX) || + qualifiers.contains(VCARD_TEL_MSG) || + qualifiers.contains(VCARD_TEL_CELL) || + qualifiers.contains(VCARD_TEL_PAGER) || + qualifiers.contains(VCARD_TEL_BBS) || + qualifiers.contains(VCARD_TEL_MODEM) || + qualifiers.contains(VCARD_TEL_CAR) || + qualifiers.contains(VCARD_TEL_ISDN) || + qualifiers.contains(VCARD_TEL_VIDEO) || + qualifiers.contains(VCARD_TEL_PCS) + ) ) + return true; + if ( name == VCARD_TZ ) + return true; + if ( name == VCARD_TITLE ) + return true; + break; + + case 'u': + if ( name == VCARD_URL ) + return true; + if ( name == VCARD_UID ) + return true; + break; + + case 'v': + if ( name == VCARD_VERSION ) + return true; + break; + default: + break; + } + + return false; +} + + +VCard21Parser::VCard21Parser() +{ +} + +VCard21Parser::~VCard21Parser() +{ +} + +void VCard21Parser::readFromString(KABC::AddressBook *addressbook, const QString &data) +{ + KABC::Addressee mAddressee = readFromString(data); + addressbook->insertAddressee(mAddressee); +} + +KABC::Addressee VCard21Parser::readFromString( const QString &data) +{ + KABC::Addressee addressee; + VCard21ParserImpl *mVCard = VCard21ParserImpl::parseVCard(data); + QString tmpStr; + + // Check if parsing failed + if (mVCard == 0) + { + kdDebug() << "Parsing failed" << endl; + return addressee; + } + //set the addressees name and formated name + QStringList tmpList = mVCard->getValues(VCARD_N); + QString formattedName = ""; + if (tmpList.count() > 0) + addressee.setFamilyName(tmpList[0]); + if (tmpList.count() > 1) + addressee.setGivenName(tmpList[1]); + if (tmpList.count() > 2) + addressee.setAdditionalName(tmpList[2]); + if (tmpList.count() > 3) + addressee.setPrefix(tmpList[3]); + if (tmpList.count() > 4) + addressee.setSuffix(tmpList[4]); + + tmpStr = (mVCard->getValue(VCARD_FN)); + if (!tmpStr.isEmpty()) + addressee.setFormattedName(tmpStr); + + //set the addressee's nick name + tmpStr = mVCard->getValue(VCARD_NICKNAME); + addressee.setNickName(tmpStr); + //set the addressee's organisation + tmpStr = mVCard->getValue(VCARD_ORG); + addressee.setOrganization(tmpStr); + //set the addressee's title + tmpStr = mVCard->getValue(VCARD_TITLE); + addressee.setTitle(tmpStr); + //set the addressee's email - we can only deal with two. The preferenced one and one other. + tmpStr = mVCard->getValue(VCARD_EMAIL, VCARD_EMAIL_INTERNET); + addressee.insertEmail(tmpStr, false); + tmpStr = mVCard->getValue(VCARD_EMAIL,VCARD_EMAIL_PREF); + addressee.insertEmail(tmpStr, true); + //set the addressee's url + tmpStr = mVCard->getValue(VCARD_URL); + if (tmpStr.isEmpty()) tmpStr = mVCard->getValue(VCARD_URL, VCARD_ADR_WORK); + if (tmpStr.isEmpty()) tmpStr = mVCard->getValue(VCARD_URL, VCARD_ADR_HOME); + if (!tmpStr.isEmpty()) { + addressee.setUrl(KURL(tmpStr)); + } + + //set the addressee's birthday + tmpStr = mVCard->getValue(VCARD_BDAY); + addressee.setBirthday(VCardStringToDate(tmpStr)); + + //set the addressee's phone numbers + for ( QValueListIterator<VCardLineX> i = mVCard->_vcdata->begin();i != mVCard->_vcdata->end(); ++i ) { + if ( (*i).name == VCARD_TEL ) { + int type = 0; + if ( (*i).qualified ) { + if ( (*i).qualifiers.contains( VCARD_TEL_HOME ) ) + type |= PhoneNumber::Home; + if ( (*i).qualifiers.contains( VCARD_TEL_WORK ) ) + type |= PhoneNumber::Work; + if ( (*i).qualifiers.contains( VCARD_TEL_PREF ) ) + type |= PhoneNumber::Pref; + // if ( (*i).qualifiers.contains( VCARD_TEL_VOICE ) ) + // type |= PhoneNumber::Voice; + if ( (*i).qualifiers.contains( VCARD_TEL_FAX ) ) + type |= PhoneNumber::Fax; + if ( (*i).qualifiers.contains( VCARD_TEL_MSG ) ) + type |= PhoneNumber::Msg; + if ( (*i).qualifiers.contains( VCARD_TEL_CELL ) ) + type |= PhoneNumber::Cell; + if ( (*i).qualifiers.contains( VCARD_TEL_PAGER ) ) + type |= PhoneNumber::Pager; + if ( (*i).qualifiers.contains( VCARD_TEL_BBS ) ) + type |= PhoneNumber::Bbs; + if ( (*i).qualifiers.contains( VCARD_TEL_MODEM ) ) + type |= PhoneNumber::Modem; + if ( (*i).qualifiers.contains( VCARD_TEL_CAR ) ) + type |= PhoneNumber::Car; + if ( (*i).qualifiers.contains( VCARD_TEL_ISDN ) ) + type |= PhoneNumber::Isdn; + if ( (*i).qualifiers.contains( VCARD_TEL_VIDEO ) ) + type |= PhoneNumber::Video; + if ( (*i).qualifiers.contains( VCARD_TEL_PCS ) ) + type |= PhoneNumber::Pcs; + } + addressee.insertPhoneNumber( PhoneNumber( (*i).parameters[ 0 ], type ) ); + } + } + + //set the addressee's addresses + for ( QValueListIterator<VCardLineX> i = mVCard->_vcdata->begin();i != mVCard->_vcdata->end(); ++i ) { + if ( (*i).name == VCARD_ADR ) { + int type = 0; + if ( (*i).qualified ) { + if ( (*i).qualifiers.contains( VCARD_ADR_DOM ) ) + type |= Address::Dom; + if ( (*i).qualifiers.contains( VCARD_ADR_INTL ) ) + type |= Address::Intl; + if ( (*i).qualifiers.contains( VCARD_ADR_POSTAL ) ) + type |= Address::Postal; + if ( (*i).qualifiers.contains( VCARD_ADR_PARCEL ) ) + type |= Address::Parcel; + if ( (*i).qualifiers.contains( VCARD_ADR_HOME ) ) + type |= Address::Home; + if ( (*i).qualifiers.contains( VCARD_ADR_WORK ) ) + type |= Address::Work; + if ( (*i).qualifiers.contains( VCARD_ADR_PREF ) ) + type |= Address::Pref; + } + addressee.insertAddress( readAddressFromQStringList( (*i).parameters, type ) ); + } + } + + //set the addressee's delivery label + tmpStr = mVCard->getValue(VCARD_LABEL); + if (!tmpStr.isEmpty()) { +qDebug("VCard21Parser::readFromString please verify if replace is correct"); +//US tmpStr.replace("\r\n","\n"); + tmpStr.replace( QRegExp("\r\n"), "\n" ); + Address tmpAddress; + tmpAddress.setLabel(tmpStr); + addressee.insertAddress(tmpAddress); + } + + //set the addressee's notes + tmpStr = mVCard->getValue(VCARD_NOTE); +qDebug("VCard21Parser::readFromString please verify if correct"); +//US tmpStr.replace("\r\n","\n"); + tmpStr.replace( QRegExp("\r\n"), "\n" ); + addressee.setNote(tmpStr); + + //set the addressee's timezone + tmpStr = mVCard->getValue(VCARD_TZ); + TimeZone tmpZone(tmpStr.toInt()); + addressee.setTimeZone(tmpZone); + + //set the addressee's geographical position + tmpList = mVCard->getValues(VCARD_GEO); + if (tmpList.count()==2) + { + tmpStr = tmpList[0]; + float glat = tmpStr.toFloat(); + tmpStr = tmpList[1]; + float glong = tmpStr.toFloat(); + Geo tmpGeo(glat,glong); + addressee.setGeo(tmpGeo); + } + + //set the last revision date + tmpStr = mVCard->getValue(VCARD_REV); + addressee.setRevision(VCardStringToDate(tmpStr)); + + //set the role of the addressee + tmpStr = mVCard->getValue(VCARD_ROLE); + addressee.setRole(tmpStr); + + return addressee; +} + + + +KABC::Address VCard21Parser::readAddressFromQStringList ( const QStringList &data, const int type ) +{ + KABC::Address mAddress; + mAddress.setType( type ); + + if ( data.count() > 0 ) + mAddress.setPostOfficeBox( data[0] ); + if ( data.count() > 1 ) + mAddress.setExtended( data[1] ); + if ( data.count() > 2 ) + mAddress.setStreet( data[2] ); + if ( data.count() > 3 ) + mAddress.setLocality( data[3] ); + if ( data.count() > 4 ) + mAddress.setRegion( data[4] ); + if ( data.count() > 5 ) + mAddress.setPostalCode( data[5] ); + if ( data.count() > 6 ) + mAddress.setCountry( data[6] ); + + return mAddress; +} + + +VCard21ParserImpl *VCard21ParserImpl::parseVCard( const QString& vc, int *err ) +{ + int _err = 0; + int _state = VC_STATE_BEGIN; + + QValueList<VCardLineX> *_vcdata; + QValueList<QString> lines; + + _vcdata = new QValueList<VCardLineX>; + + lines = QStringList::split( QRegExp( "[\x0d\x0a]" ), vc ); + + // for each line in the vCard + for ( QStringList::Iterator j = lines.begin(); j != lines.end(); ++j ) { + VCardLineX _vcl; + + // take spaces off the end - ugly but necessary hack + for ( int g = (*j).length()-1; g > 0 && (*j)[g].isSpace(); --g ) + (*j)[g] = 0; + + // first token: + // verify state, update if necessary + if ( _state & VC_STATE_BEGIN) { + if ( !qstricmp( (*j).latin1(), VCARD_BEGIN ) ) { + _state = VC_STATE_BODY; + continue; + } else { + _err = VC_ERR_NO_BEGIN; + break; + } + } else if ( _state & VC_STATE_BODY ) { + if ( !qstricmp( (*j).latin1(), VCARD_END ) ) { + _state |= VC_STATE_END; + break; + } + + // split into two tokens + int colon = (*j).find( ':' ); + if ( colon < 0 ) { + _err = VC_ERR_INVALID_LINE; + break; + } + + QString key = (*j).left( colon ); + QString value = (*j).mid( colon + 1 ); + + // check for qualifiers and + // set name, qualified, qualifier(s) + QStringList keyTokens = QStringList::split( ';', key ); + bool qp = false, first_pass = true; + bool b64 = false; + + if ( keyTokens.count() > 0 ) { + _vcl.qualified = false; + _vcl.name = keyTokens[ 0 ].lower(); + + for ( QStringList::Iterator z = keyTokens.begin(); z != keyTokens.end(); ++z ) { + QString zz = (*z).lower(); + if ( zz == VCARD_QUOTED_PRINTABLE || zz == VCARD_ENCODING_QUOTED_PRINTABLE ) { + qp = true; + } else if ( zz == VCARD_BASE64 ) { + b64 = true; + } else if ( !first_pass ) { + _vcl.qualified = true; + _vcl.qualifiers.append( zz ); + } + first_pass = false; + } + } else { + _err = VC_ERR_INVALID_LINE; + } + + if ( _err != 0 ) + break; + + if ( _vcl.name == VCARD_VERSION ) + _state |= VC_STATE_HAVE_VERSION; + + if ( _vcl.name == VCARD_N || _vcl.name == VCARD_FN ) + _state |= VC_STATE_HAVE_N; + + // second token: + // split into tokens by ; + // add to parameters vector + if ( b64 ) { + if ( value.at( value.length() - 1 ) != '=' ) + do { + value += *( ++j ); + } while ( (*j).at( (*j).length() - 1 ) != '=' ); + } else { + if ( qp ) { // join any split lines + while ( value.at( value.length() - 1 ) == '=' ) { + value.remove( value.length() - 1, 1 ); + value.append(*( ++j )); + } + } + _vcl.parameters = QStringList::split( ';', value, true ); + if ( qp ) { // decode the quoted printable + for ( QStringList::Iterator z = _vcl.parameters.begin(); z != _vcl.parameters.end(); ++z ) + *z = KCodecs::quotedPrintableDecode( (*z).latin1() ); + } + } + } else { + _err = VC_ERR_INTERNAL; + break; + } + + // validate VCardLineX + if ( !_vcl.isValid() ) { + _err = VC_ERR_INVALID_LINE; + break; + } + + // add to vector + _vcdata->append( _vcl ); + } + + // errors to check at the last minute (exit state related) + if ( _err == 0 ) { + if ( !( _state & VC_STATE_END ) ) // we have to have an end!! + _err = VC_ERR_NO_END; + + if ( !( _state & VC_STATE_HAVE_N ) || // we have to have the mandatories! + !( _state & VC_STATE_HAVE_VERSION ) ) + _err = VC_ERR_MISSING_MANDATORY; + } + + // set the error message if we can, and only return an object + // if the vCard was valid. + if ( err ) + *err = _err; + + if ( _err != 0 ) { + delete _vcdata; + return 0; + } + + return new VCard21ParserImpl( _vcdata ); +} + +VCard21ParserImpl::VCard21ParserImpl(QValueList<VCardLineX> *_vcd) : _vcdata(_vcd) +{ +} + + +QString VCard21ParserImpl::getValue(const QString& name, const QString& qualifier) +{ + QString failed; + const QString lowname = name.lower(); + const QString lowqualifier = qualifier.lower(); + + for (QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) { + if ((*i).name == lowname && (*i).qualified && (*i).qualifiers.contains(lowqualifier)) { + if ((*i).parameters.count() > 0) + return (*i).parameters[0]; + else return failed; + } + } + return failed; +} + + +QString VCard21ParserImpl::getValue(const QString& name) +{ + QString failed; + const QString lowname = name.lower(); + + for (QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) { + if ((*i).name == lowname && !(*i).qualified) { + if ((*i).parameters.count() > 0) + return (*i).parameters[0]; + else return failed; + } + } + return failed; +} + + +QStringList VCard21ParserImpl::getValues(const QString& name) +{ + const QString lowname = name.lower(); + for (QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) { + if ((*i).name == lowname && !(*i).qualified) + return (*i).parameters; + } + // failed. + return QStringList(); +} + +QStringList VCard21ParserImpl::getValues(const QString& name, const QString& qualifier) +{ + const QString lowname = name.lower(); + const QString lowqualifier = qualifier.lower(); + for (QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) { + if ((*i).name == lowname && (*i).qualified && (*i).qualifiers.contains(lowqualifier)) + return (*i).parameters; + } + // failed. + return QStringList(); +} + + diff --git a/kabc/vcard21parser.h b/kabc/vcard21parser.h new file mode 100644 index 0000000..24b0eb2 --- a/dev/null +++ b/kabc/vcard21parser.h @@ -0,0 +1,225 @@ +/* + This file is part of libkabc. + + Copyright (c) 2002 Mark Westcott <mark@houseoffish.org> + Copyright (c) 2000 George Staikos <staikos@kde.org> + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_VCARD21FORMAT_H +#define KABC_VCARD21FORMAT_H + +#include <qdatetime.h> +#include <kdebug.h> +#include <qregexp.h> +#include <qstring.h> +#include <kurl.h> +#include <qvaluelist.h> + +#include "addressee.h" +#include "addressbook.h" +#include "phonenumber.h" + + +#define VCARD_BEGIN "begin:vcard" +#define VCARD_END "end:vcard" +#define VCARD_BEGIN_N "begin" +#define VCARD_END_N "end" +#define VCARD_VERSION "version" + +#define VCARD_FN "fn" +#define VCARD_N "n" + +// optional +#define VCARD_NAME "name" +#define VCARD_NICKNAME "nickname" +#define VCARD_PHOTO "photo" +#define VCARD_BDAY "bday" +#define VCARD_ADR "adr" + +// types +#define VCARD_ADR_DOM "dom" +#define VCARD_ADR_INTL "intl" +#define VCARD_ADR_POSTAL "postal" +#define VCARD_ADR_PARCEL "parcel" +#define VCARD_ADR_HOME "home" +#define VCARD_ADR_WORK "work" +#define VCARD_ADR_PREF "pref" +// values +#define VCARD_ADR_POBOX "PO Box" +#define VCARD_ADR_EXTADR "Extended Address" +#define VCARD_ADR_STREET "Street" +#define VCARD_ADR_LOCALITY "Locality" +#define VCARD_ADR_REGION "Region" +#define VCARD_ADR_POSTCODE "Postal Code" +#define VCARD_ADR_COUNTRY "Country Name" +#define VCARD_LABEL "label" +#define VCARD_PROFILE "profile" +#define VCARD_SOURCE "source" +#define VCARD_TEL "tel" +// types +#define VCARD_TEL_HOME "home" +#define VCARD_TEL_WORK "work" +#define VCARD_TEL_PREF "pref" +#define VCARD_TEL_VOICE "voice" +#define VCARD_TEL_FAX "fax" +#define VCARD_TEL_MSG "msg" +#define VCARD_TEL_CELL "cell" +#define VCARD_TEL_PAGER "pager" +#define VCARD_TEL_BBS "bbs" +#define VCARD_TEL_MODEM "modem" +#define VCARD_TEL_CAR "car" +#define VCARD_TEL_ISDN "isdn" +#define VCARD_TEL_VIDEO "video" +#define VCARD_TEL_PCS "pcs" +#define VCARD_EMAIL "email" +// types +#define VCARD_EMAIL_PREF "pref" +#define VCARD_EMAIL_INTERNET "internet" +#define VCARD_EMAIL_X400 "x400" +#define VCARD_TZ "tz" +#define VCARD_GEO "geo" +#define VCARD_MAILER "mailer" +#define VCARD_TITLE "title" +#define VCARD_ROLE "role" +#define VCARD_LOGO "logo" +#define VCARD_AGENT "agent" +#define VCARD_ORG "org" +#define VCARD_CATEGORIES "categories" +#define VCARD_NOTE "note" +#define VCARD_PRODID "prodid" +#define VCARD_REV "rev" +#define VCARD_SOUND "sound" +#define VCARD_UID "uid" +#define VCARD_URL "url" +#define VCARD_CLASS "class" +#define VCARD_CLASS_PUBLIC "public" +#define VCARD_CLASS_PRIVATE "private" +#define VCARD_CLASS_CONFIDENTIAL "confidential" +#define VCARD_KEY "key" +// types +#define VCARD_KEY_X509 "x509" +#define VCARD_KEY_PGP "pgp" + +#define VCARD_QUOTED_PRINTABLE "quoted-printable" +// this one is a temporary hack until we support TYPE=VALUE +#define VCARD_ENCODING_QUOTED_PRINTABLE "encoding=quoted-printable" +#define VCARD_BASE64 "base64" + +#define VC_STATE_BEGIN 1 +#define VC_STATE_BODY 2 +#define VC_STATE_END 4 +#define VC_STATE_HAVE_N 8 +#define VC_STATE_HAVE_VERSION 16 + +#define VC_ERR_NO_BEGIN 1 +#define VC_ERR_NO_END 2 +#define VC_ERR_INVALID_LINE 3 +#define VC_ERR_INTERNAL 4 +#define VC_ERR_INVALID_NAME 5 +#define VC_ERR_MISSING_MANDATORY 6 + +namespace KABC { + +class AddressBook; + +class VCard21Parser +{ +public: + + /** + * Constructor. + */ + VCard21Parser(); + + /** + * Destructor. + */ + virtual ~VCard21Parser(); + + /** + * Parses a string in vcard2.1 format and saves the single addressees + * to the address book. + * + * @param ab The address book. + * @param str The vcard string. + */ + void readFromString( KABC::AddressBook *ab, const QString &str ); + + /** + * FIXME: we need a writeToString method + * QString writeToString (KABC::AddressBook *); + */ + + /** + * Parses a string in vcard2.1 format and returns the inherent addressee. + */ + KABC::Addressee readFromString( const QString &data); + + /** + * Helper method to store a address. + * + * @param data A string list, that is filled with 'street', 'house number' ... + * @param type The type of the returned address. + */ + static KABC::Address readAddressFromQStringList (const QStringList &data, const int type); +}; + +} + +/** + * @short Helper class + */ +class VCardLineX +{ +public: + QString name; + bool qualified; + QValueList<QString> qualifiers; + QValueList<QString> parameters; + bool isValid() const; +}; + +/** + * @short Helper class + */ +class VCard21ParserImpl +{ + friend class VCardLineX; + +public: + VCard21ParserImpl() { }; + virtual ~VCard21ParserImpl() { }; + static VCard21ParserImpl *parseVCard(const QString& vc, int *err = NULL); + QString getValue(const QString& name, const QString& qualifier); + QString getValue(const QString& name); + QStringList getValues(const QString& name, const QString& qualifier); + QStringList getValues(const QString& name); + + QValueList<VCardLineX> *_vcdata; + +private: + VCard21ParserImpl (QValueList<VCardLineX> *_vcd); +}; + +#endif diff --git a/kabc/vcardconverter.cpp b/kabc/vcardconverter.cpp new file mode 100644 index 0000000..266cdf9 --- a/dev/null +++ b/kabc/vcardconverter.cpp @@ -0,0 +1,115 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +//US +#include "kglobal.h" + +#include "vcard21parser.h" +#include "vcardformatimpl.h" + +#include "vcardconverter.h" + +using namespace KABC; + +struct VCardConverter::VCardConverterData +{ + VCard21Parser vcard21parser; + VCardFormatImpl vcard30parser; +}; + +VCardConverter::VCardConverter() + : d( new VCardConverterData ) +{ +} + +VCardConverter::~VCardConverter() +{ + delete d; + d = 0; +} + +bool VCardConverter::vCardToAddressee( const QString &str, Addressee &addr, Version version ) +{ + if ( version == v2_1 ) { + addr = d->vcard21parser.readFromString( str ); + return true; + } + + if ( version == v3_0 ) + return d->vcard30parser.readFromString( str, addr ); + + return false; +} + +bool VCardConverter::addresseeToVCard( const Addressee &addr, QString &str, Version version ) +{ + if ( version == v2_1 ) + return false; + + if ( version == v3_0 ) + return d->vcard30parser.writeToString( addr, str ); + + return false; +} + + +/* Helper functions */ + +QString KABC::dateToVCardString( const QDateTime &dateTime ) +{ +qDebug("vcardconverter.cpp : KABC::dateToVCardString transformation does not work yet"); + return KGlobal::locale()->formatDate(dateTime.date(), true); +//US return dateTime.toString("yyyyMMddThhmmssZ"); +} + +QString KABC::dateToVCardString( const QDate &date ) +{ +qDebug("vcardconverter.cpp : KABC::dateToVCardString transformation does not work yet"); + return KGlobal::locale()->formatDate(date, true); +//US return date.toString("yyyyMMdd"); +} + +QDateTime KABC::VCardStringToDate( const QString &dateString ) +{ + QDate date; + QTime time; + QString d( dateString ); + +//US I hope this is correct +//US d = d.remove('-').remove(':'); + d = d.replace( QRegExp("-"), "" ); + d = d.replace( QRegExp(":"), "" ); + + + if (d.length()>=8) + date = QDate( d.mid(0,4).toUInt(), d.mid(4,2).toUInt(), d.mid(6,2).toUInt() ); + if (d.length()>9 && d[8].upper()=='T') + time = QTime( d.mid(9,2).toUInt(), d.mid(11,2).toUInt(), d.mid(13,2).toUInt() ); + + return QDateTime( date, time ); +} + diff --git a/kabc/vcardconverter.h b/kabc/vcardconverter.h new file mode 100644 index 0000000..52259fc --- a/dev/null +++ b/kabc/vcardconverter.h @@ -0,0 +1,120 @@ +/* + This file is part of libkabc. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_VCARDCONVERTER_H +#define KABC_VCARDCONVERTER_H + +#include <qstring.h> + +#include "addressee.h" + +namespace KABC { + +/** + * Class to convert a vcard string to a addressee and vice versa. + * At the moment there exists read support for vCard2.1 and vCard3.0 + * and write support for vCard3.0 + */ +class VCardConverter +{ +public: + + /** + * @li v2_1 - VCard format version 2.1 + * @li v3_0 - VCard format version 3.0 + */ + enum Version + { + v2_1, + v3_0 + }; + + /** + * Constructor. + */ + VCardConverter(); + + /** + * Destructor. + */ + ~VCardConverter(); + + /** + * Converts a vcard string to an addressee. + * + * @param str The vcard string. + * @param addr The addressee. + * @param version The version of the vcard string. + */ + bool vCardToAddressee( const QString &str, Addressee &addr, Version version = v3_0 ); + + /** + * Converts an addressee to a vcard string. + * + * @param addr The addressee. + * @param str The vcard string. + * @param version The version of the vcard string. + */ + bool addresseeToVCard( const Addressee &addr, QString &str, Version version = v3_0 ); + +private: + struct VCardConverterData; + VCardConverterData *d; +}; + + +/** + Helper functions + */ + +/** + * Converts a QDateTime to a date string as it is used in VCard and LDIF files. + * The return value is in the form "yyyyMMddThhmmssZ" (e.g. "20031201T120000Z") + * @param dateTime date and time to be converted + * @since 3.2 + */ +QString dateToVCardString( const QDateTime &dateTime ); + +/** + * Converts a QDate to a short date string as it is used in VCard and LDIF files. + * The return value is in the form "yyyyMMdd" (e.g. "20031201") + * @param date date to be converted + * @since 3.2 + */ +QString dateToVCardString( const QDate &date ); + +/** + * Converts a date string as it is used in VCard and LDIF files to a QDateTime value. + * If the date string does not contain a time value, it will be returned as 00:00:00. + * (e.g. "20031201T120000" will return a QDateTime for 2003-12-01 at 12:00) + * @param dateString string representing the date and time. + * @since 3.2 + */ +QDateTime VCardStringToDate( const QString &dateString ); + +} +#endif diff --git a/kabc/vcardformatimpl.cpp b/kabc/vcardformatimpl.cpp new file mode 100644 index 0000000..f90f813 --- a/dev/null +++ b/kabc/vcardformatimpl.cpp @@ -0,0 +1,1023 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qfile.h> +#include <qregexp.h> + +#include <kdebug.h> +#include <kmdcodec.h> +#include <kstandarddirs.h> +#include <ktempfile.h> + +#include <VCard.h> + +#include "addressbook.h" +#include "vcardformatimpl.h" + +using namespace KABC; +using namespace VCARD; + +bool VCardFormatImpl::load( Addressee &addressee, QFile *file ) +{ + kdDebug(5700) << "VCardFormat::load()" << endl; + + QByteArray fdata = file->readAll(); + QCString data(fdata.data(), fdata.size()+1); + + VCardEntity e( data ); + + VCardListIterator it( e.cardList() ); + + if ( it.current() ) { + VCard v(*it.current()); + loadAddressee( addressee, v ); + return true; + } + + return false; +} + +bool VCardFormatImpl::loadAll( AddressBook *addressBook, Resource *resource, QFile *file ) +{ + kdDebug(5700) << "VCardFormat::loadAll()" << endl; + + QByteArray fdata = file->readAll(); + QCString data(fdata.data(), fdata.size()+1); + + VCardEntity e( data ); + + VCardListIterator it( e.cardList() ); + + for (; it.current(); ++it) { + VCard v(*it.current()); + Addressee addressee; + loadAddressee( addressee, v ); + addressee.setResource( resource ); + addressBook->insertAddressee( addressee ); + } + + return true; +} + +void VCardFormatImpl::save( const Addressee &addressee, QFile *file ) +{ + VCardEntity vcards; + VCardList vcardlist; + vcardlist.setAutoDelete( true ); + + VCard *v = new VCard; + + saveAddressee( addressee, v, false ); + + vcardlist.append( v ); + vcards.setCardList( vcardlist ); + + QCString vcardData = vcards.asString(); + file->writeBlock( (const char*)vcardData, vcardData.length() ); +} + +void VCardFormatImpl::saveAll( AddressBook *ab, Resource *resource, QFile *file ) +{ + VCardEntity vcards; + VCardList vcardlist; + vcardlist.setAutoDelete( true ); + + AddressBook::Iterator it; + for ( it = ab->begin(); it != ab->end(); ++it ) { + if ( (*it).resource() == resource ) { + VCard *v = new VCard; + saveAddressee( (*it), v, false ); + (*it).setChanged( false ); + vcardlist.append( v ); + } + } + + vcards.setCardList( vcardlist ); + + QCString vcardData = vcards.asString(); + file->writeBlock( (const char*)vcardData, vcardData.length() ); +} + +bool VCardFormatImpl::loadAddressee( Addressee& addressee, VCard &v ) +{ + QPtrList<ContentLine> contentLines = v.contentLineList(); + ContentLine *cl; + + for( cl = contentLines.first(); cl; cl = contentLines.next() ) { + QCString n = cl->name(); + if ( n.left( 2 ) == "X-" ) { + n = n.mid( 2 ); + int posDash = n.find( "-" ); + addressee.insertCustom( QString::fromUtf8( n.left( posDash ) ), + QString::fromUtf8( n.mid( posDash + 1 ) ), + QString::fromUtf8( cl->value()->asString() ) ); + continue; + } + + EntityType type = cl->entityType(); + switch( type ) { + + case EntityUID: + addressee.setUid( readTextValue( cl ) ); + break; + + case EntityEmail: + addressee.insertEmail( readTextValue( cl ) ); + break; + + case EntityName: + addressee.setName( readTextValue( cl ) ); + break; + + case EntityFullName: + addressee.setFormattedName( readTextValue( cl ) ); + break; + + case EntityURL: + addressee.setUrl( KURL( readTextValue( cl ) ) ); + break; + + case EntityNickname: + addressee.setNickName( readTextValue( cl ) ); + break; + + case EntityLabel: + // not yet supported by kabc + break; + + case EntityMailer: + addressee.setMailer( readTextValue( cl ) ); + break; + + case EntityTitle: + addressee.setTitle( readTextValue( cl ) ); + break; + + case EntityRole: + addressee.setRole( readTextValue( cl ) ); + break; + + case EntityOrganisation: + addressee.setOrganization( readTextValue( cl ) ); + break; + + case EntityNote: + addressee.setNote( readTextValue( cl ) ); + break; + + case EntityProductID: + addressee.setProductId( readTextValue( cl ) ); + break; + + case EntitySortString: + addressee.setSortString( readTextValue( cl ) ); + break; + + case EntityN: + readNValue( cl, addressee ); + break; + + case EntityAddress: + addressee.insertAddress( readAddressValue( cl ) ); + break; + + case EntityTelephone: + addressee.insertPhoneNumber( readTelephoneValue( cl ) ); + break; + + case EntityCategories: + addressee.setCategories( QStringList::split( ",", readTextValue( cl ) ) ); + break; + + case EntityBirthday: + addressee.setBirthday( readDateValue( cl ) ); + break; + + case EntityRevision: + addressee.setRevision( readDateTimeValue( cl ) ); + break; + + case EntityGeo: + addressee.setGeo( readGeoValue( cl ) ); + break; + + case EntityTimeZone: + addressee.setTimeZone( readUTCValue( cl ) ); + break; + + case EntityVersion: + break; + + case EntityClass: + addressee.setSecrecy( readClassValue( cl ) ); + break; + + case EntityKey: + addressee.insertKey( readKeyValue( cl ) ); + break; + + case EntityPhoto: + addressee.setPhoto( readPictureValue( cl, EntityPhoto, addressee ) ); + break; + + case EntityLogo: + addressee.setLogo( readPictureValue( cl, EntityLogo, addressee ) ); + break; + + case EntityAgent: + addressee.setAgent( readAgentValue( cl ) ); + break; + + case EntitySound: + addressee.setSound( readSoundValue( cl, addressee ) ); + break; + + default: + kdDebug(5700) << "VCardFormat::load(): Unsupported entity: " + << int( type ) << ": " << cl->asString() << endl; + break; + } + } + + for( cl = contentLines.first(); cl; cl = contentLines.next() ) { + EntityType type = cl->entityType(); + if ( type == EntityLabel ) { + int type = readAddressParam( cl ); + Address address = addressee.address( type ); + if ( address.isEmpty() ) + address.setType( type ); + + address.setLabel( QString::fromUtf8( cl->value()->asString() ) ); + addressee.insertAddress( address ); + } + } + + return true; +} + +void VCardFormatImpl::saveAddressee( const Addressee &addressee, VCard *v, bool intern ) +{ + ContentLine cl; + QString value; + + addTextValue( v, EntityName, addressee.name() ); + addTextValue( v, EntityUID, addressee.uid() ); + addTextValue( v, EntityFullName, addressee.formattedName() ); + + QStringList emails = addressee.emails(); + QStringList::ConstIterator it4; + for( it4 = emails.begin(); it4 != emails.end(); ++it4 ) { + addTextValue( v, EntityEmail, *it4 ); + } + + QStringList customs = addressee.customs(); + QStringList::ConstIterator it5; + for( it5 = customs.begin(); it5 != customs.end(); ++it5 ) { + addCustomValue( v, *it5 ); + } + + addTextValue( v, EntityURL, addressee.url().url() ); + + addNValue( v, addressee ); + + addTextValue( v, EntityNickname, addressee.nickName() ); + addTextValue( v, EntityMailer, addressee.mailer() ); + addTextValue( v, EntityTitle, addressee.title() ); + addTextValue( v, EntityRole, addressee.role() ); + addTextValue( v, EntityOrganisation, addressee.organization() ); + addTextValue( v, EntityNote, addressee.note() ); + addTextValue( v, EntityProductID, addressee.productId() ); + addTextValue( v, EntitySortString, addressee.sortString() ); + + Address::List addresses = addressee.addresses(); + Address::List::ConstIterator it3; + for( it3 = addresses.begin(); it3 != addresses.end(); ++it3 ) { + addAddressValue( v, *it3 ); + addLabelValue( v, *it3 ); + } + + PhoneNumber::List phoneNumbers = addressee.phoneNumbers(); + PhoneNumber::List::ConstIterator it2; + for( it2 = phoneNumbers.begin(); it2 != phoneNumbers.end(); ++it2 ) { + addTelephoneValue( v, *it2 ); + } + + Key::List keys = addressee.keys(); + Key::List::ConstIterator it6; + for( it6 = keys.begin(); it6 != keys.end(); ++it6 ) { + addKeyValue( v, *it6 ); + } + + addTextValue( v, EntityCategories, addressee.categories().join(",") ); + + addDateValue( v, EntityBirthday, addressee.birthday().date() ); + addDateTimeValue( v, EntityRevision, addressee.revision() ); + addGeoValue( v, addressee.geo() ); + addUTCValue( v, addressee.timeZone() ); + + addClassValue( v, addressee.secrecy() ); + + addPictureValue( v, EntityPhoto, addressee.photo(), addressee, intern ); + addPictureValue( v, EntityLogo, addressee.logo(), addressee, intern ); + + addAgentValue( v, addressee.agent() ); + + addSoundValue( v, addressee.sound(), addressee, intern ); +} + +void VCardFormatImpl::addCustomValue( VCard *v, const QString &txt ) +{ + if ( txt.isEmpty() ) return; + + ContentLine cl; + cl.setName( "X-" + txt.left( txt.find( ":" ) ).utf8() ); + QString value = txt.mid( txt.find( ":" ) + 1 ); + if ( value.isEmpty() ) + return; + cl.setValue( new TextValue( value.utf8() ) ); + v->add(cl); +} + +void VCardFormatImpl::addTextValue( VCard *v, EntityType type, const QString &txt ) +{ + if ( txt.isEmpty() ) return; + + ContentLine cl; + cl.setName( EntityTypeToParamName( type ) ); + cl.setValue( new TextValue( txt.utf8() ) ); + v->add(cl); +} + +void VCardFormatImpl::addDateValue( VCard *vcard, EntityType type, + const QDate &date ) +{ + if ( !date.isValid() ) return; + + ContentLine cl; + cl.setName( EntityTypeToParamName( type ) ); + + DateValue *v = new DateValue( date ); + cl.setValue( v ); + vcard->add(cl); +} + +void VCardFormatImpl::addDateTimeValue( VCard *vcard, EntityType type, + const QDateTime &dateTime ) +{ + if ( !dateTime.isValid() ) return; + + ContentLine cl; + cl.setName( EntityTypeToParamName( type ) ); + + DateValue *v = new DateValue( dateTime ); + cl.setValue( v ); + vcard->add(cl); +} + +void VCardFormatImpl::addAddressValue( VCard *vcard, const Address &a ) +{ + if ( a.isEmpty() ) + return; + + ContentLine cl; + cl.setName( EntityTypeToParamName( EntityAddress ) ); + + AdrValue *v = new AdrValue; + v->setPOBox( a.postOfficeBox().utf8() ); + v->setExtAddress( a.extended().utf8() ); + v->setStreet( a.street().utf8() ); + v->setLocality( a.locality().utf8() ); + v->setRegion( a.region().utf8() ); + v->setPostCode( a.postalCode().utf8() ); + v->setCountryName( a.country().utf8() ); + cl.setValue( v ); + + addAddressParam( &cl, a.type() ); + + vcard->add( cl ); +} + +void VCardFormatImpl::addLabelValue( VCard *vcard, const Address &a ) +{ + if ( a.label().isEmpty() ) return; + + ContentLine cl; + cl.setName( EntityTypeToParamName( EntityLabel ) ); + cl.setValue( new TextValue( a.label().utf8() ) ); + + addAddressParam( &cl, a.type() ); + + vcard->add( cl ); +} + +void VCardFormatImpl::addAddressParam( ContentLine *cl, int type ) +{ + ParamList params; + if ( type & Address::Dom ) params.append( new Param( "TYPE", "dom" ) ); + if ( type & Address::Intl ) params.append( new Param( "TYPE", "intl" ) ); + if ( type & Address::Parcel ) params.append( new Param( "TYPE", "parcel" ) ); + if ( type & Address::Postal ) params.append( new Param( "TYPE", "postal" ) ); + if ( type & Address::Work ) params.append( new Param( "TYPE", "work" ) ); + if ( type & Address::Home ) params.append( new Param( "TYPE", "home" ) ); + if ( type & Address::Pref ) params.append( new Param( "TYPE", "pref" ) ); + cl->setParamList( params ); +} + +void VCardFormatImpl::addGeoValue( VCard *vcard, const Geo &geo ) +{ + if ( !geo.isValid() ) return; + + ContentLine cl; + cl.setName( EntityTypeToParamName( EntityGeo ) ); + + GeoValue *v = new GeoValue; + v->setLatitude( geo.latitude() ); + v->setLongitude( geo.longitude() ); + + cl.setValue( v ); + vcard->add(cl); +} + +void VCardFormatImpl::addUTCValue( VCard *vcard, const TimeZone &tz ) +{ + if ( !tz.isValid() ) return; + + ContentLine cl; + cl.setName( EntityTypeToParamName( EntityTimeZone ) ); + + UTCValue *v = new UTCValue; + + v->setPositive( tz.offset() >= 0 ); + v->setHour( (tz.offset() / 60) * ( tz.offset() >= 0 ? 1 : -1 ) ); + v->setMinute( (tz.offset() % 60) * ( tz.offset() >= 0 ? 1 : -1 ) ); + + cl.setValue( v ); + vcard->add(cl); +} + +void VCardFormatImpl::addClassValue( VCard *vcard, const Secrecy &secrecy ) +{ + ContentLine cl; + cl.setName( EntityTypeToParamName( EntityClass ) ); + + ClassValue *v = new ClassValue; + switch ( secrecy.type() ) { + case Secrecy::Public: + v->setType( (int)ClassValue::Public ); + break; + case Secrecy::Private: + v->setType( (int)ClassValue::Private ); + break; + case Secrecy::Confidential: + v->setType( (int)ClassValue::Confidential ); + break; + } + + cl.setValue( v ); + vcard->add(cl); +} + + +Address VCardFormatImpl::readAddressValue( ContentLine *cl ) +{ + Address a; + AdrValue *v = (AdrValue *)cl->value(); + a.setPostOfficeBox( QString::fromUtf8( v->poBox() ) ); + a.setExtended( QString::fromUtf8( v->extAddress() ) ); + a.setStreet( QString::fromUtf8( v->street() ) ); + a.setLocality( QString::fromUtf8( v->locality() ) ); + a.setRegion( QString::fromUtf8( v->region() ) ); + a.setPostalCode( QString::fromUtf8( v->postCode() ) ); + a.setCountry( QString::fromUtf8( v->countryName() ) ); + + a.setType( readAddressParam( cl ) ); + + return a; +} + +int VCardFormatImpl::readAddressParam( ContentLine *cl ) +{ + int type = 0; + ParamList params = cl->paramList(); + ParamListIterator it( params ); + for( ; it.current(); ++it ) { + if ( (*it)->name() == "TYPE" ) { + if ( (*it)->value() == "dom" ) type |= Address::Dom; + else if ( (*it)->value() == "intl" ) type |= Address::Intl; + else if ( (*it)->value() == "parcel" ) type |= Address::Parcel; + else if ( (*it)->value() == "postal" ) type |= Address::Postal; + else if ( (*it)->value() == "work" ) type |= Address::Work; + else if ( (*it)->value() == "home" ) type |= Address::Home; + else if ( (*it)->value() == "pref" ) type |= Address::Pref; + } + } + return type; +} + +void VCardFormatImpl::addNValue( VCard *vcard, const Addressee &a ) +{ + ContentLine cl; + cl.setName(EntityTypeToParamName( EntityN ) ); + NValue *v = new NValue; + v->setFamily( a.familyName().utf8() ); + v->setGiven( a.givenName().utf8() ); + v->setMiddle( a.additionalName().utf8() ); + v->setPrefix( a.prefix().utf8() ); + v->setSuffix( a.suffix().utf8() ); + + cl.setValue( v ); + vcard->add(cl); +} + +void VCardFormatImpl::readNValue( ContentLine *cl, Addressee &a ) +{ + NValue *v = (NValue *)cl->value(); + a.setFamilyName( QString::fromUtf8( v->family() ) ); + a.setGivenName( QString::fromUtf8( v->given() ) ); + a.setAdditionalName( QString::fromUtf8( v->middle() ) ); + a.setPrefix( QString::fromUtf8( v->prefix() ) ); + a.setSuffix( QString::fromUtf8( v->suffix() ) ); +} + +void VCardFormatImpl::addTelephoneValue( VCard *v, const PhoneNumber &p ) +{ + if ( p.number().isEmpty() ) + return; + + ContentLine cl; + cl.setName(EntityTypeToParamName(EntityTelephone)); + cl.setValue(new TelValue( p.number().utf8() )); + + ParamList params; + if( p.type() & PhoneNumber::Home ) params.append( new Param( "TYPE", "home" ) ); + if( p.type() & PhoneNumber::Work ) params.append( new Param( "TYPE", "work" ) ); + if( p.type() & PhoneNumber::Msg ) params.append( new Param( "TYPE", "msg" ) ); + if( p.type() & PhoneNumber::Pref ) params.append( new Param( "TYPE", "pref" ) ); + if( p.type() & PhoneNumber::Voice ) params.append( new Param( "TYPE", "voice" ) ); + if( p.type() & PhoneNumber::Fax ) params.append( new Param( "TYPE", "fax" ) ); + if( p.type() & PhoneNumber::Cell ) params.append( new Param( "TYPE", "cell" ) ); + if( p.type() & PhoneNumber::Video ) params.append( new Param( "TYPE", "video" ) ); + if( p.type() & PhoneNumber::Bbs ) params.append( new Param( "TYPE", "bbs" ) ); + if( p.type() & PhoneNumber::Modem ) params.append( new Param( "TYPE", "modem" ) ); + if( p.type() & PhoneNumber::Car ) params.append( new Param( "TYPE", "car" ) ); + if( p.type() & PhoneNumber::Isdn ) params.append( new Param( "TYPE", "isdn" ) ); + if( p.type() & PhoneNumber::Pcs ) params.append( new Param( "TYPE", "pcs" ) ); + if( p.type() & PhoneNumber::Pager ) params.append( new Param( "TYPE", "pager" ) ); + cl.setParamList( params ); + + v->add(cl); +} + +PhoneNumber VCardFormatImpl::readTelephoneValue( ContentLine *cl ) +{ + PhoneNumber p; + TelValue *value = (TelValue *)cl->value(); + p.setNumber( QString::fromUtf8( value->asString() ) ); + + int type = 0; + ParamList params = cl->paramList(); + ParamListIterator it( params ); + for( ; it.current(); ++it ) { + if ( (*it)->name() == "TYPE" ) { + if ( (*it)->value() == "home" ) type |= PhoneNumber::Home; + else if ( (*it)->value() == "work" ) type |= PhoneNumber::Work; + else if ( (*it)->value() == "msg" ) type |= PhoneNumber::Msg; + else if ( (*it)->value() == "pref" ) type |= PhoneNumber::Pref; + else if ( (*it)->value() == "voice" ) type |= PhoneNumber::Voice; + else if ( (*it)->value() == "fax" ) type |= PhoneNumber::Fax; + else if ( (*it)->value() == "cell" ) type |= PhoneNumber::Cell; + else if ( (*it)->value() == "video" ) type |= PhoneNumber::Video; + else if ( (*it)->value() == "bbs" ) type |= PhoneNumber::Bbs; + else if ( (*it)->value() == "modem" ) type |= PhoneNumber::Modem; + else if ( (*it)->value() == "car" ) type |= PhoneNumber::Car; + else if ( (*it)->value() == "isdn" ) type |= PhoneNumber::Isdn; + else if ( (*it)->value() == "pcs" ) type |= PhoneNumber::Pcs; + else if ( (*it)->value() == "pager" ) type |= PhoneNumber::Pager; + } + } + p.setType( type ); + + return p; +} + +QString VCardFormatImpl::readTextValue( ContentLine *cl ) +{ + VCARD::Value *value = cl->value(); + if ( value ) { + return QString::fromUtf8( value->asString() ); + } else { + kdDebug(5700) << "No value: " << cl->asString() << endl; + return QString::null; + } +} + +QDate VCardFormatImpl::readDateValue( ContentLine *cl ) +{ + DateValue *dateValue = (DateValue *)cl->value(); + if ( dateValue ) + return dateValue->qdate(); + else + return QDate(); +} + +QDateTime VCardFormatImpl::readDateTimeValue( ContentLine *cl ) +{ + DateValue *dateValue = (DateValue *)cl->value(); + if ( dateValue ) + return dateValue->qdt(); + else + return QDateTime(); +} + +Geo VCardFormatImpl::readGeoValue( ContentLine *cl ) +{ + GeoValue *geoValue = (GeoValue *)cl->value(); + if ( geoValue ) { + Geo geo( geoValue->latitude(), geoValue->longitude() ); + return geo; + } else + return Geo(); +} + +TimeZone VCardFormatImpl::readUTCValue( ContentLine *cl ) +{ + UTCValue *utcValue = (UTCValue *)cl->value(); + if ( utcValue ) { + TimeZone tz; + tz.setOffset(((utcValue->hour()*60)+utcValue->minute())*(utcValue->positive() ? 1 : -1)); + return tz; + } else + return TimeZone(); +} + +Secrecy VCardFormatImpl::readClassValue( ContentLine *cl ) +{ + ClassValue *classValue = (ClassValue *)cl->value(); + if ( classValue ) { + Secrecy secrecy; + switch ( classValue->type() ) { + case ClassValue::Public: + secrecy.setType( Secrecy::Public ); + break; + case ClassValue::Private: + secrecy.setType( Secrecy::Private ); + break; + case ClassValue::Confidential: + secrecy.setType( Secrecy::Confidential ); + break; + } + + return secrecy; + } else + return Secrecy(); +} + +void VCardFormatImpl::addKeyValue( VCARD::VCard *vcard, const Key &key ) +{ + ContentLine cl; + cl.setName( EntityTypeToParamName( EntityKey ) ); + + ParamList params; + if ( key.isBinary() ) { + cl.setValue( new TextValue( KCodecs::base64Encode( key.binaryData() ) ) ); + params.append( new Param( "ENCODING", "b" ) ); + } else { + cl.setValue( new TextValue( key.textData().utf8() ) ); + } + + switch ( key.type() ) { + case Key::X509: + params.append( new Param( "TYPE", "X509" ) ); + break; + case Key::PGP: + params.append( new Param( "TYPE", "PGP" ) ); + break; + case Key::Custom: + params.append( new Param( "TYPE", key.customTypeString().utf8() ) ); + break; + } + + cl.setParamList( params ); + vcard->add( cl ); +} + +Key VCardFormatImpl::readKeyValue( VCARD::ContentLine *cl ) +{ + Key key; + bool isBinary = false; + TextValue *v = (TextValue *)cl->value(); + + ParamList params = cl->paramList(); + ParamListIterator it( params ); + for( ; it.current(); ++it ) { + if ( (*it)->name() == "ENCODING" && (*it)->value() == "b" ) + isBinary = true; + if ( (*it)->name() == "TYPE" ) { + if ( (*it)->value().isEmpty() ) + continue; + if ( (*it)->value() == "X509" ) + key.setType( Key::X509 ); + else if ( (*it)->value() == "PGP" ) + key.setType( Key::PGP ); + else { + key.setType( Key::Custom ); + key.setCustomTypeString( QString::fromUtf8( (*it)->value() ) ); + } + } + } + + + if ( isBinary ) { + QByteArray data; + KCodecs::base64Decode( v->asString().stripWhiteSpace(), data ); + key.setBinaryData( data ); + } else { + key.setTextData( QString::fromUtf8( v->asString() ) ); + } + + return key; +} + + +void VCardFormatImpl::addAgentValue( VCARD::VCard *vcard, const Agent &agent ) +{ + if ( agent.isIntern() && !agent.addressee() ) + return; + + if ( !agent.isIntern() && agent.url().isEmpty() ) + return; + + ContentLine cl; + cl.setName( EntityTypeToParamName( EntityAgent ) ); + + ParamList params; + if ( agent.isIntern() ) { + QString vstr; + Addressee *addr = agent.addressee(); + if ( addr ) { + writeToString( (*addr), vstr ); + + qDebug("VCardFormatImpl::addAgentValue please verify if replace is correct"); +/*US + vstr.replace( ":", "\\:" ); + vstr.replace( ",", "\\," ); + vstr.replace( ";", "\\;" ); + vstr.replace( "\r\n", "\\n" ); +*/ + vstr.replace( QRegExp(":"), "\\:" ); + vstr.replace( QRegExp(","), "\\," ); + vstr.replace( QRegExp(";"), "\\;" ); + vstr.replace( QRegExp("\r\n"), "\\n" ); + + cl.setValue( new TextValue( vstr.utf8() ) ); + } else + return; + } else { + cl.setValue( new TextValue( agent.url().utf8() ) ); + params.append( new Param( "VALUE", "uri" ) ); + } + + cl.setParamList( params ); + vcard->add( cl ); +} + +Agent VCardFormatImpl::readAgentValue( VCARD::ContentLine *cl ) +{ + Agent agent; + bool isIntern = true; + TextValue *v = (TextValue *)cl->value(); + + ParamList params = cl->paramList(); + ParamListIterator it( params ); + for( ; it.current(); ++it ) { + if ( (*it)->name() == "VALUE" && (*it)->value() == "uri" ) + isIntern = false; + } + + if ( isIntern ) { + QString vstr = QString::fromUtf8( v->asString() ); + qDebug("VCardFormatImpl::addAgentValue please verify if replace is correct"); +/*US + vstr.replace( "\\n", "\r\n" ); + vstr.replace( "\\:", ":" ); + vstr.replace( "\\,", "," ); + vstr.replace( "\\;", ";" ); +*/ + vstr.replace( QRegExp("\\n"), "\r\n" ); + vstr.replace( QRegExp("\\:"), ":" ); + vstr.replace( QRegExp("\\,"), "," ); + vstr.replace( QRegExp("\\;"), ";" ); + + Addressee *addr = new Addressee; + readFromString( vstr, *addr ); + agent.setAddressee( addr ); + } else { + agent.setUrl( QString::fromUtf8( v->asString() ) ); + } + + return agent; +} + +void VCardFormatImpl::addPictureValue( VCARD::VCard *vcard, VCARD::EntityType type, const Picture &pic, const Addressee &addr, bool intern ) +{ + ContentLine cl; + cl.setName( EntityTypeToParamName( type ) ); + + if ( pic.isIntern() && pic.data().isNull() ) + return; + + if ( !pic.isIntern() && pic.url().isEmpty() ) + return; + + ParamList params; + if ( pic.isIntern() ) { + QImage img = pic.data(); + if ( intern ) { // only for vCard export we really write the data inline + QByteArray data; + QDataStream s( data, IO_WriteOnly ); + s.setVersion( 4 ); // to produce valid png files + s << img; + cl.setValue( new TextValue( KCodecs::base64Encode( data ) ) ); + + } else { // save picture in cache + QString dir; + if ( type == EntityPhoto ) + dir = "photos"; + if ( type == EntityLogo ) + dir = "logos"; + + img.save( locateLocal( "data", "kabc/" + dir + "/" + addr.uid() ), pic.type().utf8() ); + cl.setValue( new TextValue( "<dummy>" ) ); + } + params.append( new Param( "ENCODING", "b" ) ); + if ( !pic.type().isEmpty() ) + params.append( new Param( "TYPE", pic.type().utf8() ) ); + } else { + + cl.setValue( new TextValue( pic.url().utf8() ) ); + params.append( new Param( "VALUE", "uri" ) ); + } + + cl.setParamList( params ); + vcard->add( cl ); +} + +Picture VCardFormatImpl::readPictureValue( VCARD::ContentLine *cl, VCARD::EntityType type, const Addressee &addr ) +{ + Picture pic; + bool isInline = false; + QString picType; + TextValue *v = (TextValue *)cl->value(); + + ParamList params = cl->paramList(); + ParamListIterator it( params ); + for( ; it.current(); ++it ) { + if ( (*it)->name() == "ENCODING" && (*it)->value() == "b" ) + isInline = true; + if ( (*it)->name() == "TYPE" && !(*it)->value().isEmpty() ) + picType = QString::fromUtf8( (*it)->value() ); + } + + if ( isInline ) { + QImage img; + if ( v->asString() == "<dummy>" ) { // no picture inline stored => picture is in cache + QString dir; + if ( type == EntityPhoto ) + dir = "photos"; + if ( type == EntityLogo ) + dir = "logos"; + + img.load( locateLocal( "data", "kabc/" + dir + "/" + addr.uid() ) ); + } else { + QByteArray data; + KCodecs::base64Decode( v->asString(), data ); + img.loadFromData( data ); + } + pic.setData( img ); + pic.setType( picType ); + } else { + pic.setUrl( QString::fromUtf8( v->asString() ) ); + } + + return pic; +} + +void VCardFormatImpl::addSoundValue( VCARD::VCard *vcard, const Sound &sound, const Addressee &addr, bool intern ) +{ + ContentLine cl; + cl.setName( EntityTypeToParamName( EntitySound ) ); + + if ( sound.isIntern() && sound.data().isNull() ) + return; + + if ( !sound.isIntern() && sound.url().isEmpty() ) + return; + + ParamList params; + if ( sound.isIntern() ) { + QByteArray data = sound.data(); + if ( intern ) { // only for vCard export we really write the data inline + cl.setValue( new TextValue( KCodecs::base64Encode( data ) ) ); + } else { // save sound in cache + QFile file( locateLocal( "data", "kabc/sounds/" + addr.uid() ) ); + if ( file.open( IO_WriteOnly ) ) { + file.writeBlock( data ); + } + cl.setValue( new TextValue( "<dummy>" ) ); + } + params.append( new Param( "ENCODING", "b" ) ); + } else { + cl.setValue( new TextValue( sound.url().utf8() ) ); + params.append( new Param( "VALUE", "uri" ) ); + } + + cl.setParamList( params ); + vcard->add( cl ); +} + +Sound VCardFormatImpl::readSoundValue( VCARD::ContentLine *cl, const Addressee &addr ) +{ + Sound sound; + bool isInline = false; + TextValue *v = (TextValue *)cl->value(); + + ParamList params = cl->paramList(); + ParamListIterator it( params ); + for( ; it.current(); ++it ) { + if ( (*it)->name() == "ENCODING" && (*it)->value() == "b" ) + isInline = true; + } + + if ( isInline ) { + QByteArray data; + if ( v->asString() == "<dummy>" ) { // no sound inline stored => sound is in cache + QFile file( locateLocal( "data", "kabc/sounds/" + addr.uid() ) ); + if ( file.open( IO_ReadOnly ) ) { + data = file.readAll(); + file.close(); + } + } else { + KCodecs::base64Decode( v->asString(), data ); + } + sound.setData( data ); + } else { + sound.setUrl( QString::fromUtf8( v->asString() ) ); + } + + return sound; +} + +bool VCardFormatImpl::readFromString( const QString &vcard, Addressee &addressee ) +{ + VCardEntity e( vcard.utf8() ); + VCardListIterator it( e.cardList() ); + + if ( it.current() ) { + VCard v(*it.current()); + loadAddressee( addressee, v ); + return true; + } + + return false; +} + +bool VCardFormatImpl::writeToString( const Addressee &addressee, QString &vcard ) +{ + VCardEntity vcards; + VCardList vcardlist; + vcardlist.setAutoDelete( true ); + + VCard *v = new VCard; + + saveAddressee( addressee, v, true ); + + vcardlist.append( v ); + vcards.setCardList( vcardlist ); + vcard = QString::fromUtf8( vcards.asString() ); + + return true; +} diff --git a/kabc/vcardformatimpl.h b/kabc/vcardformatimpl.h new file mode 100644 index 0000000..2dd68d9 --- a/dev/null +++ b/kabc/vcardformatimpl.h @@ -0,0 +1,112 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KABC_VCARDFORMATIMPL_H +#define KABC_VCARDFORMATIMPL_H + +#include <qstring.h> +#include <qfile.h> + +#include "address.h" +#include "addressee.h" + +#include <VCard.h> + +namespace KABC { + +class AddressBook; + +/** + @short Implementation of vCard backend for address book. + + This class implements reading and writing of address book information using + the vCard format. It requires the vCard lib from kdepim. +*/ +class VCardFormatImpl +{ + public: + bool load( Addressee &, QFile *file ); + bool loadAll( AddressBook *, Resource *, QFile *file ); + void save( const Addressee &, QFile *file ); + void saveAll( AddressBook *, Resource *, QFile *file ); + + bool readFromString( const QString &vcard, Addressee &addr ); + bool writeToString( const Addressee &addressee, QString &vcard ); + + protected: + bool loadAddressee( Addressee &, VCARD::VCard & ); + void saveAddressee( const Addressee &, VCARD::VCard *, bool intern ); + + void addTextValue (VCARD::VCard *, VCARD::EntityType, const QString & ); + QString readTextValue( VCARD::ContentLine * ); + + void addDateValue( VCARD::VCard *, VCARD::EntityType, const QDate & ); + QDate readDateValue( VCARD::ContentLine * ); + + void addDateTimeValue( VCARD::VCard *, VCARD::EntityType, const QDateTime & ); + QDateTime readDateTimeValue( VCARD::ContentLine * ); + + void addAddressValue( VCARD::VCard *, const Address & ); + Address readAddressValue( VCARD::ContentLine * ); + + void addLabelValue( VCARD::VCard *, const Address & ); + + void addTelephoneValue( VCARD::VCard *, const PhoneNumber & ); + PhoneNumber readTelephoneValue( VCARD::ContentLine * ); + + void addNValue( VCARD::VCard *, const Addressee & ); + void readNValue( VCARD::ContentLine *, Addressee & ); + + void addCustomValue( VCARD::VCard *, const QString & ); + + void addAddressParam( VCARD::ContentLine *, int ); + int readAddressParam( VCARD::ContentLine * ); + + void addGeoValue( VCARD::VCard *, const Geo & ); + Geo readGeoValue( VCARD::ContentLine * ); + + void addUTCValue( VCARD::VCard *, const TimeZone & ); + TimeZone readUTCValue( VCARD::ContentLine * ); + + void addClassValue( VCARD::VCard *, const Secrecy & ); + Secrecy readClassValue( VCARD::ContentLine * ); + + void addKeyValue( VCARD::VCard *, const Key & ); + Key readKeyValue( VCARD::ContentLine * ); + + void addPictureValue( VCARD::VCard *, VCARD::EntityType, const Picture &, const Addressee &, bool ); + Picture readPictureValue( VCARD::ContentLine *, VCARD::EntityType, const Addressee &addr ); + + void addSoundValue( VCARD::VCard *, const Sound &, const Addressee &, bool ); + Sound readSoundValue( VCARD::ContentLine *, const Addressee &addr ); + + void addAgentValue( VCARD::VCard *, const Agent & ); + Agent readAgentValue( VCARD::ContentLine * ); +}; + +} +#endif diff --git a/kabc/vcardformatplugin.cpp b/kabc/vcardformatplugin.cpp new file mode 100644 index 0000000..3cba59a --- a/dev/null +++ b/kabc/vcardformatplugin.cpp @@ -0,0 +1,66 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "vcardformatplugin.h" +#include "vcardformatimpl.h" + +using namespace KABC; + +VCardFormatPlugin::VCardFormatPlugin() +{ + mImpl = new VCardFormatImpl; +} + +VCardFormatPlugin::~VCardFormatPlugin() +{ + delete mImpl; +} + +bool VCardFormatPlugin::load( Addressee &addressee, QFile *file ) +{ + return mImpl->load( addressee, file ); +} + +bool VCardFormatPlugin::loadAll( AddressBook *addressBook, Resource *resource, QFile *file ) +{ + return mImpl->loadAll( addressBook, resource, file ); +} + +void VCardFormatPlugin::save( const Addressee &addressee, QFile *file ) +{ + mImpl->save( addressee, file ); +} + +void VCardFormatPlugin::saveAll( AddressBook *addressBook, Resource *resource, QFile *file ) +{ + mImpl->saveAll( addressBook, resource, file ); +} + +bool VCardFormatPlugin::checkFormat( QFile *file ) const +{ + QString line; + + file->readLine( line, 1024 ); + line = line.stripWhiteSpace(); + if ( line == "BEGIN:VCARD" ) + return true; + else + return false; +} diff --git a/kabc/vcardformatplugin.h b/kabc/vcardformatplugin.h new file mode 100644 index 0000000..dc2b45d --- a/dev/null +++ b/kabc/vcardformatplugin.h @@ -0,0 +1,56 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KABC_VCARDFORMATPLUGIN_H +#define KABC_VCARDFORMATPLUGIN_H + +#include "formatplugin.h" + +namespace KABC { + +class AddressBook; +class Addressee; +class VCardFormatImpl; + +/** + @short Interface of vCard backend for address book. + + This class implements the file format interface of address book entries for + the vCard format. +*/ +class VCardFormatPlugin : public FormatPlugin +{ + public: + VCardFormatPlugin(); + virtual ~VCardFormatPlugin(); + + bool load( Addressee &, QFile *file ); + bool loadAll( AddressBook *, Resource *, QFile *file ); + void save( const Addressee &, QFile *file ); + void saveAll( AddressBook *, Resource *, QFile *file ); + + bool checkFormat( QFile *file ) const; + + private: + VCardFormatImpl *mImpl; +}; + +} +#endif diff --git a/kabc/vcardparser/vcard.cpp b/kabc/vcardparser/vcard.cpp new file mode 100644 index 0000000..da97ec2 --- a/dev/null +++ b/kabc/vcardparser/vcard.cpp @@ -0,0 +1,144 @@ +/* + This file is part of libkabc. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "vcard.h" + +using namespace KABC; + +VCard::VCard() + : mLineMap( 0 ) +{ +} + +VCard::VCard( const VCard& vcard ) + : mLineMap( 0 ) +{ + if ( vcard.mLineMap ) { + if ( !mLineMap ) + mLineMap = new QMap<QString, QValueList<VCardLine> >; + + *mLineMap = *(vcard.mLineMap); + } else { + delete mLineMap; + mLineMap = 0; + } +} + +VCard::~VCard() +{ + delete mLineMap; + mLineMap = 0; +} + +VCard& VCard::operator=( const VCard& vcard ) +{ + if ( &vcard == this ) + return *this; + + if ( vcard.mLineMap ) { + if ( !mLineMap ) + mLineMap = new QMap<QString, QValueList<VCardLine> >; + + *mLineMap = *(vcard.mLineMap); + } else { + delete mLineMap; + mLineMap = 0; + } + + return *this; +} + +void VCard::clear() +{ + if ( mLineMap ) + mLineMap->clear(); +} + +QStringList VCard::identifiers() const +{ + if ( !mLineMap ) + return QStringList(); + else { +//US method QMap::keys() not available yet. SO collect the data manually +//US return mLineMap->keys(); + + QStringList result; + + QMap< QString, VCardLine::List >::ConstIterator it; + for( it = mLineMap->begin(); it != mLineMap->end(); ++it ) { + result << it.key().latin1(); + } + return result; + } +} + +void VCard::addLine( const VCardLine& line ) +{ + if ( !mLineMap ) + mLineMap = new QMap<QString, QValueList<VCardLine> >; + + (*mLineMap)[ line.identifier() ].append( line ); +} + +VCardLine::List VCard::lines( const QString& identifier ) +{ + if ( !mLineMap ) + return VCardLine::List(); + else + return (*mLineMap)[ identifier ]; +} + +VCardLine VCard::line( const QString& identifier ) +{ + if ( !mLineMap ) + return VCardLine(); + else + return (*mLineMap)[ identifier ][ 0 ]; +} + +void VCard::setVersion( Version version ) +{ + if ( !mLineMap ) + mLineMap = new QMap<QString, QValueList<VCardLine> >; + else { +//US mLineMap->erase( "VERSION" ); + mLineMap->remove( "VERSION" ); + } + VCardLine line; + line.setIdentifier( "VERSION" ); + if ( version == v2_1 ) + line.setIdentifier( "2.1" ); + if ( version == v3_0 ) + line.setIdentifier( "3.0" ); + + (*mLineMap)[ "VERSION" ].append( line ); +} + +VCard::Version VCard::version() const +{ + if ( !mLineMap ) + return v3_0; + + VCardLine line = (*mLineMap)[ "VERSION" ][ 0 ]; + if ( line.value() == "2.1" ) + return v2_1; + else + return v3_0; +} diff --git a/kabc/vcardparser/vcard.h b/kabc/vcardparser/vcard.h new file mode 100644 index 0000000..ce672b5 --- a/dev/null +++ b/kabc/vcardparser/vcard.h @@ -0,0 +1,90 @@ +/* + This file is part of libkabc. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef VCARD_H +#define VCARD_H + +#include "vcardline.h" +#include <qmap.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +namespace KABC { + +class VCard +{ + public: + typedef QValueList<VCard> List; + + enum Version { v2_1, v3_0 }; + + VCard(); + VCard( const VCard& ); + + ~VCard(); + + VCard& operator=( const VCard& ); + + /** + * Removes all lines from the vCard. + */ + void clear(); + + /** + * Returns a list of all identifiers that exists in the + * vCard. + */ + QStringList identifiers() const; + + /** + * Adds a VCardLine to the VCard + */ + void addLine( const VCardLine& line ); + + /** + * Returns all lines of the vcard with a special identifier. + */ + VCardLine::List lines( const QString& identifier ); + + /** + * Returns only the first line of the vcard with a special identifier. + */ + VCardLine line( const QString& identifier ); + + /** + * Set the version of the vCard. + */ + void setVersion( Version version ); + + /** + * Returns the version of this vCard. + */ + Version version() const; + + private: + QMap< QString, VCardLine::List > *mLineMap; + + class VCardPrivate; + VCardPrivate *d; +}; + +} + +#endif diff --git a/kabc/vcardparser/vcardline.cpp b/kabc/vcardparser/vcardline.cpp new file mode 100644 index 0000000..84638f8 --- a/dev/null +++ b/kabc/vcardparser/vcardline.cpp @@ -0,0 +1,148 @@ +/* + This file is part of libkabc. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "vcardline.h" + +using namespace KABC; + +VCardLine::VCardLine() + : mParamMap( 0 ) +{ +} + +VCardLine::VCardLine( const QString &identifier ) + : mParamMap( 0 ) +{ + mIdentifier = identifier; +} + +VCardLine::VCardLine( const QString &identifier, const QVariant &value ) + : mParamMap( 0 ) +{ + mIdentifier = identifier; + mValue = value; +} + +VCardLine::VCardLine( const VCardLine& line ) + : mParamMap( 0 ) +{ + if ( line.mParamMap ) { + if ( !mParamMap ) + mParamMap = new QMap<QString, QStringList>; + + *mParamMap = *(line.mParamMap); + } else { + delete mParamMap; + mParamMap = 0; + } + + mValue = line.mValue; + mIdentifier = line.mIdentifier; +} + +VCardLine::~VCardLine() +{ + delete mParamMap; + mParamMap = 0; +} + +VCardLine& VCardLine::operator=( const VCardLine& line ) +{ + if ( &line == this ) + return *this; + + if ( line.mParamMap ) { + if ( !mParamMap ) + mParamMap = new QMap<QString, QStringList>; + + *mParamMap = *(line.mParamMap); + } else { + delete mParamMap; + mParamMap = 0; + } + + mValue = line.mValue; + mIdentifier = line.mIdentifier; + + return *this; +} + +void VCardLine::setIdentifier( const QString& identifier ) +{ + mIdentifier = identifier; +} + +QString VCardLine::identifier() const +{ + return mIdentifier; +} +void VCardLine::setValue( const QVariant& value ) +{ + mValue = value; +} + +QVariant VCardLine::value() const +{ + return mValue; +} + +QStringList VCardLine::parameterList() const +{ + if ( !mParamMap ) + return QStringList(); + else { +//US method QMap::keys() not available yet. SO collect the data manually +//US return mParamMap->keys(); + + QStringList result; + + QMap<QString, QStringList>::ConstIterator it; + for( it = mParamMap->begin(); it != mParamMap->end(); ++it ) { + result << it.key().latin1(); + } + return result; + } +} + +void VCardLine::addParameter( const QString& param, const QString& value ) +{ + if ( !mParamMap ) + mParamMap = new QMap<QString, QStringList>; + + QStringList &list = (*mParamMap)[ param ]; + if ( list.find( value ) == list.end() ) // not included yet + list.append( value ); +} + +QStringList VCardLine::parameters( const QString& param ) const +{ + if ( !mParamMap ) + return QStringList(); + else + return (*mParamMap)[ param ]; +} + +QString VCardLine::parameter( const QString& param ) const +{ + if ( !mParamMap ) + return QString::null; + else + return (*mParamMap)[ param ][ 0 ]; +} diff --git a/kabc/vcardparser/vcardline.h b/kabc/vcardparser/vcardline.h new file mode 100644 index 0000000..78b61f8 --- a/dev/null +++ b/kabc/vcardparser/vcardline.h @@ -0,0 +1,99 @@ +/* + This file is part of libkabc. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef VCARDLINE_H +#define VCARDLINE_H + +#include <qstringlist.h> +#include <qvaluelist.h> +#include <qvariant.h> +#include <qmap.h> +#include <qstring.h> + +namespace KABC { + +class VCardLine +{ + public: + typedef QValueList<VCardLine> List; + + VCardLine(); + VCardLine( const QString &identifier ); + VCardLine( const QString &identifier, const QVariant &value ); + VCardLine( const VCardLine& ); + + ~VCardLine(); + + VCardLine& operator=( const VCardLine& ); + + /** + * Sets the identifier of this line e.g. UID, FN, CLASS + */ + void setIdentifier( const QString& identifier ); + + /** + * Returns the identifier of this line. + */ + QString identifier() const; + + /** + * Sets the value of of this line. + */ + void setValue( const QVariant& value ); + + /** + * Returns the value of this line. + */ + QVariant value() const; + + /** + * Returns all parameters. + */ + QStringList parameterList() const; + + /** + * Add a new parameter to the line. + */ + void addParameter( const QString& param, const QString& value ); + + /** + * Returns the values of a special parameter. + * You can get a list of all parameters with @ref paramList(). + */ + QStringList parameters( const QString& param ) const; + + /** + * Returns only the first value of a special parameter. + * You can get a list of all parameters with @ref paramList(). + */ + QString parameter( const QString& param ) const; + + private: + QMap< QString, QStringList > *mParamMap; + QString mIdentifier; + QVariant mValue; + + class VCardLinePrivate; + VCardLinePrivate *d; +}; + +} + +#endif diff --git a/kabc/vcardparser/vcardparser.cpp b/kabc/vcardparser/vcardparser.cpp new file mode 100644 index 0000000..9ea084d --- a/dev/null +++ b/kabc/vcardparser/vcardparser.cpp @@ -0,0 +1,233 @@ +/* + This file is part of libkabc. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qregexp.h> + +#include <kmdcodec.h> + +#include "vcardparser.h" + +#define FOLD_WIDTH 75 + +using namespace KABC; + +VCardParser::VCardParser() +{ +} + +VCardParser::~VCardParser() +{ +} + +VCard::List VCardParser::parseVCards( const QString& text ) +{ + VCard currentVCard; + VCard::List vCardList; + QString currentLine; + + QStringList lines = QStringList::split( QRegExp( "[\x0d\x0a]" ), text ); + QStringList::Iterator it; + + bool inVCard = false; + for ( it = lines.begin(); it != lines.end(); ++it ) { + + if ( (*it).isEmpty() ) // empty line + continue; + + if ( (*it)[ 0 ] == ' ' || (*it)[ 0 ] == '\t' ) { // folded line => append to previous + currentLine += (*it).remove( 0, 1 ); + continue; + } else { + if ( inVCard && !currentLine.isEmpty() ) { // now parse the line + int colon = currentLine.find( ':' ); + if ( colon == -1 ) { // invalid line + currentLine = (*it); + continue; + } + + VCardLine vCardLine; + QString key = currentLine.left( colon ).stripWhiteSpace(); + QString value = currentLine.mid( colon + 1 ); + + QStringList params = QStringList::split( ';', key ); + vCardLine.setIdentifier( params[0] ); + if ( params.count() > 1 ) { // find all parameters + for ( uint i = 1; i < params.count(); ++i ) { + QStringList pair = QStringList::split( '=', params[i] ); +//US if ( pair.size() == 1 ) { + if ( pair.count() == 1 ) { + pair.prepend( "type" ); + } + if ( pair[1].contains( ',' ) ) { // parameter in type=x,y,z format + QStringList args = QStringList::split( ',', pair[ 1 ] ); + for ( uint j = 0; j < args.count(); ++j ) + vCardLine.addParameter( pair[0].lower(), args[j] ); + } else + vCardLine.addParameter( pair[0].lower(), pair[1] ); + } + } + + params = vCardLine.parameterList(); + if ( params.contains( "encoding" ) ) { // have to decode the data +#if 0 + QByteArray input, output; + input = value.local8Bit(); + if ( vCardLine.parameter( "encoding" ).lower() == "b" ) + KCodecs::base64Decode( input, output ); + else if ( vCardLine.parameter( "encoding" ).lower() == "quoted-printable" ) + KCodecs::quotedPrintableDecode( input, output ); + + //qDebug("VCardParser::parseVCards has to be verified"); + //US I am not sure if this is correct + //US vCardLine.setValue( output ); + QCString cs(output); + qDebug("len1 %d len2 %d ",input.size(), output.size( )); +#endif + QCString cs = value.local8Bit(); + qDebug("****************************************** "); + qDebug("************* WARNING ******************** "); + qDebug("****************************************** "); + qDebug("Make sure, the decoding is done after"); + qDebug("QVariant conversion!"); + qDebug("Insert Line DECODING OKAY, where this is implemented"); + // use for decoding the above code! + vCardLine.setValue( cs ); + } else { + + //qDebug("VCardParser::parseVCards has to be verified"); +//US vCardLine.setValue( value.replace( "\\n", "\n" ) ); + vCardLine.setValue( value.replace( QRegExp("\\n"), "\n" ) ); + } + + currentVCard.addLine( vCardLine ); + } + // we do not save the start and end tag as vcardline + if ( (*it).lower().startsWith( "begin:vcard" ) ) { + inVCard = true; + //qDebug("VCardParser::parseVCards has to be verified"); +//US currentLine.setLength( 0 ); + currentLine = ""; + currentVCard.clear(); // flush vcard + continue; + } + + if ( (*it).lower().startsWith( "end:vcard" ) ) { + inVCard = false; + vCardList.append( currentVCard ); + //qDebug("VCardParser::parseVCards has to be verified"); +//US currentLine.setLength( 0 ); + currentLine = ""; + currentVCard.clear(); // flush vcard + continue; + } + + currentLine = (*it); + } + } + + return vCardList; +} + +QString VCardParser::createVCards( const VCard::List& list ) +{ + QString text; + QString textLine; + QString encodingType; + QStringList idents; + QStringList params; + QStringList values; + QStringList::ConstIterator identIt; + QStringList::Iterator paramIt; + QStringList::Iterator valueIt; + + VCardLine::List lines; + VCardLine::List::Iterator lineIt; + VCard::List::ConstIterator cardIt; + + bool hasEncoding; + + + // iterate over the cards + for ( cardIt = list.begin(); cardIt != list.end(); ++cardIt ) { + text.append( "BEGIN:VCARD\r\n" ); + + idents = (*cardIt).identifiers(); + for ( identIt = idents.begin(); identIt != idents.end(); ++identIt ) { + VCard card = (*cardIt); + lines = card.lines( (*identIt) ); + + // iterate over the lines + for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) { + if ( !(*lineIt).value().asString().isEmpty() ) { + textLine = (*lineIt).identifier(); + + params = (*lineIt).parameterList(); + hasEncoding = false; + if ( params.count() > 0 ) { // we have parameters + for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) { + if ( (*paramIt) == "encoding" ) { + hasEncoding = true; + encodingType = (*lineIt).parameter( "encoding" ).lower(); + } + + values = (*lineIt).parameters( *paramIt ); + for ( valueIt = values.begin(); valueIt != values.end(); ++valueIt ) { + textLine.append( ";" + (*paramIt).upper() ); + if ( !(*valueIt).isEmpty() ) + textLine.append( "=" + (*valueIt) ); + } + } + } + + if ( hasEncoding ) { // have to encode the data + QByteArray input, output; + + qDebug("VCardParser::createVCards has to be verified"); +//US input = (*lineIt).value().toByteArray(); + +//US I am not sure if this is correct + QCString cs ((*lineIt).value().toCString()); + input = cs; + + if ( encodingType == "b" ) + KCodecs::base64Encode( input, output ); + else if ( encodingType == "quoted-printable" ) + KCodecs::quotedPrintableEncode( input, output ); + textLine.append( ":" + QString( output ) ); + } else { + qDebug("VCardParser::createVCards has to be verified"); +//US textLine.append( ":" + (*lineIt).value().asString().replace( "\n", "\\n" ) ); + textLine.append( ":" + (*lineIt).value().asString().replace( QRegExp("\n"), "\\n" ) ); + } + if ( textLine.length() > FOLD_WIDTH ) { // we have to fold the line + for ( uint i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i ) + text.append( ( i == 0 ? "" : " " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) + "\r\n" ); + } else + text.append( textLine + "\r\n" ); + } + } + } + + text.append( "END:VCARD\r\n" ); + text.append( "\r\n" ); + } + + return text; +} diff --git a/kabc/vcardparser/vcardparser.h b/kabc/vcardparser/vcardparser.h new file mode 100644 index 0000000..ae185ef --- a/dev/null +++ b/kabc/vcardparser/vcardparser.h @@ -0,0 +1,40 @@ +/* + This file is part of libkabc. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef VCARDPARSER_H +#define VCARDPARSER_H + +#include "vcard.h" + +namespace KABC { + +class VCardParser +{ + public: + VCardParser(); + ~VCardParser(); + + static VCard::List parseVCards( const QString& text ); + static QString createVCards( const VCard::List& list ); +}; + +} + +#endif diff --git a/kabc/vcardparser/vcardtool.cpp b/kabc/vcardparser/vcardtool.cpp new file mode 100644 index 0000000..01c5b3e --- a/dev/null +++ b/kabc/vcardparser/vcardtool.cpp @@ -0,0 +1,883 @@ +/* + This file is part of libkabc. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdatastream.h> +#include <qstring.h> +#include <qregexp.h> +#include <kmdcodec.h> + +#include "agent.h" +#include "key.h" +#include "picture.h" +#include "secrecy.h" +#include "sound.h" + +#include "vcardtool.h" + +using namespace KABC; + +VCardTool::VCardTool() +{ + mAddressTypeMap.insert( "dom", Address::Dom ); + mAddressTypeMap.insert( "intl", Address::Intl ); + mAddressTypeMap.insert( "postal", Address::Postal ); + mAddressTypeMap.insert( "parcel", Address::Parcel ); + mAddressTypeMap.insert( "home", Address::Home ); + mAddressTypeMap.insert( "work", Address::Work ); + mAddressTypeMap.insert( "pref", Address::Pref ); + + mPhoneTypeMap.insert( "HOME", PhoneNumber::Home ); + mPhoneTypeMap.insert( "WORK", PhoneNumber::Work ); + mPhoneTypeMap.insert( "MSG", PhoneNumber::Msg ); + mPhoneTypeMap.insert( "PREF", PhoneNumber::Pref ); + mPhoneTypeMap.insert( "VOICE", PhoneNumber::Voice ); + mPhoneTypeMap.insert( "FAX", PhoneNumber::Fax ); + mPhoneTypeMap.insert( "CELL", PhoneNumber::Cell ); + mPhoneTypeMap.insert( "VIDEO", PhoneNumber::Video ); + mPhoneTypeMap.insert( "BBS", PhoneNumber::Bbs ); + mPhoneTypeMap.insert( "MODEM", PhoneNumber::Modem ); + mPhoneTypeMap.insert( "CAR", PhoneNumber::Car ); + mPhoneTypeMap.insert( "ISDN", PhoneNumber::Isdn ); + mPhoneTypeMap.insert( "PCS", PhoneNumber::Pcs ); + mPhoneTypeMap.insert( "PAGER", PhoneNumber::Pager ); +} + +VCardTool::~VCardTool() +{ +} + +QString VCardTool::createVCards( Addressee::List list, VCard::Version version ) +{ + VCard::List vCardList; + + Addressee::List::Iterator addrIt; + for ( addrIt = list.begin(); addrIt != list.end(); ++addrIt ) { + VCard card; + QStringList::ConstIterator strIt; + + // ADR + LABEL + Address::List addresses = (*addrIt).addresses(); + for ( Address::List::Iterator it = addresses.begin(); it != addresses.end(); ++it ) { + QStringList address; + +/*US + address.append( (*it).postOfficeBox().replace( ';', "\\;" ) ); + address.append( (*it).extended().replace( ';', "\\;" ) ); + address.append( (*it).street().replace( ';', "\\;" ) ); + address.append( (*it).locality().replace( ';', "\\;" ) ); + address.append( (*it).region().replace( ';', "\\;" ) ); + address.append( (*it).postalCode().replace( ';', "\\;" ) ); + address.append( (*it).country().replace( ';', "\\;" ) ); +*/ +//US using the old implementation instead + //qDebug("VCardTool::createVCards has to be verified"); + address.append( (*it).postOfficeBox().replace( QRegExp(";"), "\\;" ) ); + address.append( (*it).extended().replace( QRegExp(";"), "\\;" ) ); + address.append( (*it).street().replace( QRegExp(";"), "\\;" ) ); + address.append( (*it).locality().replace( QRegExp(";"), "\\;" ) ); + address.append( (*it).region().replace( QRegExp(";"), "\\;" ) ); + address.append( (*it).postalCode().replace( QRegExp(";"), "\\;" ) ); + address.append( (*it).country().replace( QRegExp(";"), "\\;" ) ); + + VCardLine adrLine( "ADR", address.join( ";" ) ); + VCardLine labelLine( "LABEL", (*it).label() ); + + bool hasLabel = !(*it).label().isEmpty(); + QMap<QString, int>::Iterator typeIt; + for ( typeIt = mAddressTypeMap.begin(); typeIt != mAddressTypeMap.end(); ++typeIt ) { + if ( typeIt.data() & (*it).type() ) { + adrLine.addParameter( "TYPE", typeIt.key() ); + if ( hasLabel ) + labelLine.addParameter( "TYPE", typeIt.key() ); + } + } + + card.addLine( adrLine ); + if ( hasLabel ) + card.addLine( labelLine ); + } + + // AGENT + card.addLine( createAgent( version, (*addrIt).agent() ) ); + + // BDAY + card.addLine( VCardLine( "BDAY", createDateTime( (*addrIt).birthday() ) ) ); + + // CATEGORIES + if ( version == VCard::v3_0 ) { + QStringList categories = (*addrIt).categories(); + QStringList::Iterator catIt; + for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) + { +//US using the old implementation instead + // qDebug("VCardTool::createVCards has to be verified"); +//US (*catIt).replace( ',', "\\," ); + (*catIt).replace( QRegExp(","), "\\," ); + } + card.addLine( VCardLine( "CATEGORIES", categories.join( "," ) ) ); + } + + // CLASS + if ( version == VCard::v3_0 ) { + card.addLine( createSecrecy( (*addrIt).secrecy() ) ); + } + + // EMAIL + QStringList emails = (*addrIt).emails(); + bool pref = true; + for ( strIt = emails.begin(); strIt != emails.end(); ++strIt ) { + VCardLine line( "EMAIL", *strIt ); + if ( pref == true ) { + line.addParameter( "TYPE", "PREF" ); + pref = false; + } + card.addLine( line ); + } + + // FN + card.addLine( VCardLine( "FN", (*addrIt).formattedName() ) ); + + // GEO + Geo geo = (*addrIt).geo(); + if ( geo.isValid() ) { + QString str; + str.sprintf( "%.6f;%.6f", geo.latitude(), geo.longitude() ); + card.addLine( VCardLine( "GEO", str ) ); + } + + // KEY + Key::List keys = (*addrIt).keys(); + Key::List::ConstIterator keyIt; + for ( keyIt = keys.begin(); keyIt != keys.end(); ++keyIt ) + card.addLine( createKey( *keyIt ) ); + + // LOGO + card.addLine( createPicture( "LOGO", (*addrIt).logo() ) ); + + // MAILER + card.addLine( VCardLine( "MAILER", (*addrIt).mailer() ) ); + + // N + QStringList name; +//US using the old implementation instead + //qDebug("VCardTool::createVCards has to be verified"); +/*US + name.append( (*addrIt).familyName().replace( ';', "\\;" ) ); + name.append( (*addrIt).givenName().replace( ';', "\\;" ) ); + name.append( (*addrIt).additionalName().replace( ';', "\\;" ) ); + name.append( (*addrIt).prefix().replace( ';', "\\;" ) ); + name.append( (*addrIt).suffix().replace( ';', "\\;" ) ); +*/ + name.append( (*addrIt).familyName().replace( QRegExp(";"), "\\;" ) ); + name.append( (*addrIt).givenName().replace( QRegExp(";"), "\\;" ) ); + name.append( (*addrIt).additionalName().replace( QRegExp(";"), "\\;" ) ); + name.append( (*addrIt).prefix().replace( QRegExp(";"), "\\;" ) ); + name.append( (*addrIt).suffix().replace( QRegExp(";"), "\\;" ) ); + + if ( !name.join( "" ).isEmpty() ) + card.addLine( VCardLine( "N", name.join( ";" ) ) ); + + // NICKNAME + if ( version == VCard::v3_0 ) + card.addLine( VCardLine( "NICKNAME", (*addrIt).nickName() ) ); + + // NOTE + card.addLine( VCardLine( "NOTE", (*addrIt).note() ) ); + + // ORG + card.addLine( VCardLine( "ORG", (*addrIt).organization() ) ); + + // PHOTO + card.addLine( createPicture( "PHOTO", (*addrIt).photo() ) ); + + // PROID + if ( version == VCard::v3_0 ) + card.addLine( VCardLine( "PRODID", (*addrIt).productId() ) ); + + // REV + card.addLine( VCardLine( "REV", createDateTime( (*addrIt).revision() ) ) ); + + // ROLE + card.addLine( VCardLine( "ROLE", (*addrIt).role() ) ); + + // SORT-STRING + if ( version == VCard::v3_0 ) + card.addLine( VCardLine( "SORT-STRING", (*addrIt).sortString() ) ); + + // SOUND + card.addLine( createSound( (*addrIt).sound() ) ); + + // TEL + PhoneNumber::List phoneNumbers = (*addrIt).phoneNumbers(); + PhoneNumber::List::ConstIterator phoneIt; + for ( phoneIt = phoneNumbers.begin(); phoneIt != phoneNumbers.end(); ++phoneIt ) { + VCardLine line( "TEL", (*phoneIt).number() ); + + QMap<QString, int>::Iterator typeIt; + for ( typeIt = mPhoneTypeMap.begin(); typeIt != mPhoneTypeMap.end(); ++typeIt ) { + if ( typeIt.data() & (*phoneIt).type() ) + line.addParameter( "TYPE", typeIt.key() ); + } + + card.addLine( line ); + } + + // TITLE + card.addLine( VCardLine( "TITLE", (*addrIt).title() ) ); + + // TZ + TimeZone timeZone = (*addrIt).timeZone(); + if ( timeZone.isValid() ) { + QString str; + + int neg = 1; + if ( timeZone.offset() < 0 ) + neg = -1; + + str.sprintf( "%c%02d:%02d", ( timeZone.offset() >= 0 ? '+' : '-' ), + ( timeZone.offset() / 60 ) * neg, + ( timeZone.offset() % 60 ) * neg ); + + card.addLine( VCardLine( "TZ", str ) ); + } + + // UID + card.addLine( VCardLine( "UID", (*addrIt).uid() ) ); + + // URL + card.addLine( VCardLine( "URL", (*addrIt).url().url() ) ); + + // VERSION + if ( version == VCard::v2_1 ) + card.addLine( VCardLine( "VERSION", "2.1" ) ); + if ( version == VCard::v3_0 ) + card.addLine( VCardLine( "VERSION", "3.0" ) ); + + // X- + QStringList customs = (*addrIt).customs(); + for ( strIt = customs.begin(); strIt != customs.end(); ++strIt ) { + QString identifier = "X-" + (*strIt).left( (*strIt).find( ":" ) ); + QString value = (*strIt).mid( (*strIt).find( ":" ) + 1 ); + if ( value.isEmpty() ) + continue; + + card.addLine( VCardLine( identifier, value ) ); + } + + vCardList.append( card ); + } + + return VCardParser::createVCards( vCardList ); +} + +Addressee::List VCardTool::parseVCards( const QString& vcard ) +{ + QChar semicolonSep( ';' ); + QChar commaSep( ',' ); + QString identifier; + + Addressee::List addrList; + VCard::List vCardList = VCardParser::parseVCards( vcard ); + VCard::List::Iterator cardIt; + for ( cardIt = vCardList.begin(); cardIt != vCardList.end(); ++cardIt ) { + Addressee addr; + QStringList idents = (*cardIt).identifiers(); + QStringList::ConstIterator identIt; + for ( identIt = idents.begin(); identIt != idents.end(); ++identIt ) { + VCard card = (*cardIt); + VCardLine::List lines = card.lines( (*identIt) ); + VCardLine::List::Iterator lineIt; + + // iterate over the lines + for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) { + QStringList params = (*lineIt).parameterList(); + + identifier = (*lineIt).identifier().lower(); + // ADR + if ( identifier == "adr" ) { + Address address; + QStringList addrParts = splitString( semicolonSep, (*lineIt).value().asString() ); + if ( addrParts.count() > 0 ) + address.setPostOfficeBox( addrParts[ 0 ] ); + if ( addrParts.count() > 1 ) + address.setExtended( addrParts[ 1 ] ); + if ( addrParts.count() > 2 ) + address.setStreet( addrParts[ 2 ].replace ( QRegExp("\\\\n") , "\n") ); + if ( addrParts.count() > 3 ) + address.setLocality( addrParts[ 3 ] ); + if ( addrParts.count() > 4 ) + address.setRegion( addrParts[ 4 ] ); + if ( addrParts.count() > 5 ) + address.setPostalCode( addrParts[ 5 ] ); + if ( addrParts.count() > 6 ) + address.setCountry( addrParts[ 6 ] ); + + int type = 0; + + QStringList types = (*lineIt).parameters( "type" ); + for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) + type += mAddressTypeMap[ (*it).lower() ]; + + if ( !type ) + type = Address::Home; // default + + address.setType( type ); + addr.insertAddress( address ); + } + + // AGENT + if ( identifier == "agent" ) + addr.setAgent( parseAgent( *lineIt ) ); + + // BDAY + if ( identifier == "bday" ) + addr.setBirthday( parseDateTime( (*lineIt).value().asString() ) ); + + // CATEGORIES + if ( identifier == "categories" ) { + QStringList categories = splitString( commaSep, (*lineIt).value().asString() ); + addr.setCategories( categories ); + } + + // CLASS + if ( identifier == "class" ) + addr.setSecrecy( parseSecrecy( *lineIt ) ); + + // EMAIL + if ( identifier == "email" ) { + QStringList types = (*lineIt).parameters( "type" ); + addr.insertEmail( (*lineIt).value().asString(), types.contains( "PREF" ) ); + } + + // FN + if ( identifier == "fn" ) + addr.setFormattedName( (*lineIt).value().asString() ); + + // GEO + if ( identifier == "geo" ) { + Geo geo; + + QStringList geoParts = QStringList::split( ';', (*lineIt).value().asString(), true ); + geo.setLatitude( geoParts[ 0 ].toFloat() ); + geo.setLongitude( geoParts[ 1 ].toFloat() ); + + addr.setGeo( geo ); + } + + // KEY + if ( identifier == "key" ) + addr.insertKey( parseKey( *lineIt ) ); + + // LABEL + if ( identifier == "label" ) { + int type = 0; + + QStringList types = (*lineIt).parameters( "type" ); + for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) + type += mAddressTypeMap[ (*it).lower() ]; + + if ( !type ) + type = Address::Home; + + KABC::Address::List addressList = addr.addresses(); + KABC::Address::List::Iterator it; + for ( it = addressList.begin(); it != addressList.end(); ++it ) { + if ( (*it).type() == type ) { + (*it).setLabel( (*lineIt).value().asString() ); + addr.insertAddress( *it ); + } + } + } + + // LOGO + if ( identifier == "logo" ) + addr.setLogo( parsePicture( *lineIt ) ); + + // MAILER + if ( identifier == "mailer" ) + addr.setMailer( (*lineIt).value().asString() ); + + // N + if ( identifier == "n" ) { + QStringList nameParts = splitString( semicolonSep, (*lineIt).value().asString() ); + if ( nameParts.count() > 0 ) + addr.setFamilyName( nameParts[ 0 ] ); + if ( nameParts.count() > 1 ) + addr.setGivenName( nameParts[ 1 ] ); + if ( nameParts.count() > 2 ) + addr.setAdditionalName( nameParts[ 2 ] ); + if ( nameParts.count() > 3 ) + addr.setPrefix( nameParts[ 3 ] ); + if ( nameParts.count() > 4 ) + addr.setSuffix( nameParts[ 4 ] ); + } + + // NICKNAME + if ( identifier == "nickname" ) + addr.setNickName( (*lineIt).value().asString() ); + + // NOTE + if ( identifier == "note" ) { +// #ifdef DESKTOP_VERSION +// addr.setNote( (*lineIt).value().asString() ); +// #else + QString note = (*lineIt).value().asString(); + if ( ! note.isEmpty() ) + addr.setNote( note.replace ( QRegExp("\\\\n") , "\n") ); + else + addr.setNote( note ); + //#endif + } + + // ORGANIZATION + if ( identifier == "org" ) + addr.setOrganization( (*lineIt).value().asString() ); + + // PHOTO + if ( identifier == "photo" ) + addr.setPhoto( parsePicture( *lineIt ) ); + + // PROID + if ( identifier == "prodid" ) + addr.setProductId( (*lineIt).value().asString() ); + + // REV + if ( identifier == "rev" ) + addr.setRevision( parseDateTime( (*lineIt).value().asString() ) ); + + // ROLE + if ( identifier == "role" ) + addr.setRole( (*lineIt).value().asString() ); + + // SORT-STRING + if ( identifier == "sort-string" ) + addr.setSortString( (*lineIt).value().asString() ); + + // SOUND + if ( identifier == "sound" ) + addr.setSound( parseSound( *lineIt ) ); + + // TEL + if ( identifier == "tel" ) { + PhoneNumber phone; + phone.setNumber( (*lineIt).value().asString() ); + + int type = 0; + + QStringList types = (*lineIt).parameters( "type" ); + for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) + type += mPhoneTypeMap[(*it).upper()]; + + if ( !type ) + type = PhoneNumber::Home; // default + + phone.setType( type ); + + addr.insertPhoneNumber( phone ); + } + + // TITLE + if ( identifier == "title" ) + addr.setTitle( (*lineIt).value().asString() ); + + // TZ + if ( identifier == "tz" ) { + TimeZone tz; + QString date = (*lineIt).value().asString(); + + int hours = date.mid( 1, 2).toInt(); + int minutes = date.mid( 4, 2 ).toInt(); + int offset = ( hours * 60 ) + minutes; + offset = offset * ( date[ 0 ] == '+' ? 1 : -1 ); + + tz.setOffset( offset ); + addr.setTimeZone( tz ); + } + + // UID + if ( identifier == "uid" ) + addr.setUid( (*lineIt).value().asString() ); + + // URL + if ( identifier == "url" ) + addr.setUrl( (*lineIt).value().asString() ); + + // X- + if ( identifier.startsWith( "x-" ) ) { + QString key = (*lineIt).identifier().mid( 2 ); + int dash = key.find( "-" ); + addr.insertCustom( key.left( dash ), key.mid( dash + 1 ), (*lineIt).value().asString() ); + } + } + } + + addrList.append( addr ); + } + + return addrList; +} + +QDateTime VCardTool::parseDateTime( const QString &str ) +{ + QDateTime dateTime; + + if ( str.find( '-' ) == -1 ) { // is base format (yyyymmdd) + dateTime.setDate( QDate( str.left( 4 ).toInt(), str.mid( 4, 2 ).toInt(), + str.mid( 6, 2 ).toInt() ) ); + + if ( str.find( 'T' ) ) // has time information yyyymmddThh:mm:ss + dateTime.setTime( QTime( str.mid( 11, 2 ).toInt(), str.mid( 14, 2 ).toInt(), + str.mid( 17, 2 ).toInt() ) ); + + } else { // is extended format yyyy-mm-dd + dateTime.setDate( QDate( str.left( 4 ).toInt(), str.mid( 5, 2 ).toInt(), + str.mid( 8, 2 ).toInt() ) ); + + if ( str.find( 'T' ) ) // has time information yyyy-mm-ddThh:mm:ss + dateTime.setTime( QTime( str.mid( 11, 2 ).toInt(), str.mid( 14, 2 ).toInt(), + str.mid( 17, 2 ).toInt() ) ); + } + + return dateTime; +} + +QString VCardTool::createDateTime( const QDateTime &dateTime ) +{ + QString str; + + if ( dateTime.date().isValid() ) { + str.sprintf( "%4d-%02d-%02d", dateTime.date().year(), dateTime.date().month(), + dateTime.date().day() ); + if ( dateTime.time().isValid() ) { + QString tmp; + tmp.sprintf( "T%02d:%02d:%02dZ", dateTime.time().hour(), dateTime.time().minute(), + dateTime.time().second() ); + str += tmp; + } + } + + return str; +} + +Picture VCardTool::parsePicture( const VCardLine &line ) +{ + Picture pic; + + QStringList params = line.parameterList(); + if ( params.contains( "encoding" ) ) { + QCString cs(line.value().asCString()); + QByteArray input, output; + input = line.value().asCString(); + if ( line.parameter( "encoding" ).lower() == "b" ) + KCodecs::base64Decode( input, output ); + else if ( line.parameter( "encoding" ).lower() == "quoted-printable" ) + KCodecs::quotedPrintableDecode( input, output ); + + qDebug("********** DECODING OKAY ************** (picture)"); + pic.setData( QImage(output) ); + + } + else if ( params.contains( "value" ) ) { + if ( line.parameter( "value" ).lower() == "uri" ) + pic.setUrl( line.value().asString() ); + } + + if ( params.contains( "type" ) ) + pic.setType( line.parameter( "type" ) ); + + return pic; +} + +VCardLine VCardTool::createPicture( const QString &identifier, const Picture &pic ) +{ + // LR fixed + VCardLine line( identifier ); + + if ( pic.isIntern() ) { + if ( !pic.data().isNull() ) { +#if 0 + QByteArray input; + QDataStream s( input, IO_WriteOnly ); + s.setVersion( 4 ); + s << pic.data(); + line.setValue( input ); +#else + QCString input; + QDataStream s( input, IO_WriteOnly ); + s.setVersion( 4 ); + s << pic.data(); + //QCString cs(line.value().asCString()); + //QImage qi(cs); + line.setValue( input ); +#endif + + line.addParameter( "encoding", "b" ); + line.addParameter( "type", "image/png" ); + } + } else if ( !pic.url().isEmpty() ) { + line.setValue( pic.url() ); + line.addParameter( "value", "URI" ); + } + + return line; +} + +Sound VCardTool::parseSound( const VCardLine &line ) +{ + Sound snd; + + QStringList params = line.parameterList(); + if ( params.contains( "encoding" ) ) { + qDebug("VCardTool::parseSound has to be verified"); +//US snd.setData( line.value().asByteArray() ); +//US I am not sure if this is correct + QCString cs(line.value().asCString()); + snd.setData( cs ); + } + else if ( params.contains( "value" ) ) { + if ( line.parameter( "value" ).lower() == "uri" ) + snd.setUrl( line.value().asString() ); + } + +/* TODO: support sound types + if ( params.contains( "type" ) ) + snd.setType( line.parameter( "type" ) ); +*/ + + return snd; +} + +VCardLine VCardTool::createSound( const Sound &snd ) +{ + VCardLine line( "SOUND" ); + + if ( snd.isIntern() ) { + if ( !snd.data().isEmpty() ) { + qDebug("VCardTool::createSound has to be verified"); +//US line.setValue( snd.data() ); + +//US I am not sure if this is correct + QCString cs(snd.data()); + line.setValue( cs ); + + + line.addParameter( "encoding", "b" ); + // TODO: need to store sound type!!! + } + } else if ( !snd.url().isEmpty() ) { + line.setValue( snd.url() ); + line.addParameter( "value", "URI" ); + } + + return line; +} + +Key VCardTool::parseKey( const VCardLine &line ) +{ + Key key; + + QStringList params = line.parameterList(); + if ( params.contains( "encoding" ) ) { + qDebug("VCardTool::parseKey has to be verified"); +//US key.setBinaryData( line.value().asByteArray() ); + +//US I am not sure if this is correct + QCString cs( line.value().asCString() ); + key.setBinaryData( cs ); + } + else + key.setTextData( line.value().asString() ); + + if ( params.contains( "type" ) ) { + if ( line.parameter( "type" ).lower() == "x509" ) + key.setType( Key::X509 ); + else if ( line.parameter( "type" ).lower() == "pgp" ) + key.setType( Key::PGP ); + else { + key.setType( Key::Custom ); + key.setCustomTypeString( line.parameter( "type" ) ); + } + } + + return key; +} + +VCardLine VCardTool::createKey( const Key &key ) +{ + VCardLine line( "KEY" ); + + if ( key.isBinary() ) { + if ( !key.binaryData().isEmpty() ) { + qDebug("VCardTool::createKey has to be verified"); +//US line.setValue( key.binaryData() ); +//US I am not sure if this is correct + QCString cs(key.binaryData()); + line.setValue( cs ); + + + line.addParameter( "encoding", "b" ); + } + } else if ( !key.textData().isEmpty() ) + line.setValue( key.textData() ); + + if ( key.type() == Key::X509 ) + line.addParameter( "type", "X509" ); + else if ( key.type() == Key::PGP ) + line.addParameter( "type", "PGP" ); + else if ( key.type() == Key::Custom ) + line.addParameter( "type", key.customTypeString() ); + + return line; +} + +Secrecy VCardTool::parseSecrecy( const VCardLine &line ) +{ + Secrecy secrecy; + + if ( line.value().asString().lower() == "public" ) + secrecy.setType( Secrecy::Public ); + if ( line.value().asString().lower() == "private" ) + secrecy.setType( Secrecy::Private ); + if ( line.value().asString().lower() == "confidential" ) + secrecy.setType( Secrecy::Confidential ); + + return secrecy; +} + +VCardLine VCardTool::createSecrecy( const Secrecy &secrecy ) +{ + VCardLine line( "CLASS" ); + + int type = secrecy.type(); + + if ( type == Secrecy::Public ) + line.setValue( "PUBLIC" ); + else if ( type == Secrecy::Private ) + line.setValue( "PRIVATE" ); + else if ( type == Secrecy::Confidential ) + line.setValue( "CONFIDENTIAL" ); + + return line; +} + +Agent VCardTool::parseAgent( const VCardLine &line ) +{ + Agent agent; + + QStringList params = line.parameterList(); + if ( params.contains( "value" ) ) { + if ( line.parameter( "value" ).lower() == "uri" ) + agent.setUrl( line.value().asString() ); + } else { + QString str = line.value().asString(); + +//US using the old implementation instead + qDebug("VCardTool::parseAgent has to be verified"); +/*US + str.replace( "\\n", "\r\n" ); + str.replace( "\\N", "\r\n" ); + str.replace( "\\;", ";" ); + str.replace( "\\:", ":" ); + str.replace( "\\,", "," ); +*/ + str.replace( QRegExp("\\n") , "\r\n" ); + str.replace( QRegExp("\\N") , "\r\n" ); + str.replace( QRegExp("\\;") , ";" ); + str.replace( QRegExp("\\:") , ":" ); + str.replace( QRegExp("\\,") , "," ); + + Addressee::List list = parseVCards( str ); + if ( list.count() > 0 ) { + Addressee *addr = new Addressee; + *addr = list[ 0 ]; + agent.setAddressee( addr ); + } + } + + return agent; +} + +VCardLine VCardTool::createAgent( VCard::Version version, const Agent &agent ) +{ + VCardLine line( "AGENT" ); + + if ( agent.isIntern() ) { + if ( agent.addressee() != 0 ) { + Addressee::List list; + list.append( *agent.addressee() ); + + QString str = createVCards( list, version ); + +//US using the old implementation instead + qDebug("VCardTool::createAgent has to be verified"); +/*US + str.replace( "\r\n", "\\n" ); + str.replace( ";", "\\;" ); + str.replace( ":", "\\:" ); + str.replace( ",", "\\," ); +*/ + str.replace( QRegExp("\r\n"), "\\n" ); + str.replace( QRegExp(";"), "\\;" ); + str.replace( QRegExp(":"), "\\:" ); + str.replace( QRegExp(","), "\\," ); + line.setValue( str ); + } + } else if ( !agent.url().isEmpty() ) { + line.setValue( agent.url() ); + line.addParameter( "value", "URI" ); + } + + return line; +} + +QStringList VCardTool::splitString( const QChar &sep, const QString &str ) +{ + QStringList list; + QString value( str ); + + int start = 0; + int pos = value.find( sep, start ); + + while ( pos != -1 ) { + if ( value[ pos - 1 ] != '\\' ) { + if ( pos > start && pos <= (int)value.length() ) + list << value.mid( start, pos - start ); + else + list << QString::null; + + start = pos + 1; + pos = value.find( sep, start ); + } else { + if ( pos != 0 ) { + value.replace( pos - 1, 2, sep ); + pos = value.find( sep, pos ); + } else + pos = value.find( sep, pos + 1 ); + } + } + + int l = value.length() - 1; + if ( value.mid( start, l - start + 1 ).length() > 0 ) + list << value.mid( start, l - start + 1 ); + else + list << QString::null; + + return list; +} diff --git a/kabc/vcardparser/vcardtool.h b/kabc/vcardparser/vcardtool.h new file mode 100644 index 0000000..40a3b82 --- a/dev/null +++ b/kabc/vcardparser/vcardtool.h @@ -0,0 +1,88 @@ +/* + This file is part of libkabc. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KABC_VCARDTOOL_H +#define KABC_VCARDTOOL_H + +#include "addressee.h" +#include "vcardparser.h" + +class QDateTime; + +namespace KABC { + +class Agent; +class Key; +class Picture; +class Secrecy; +class Sound; + +class VCardTool +{ + public: + VCardTool(); + ~VCardTool(); + + /** + Creates a string that contains the addressees from the list in + the vCard format. + */ + QString createVCards( Addressee::List list, VCard::Version version = VCard::v3_0 ); + + /** + Parses the string and returns a list of addressee objects. + */ + Addressee::List parseVCards( const QString& vcard ); + + private: + /** + Split a string and replaces escaped separators on the fly with + unescaped ones. + */ + QStringList splitString( const QChar &sep, const QString &value ); + + QDateTime parseDateTime( const QString &str ); + QString createDateTime( const QDateTime &dateTime ); + + Picture parsePicture( const VCardLine &line ); + VCardLine createPicture( const QString &identifier, const Picture &pic ); + + Sound parseSound( const VCardLine &line ); + VCardLine createSound( const Sound &snd ); + + Key parseKey( const VCardLine &line ); + VCardLine createKey( const Key &key ); + + Secrecy parseSecrecy( const VCardLine &line ); + VCardLine createSecrecy( const Secrecy &secrecy ); + + Agent parseAgent( const VCardLine &line ); + VCardLine createAgent( VCard::Version version, const Agent &agent ); + + QMap<QString, int> mAddressTypeMap; + QMap<QString, int> mPhoneTypeMap; + + class VCardToolPrivate; + VCardToolPrivate *d; +}; + +} + +#endif diff --git a/kaddressbook/addresseditwidget.cpp b/kaddressbook/addresseditwidget.cpp new file mode 100644 index 0000000..3dcd592 --- a/dev/null +++ b/kaddressbook/addresseditwidget.cpp @@ -0,0 +1,622 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qsignal.h> +#include <qstring.h> +#include <qapplication.h> + +#ifndef KAB_EMBEDDED +#include <qtextedit.h> +#include <kaccelmanager.h> +#include <kbuttonbox.h> +#else //KAB_EMBEDDED +#include <qmultilineedit.h> +#endif //KAB_EMBEDDED + +#include <qtoolbutton.h> +#include <qtooltip.h> + +#include <kapplication.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klistview.h> +#include <klocale.h> +#include <kglobal.h> +#include <kmessagebox.h> +#include <kseparator.h> + +#include "addresseditwidget.h" + + + +AddressEditWidget::AddressEditWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + + mConfig = AddresseeConfig::instance(); + QVBoxLayout *layout = new QVBoxLayout( this ); + layout->setSpacing( KDialog::spacingHintSmall() ); + QHBox *b1 = new QHBox( this); + //QLabel * label = new QLabel( b1 ); + //label->setPixmap( KGlobal::iconLoader()->loadIcon( "gohome", KIcon::Desktop, 0 ) ); + + + //label->setAlignment( AlignCenter); + layout->addWidget( b1 ); + mTypeCombo = new AddressTypeCombo( mAddressList, b1 ); + QPushButton *editButton = new QPushButton( i18n( "&Edit Addresses..." ), + b1 ); + connect( mTypeCombo, SIGNAL( activated( int ) ), + SLOT( updateAddressEdit() ) ); + // layout->addWidget( mTypeCombo ); + +#ifndef KAB_EMBEDDED + mAddressTextEdit = new QTextEdit( this ); + mAddressTextEdit->setReadOnly( true ); + mAddressTextEdit->setMinimumHeight( 20 ); +#else //KAB_EMBEDDED + mAddressTextEdit = new QMultiLineEdit( this ); + mAddressTextEdit->setReadOnly( true ); + mAddressTextEdit->setMinimumHeight( 20 ); +#endif //KAB_EMBEDDED + + layout->addWidget( mAddressTextEdit ); + + + connect( editButton, SIGNAL( clicked() ), SLOT( edit() ) ); +} + +AddressEditWidget::~AddressEditWidget() +{ + +} + +KABC::Address::List AddressEditWidget::addresses() +{ + KABC::Address::List retList; + + KABC::Address::List::Iterator it; + for ( it = mAddressList.begin(); it != mAddressList.end(); ++it ) + if ( !(*it).isEmpty() ) + retList.append( *it ); + + return retList; +} + +void AddressEditWidget::setAddresses( const KABC::Addressee &addr, + const KABC::Address::List &list ) +{ + mAddressee = addr; + + mAddressList.clear(); + + // Insert types for existing numbers. + mTypeCombo->insertTypeList( list ); + + QValueList<int> defaultTypes; + defaultTypes << KABC::Address::Home; + defaultTypes << KABC::Address::Work; + + mConfig->setUid( mAddressee.uid() ); + QValueList<int> configList = mConfig->noDefaultAddrTypes(); + QValueList<int>::ConstIterator it; + for ( it = configList.begin(); it != configList.end(); ++it ) + defaultTypes.remove( *it ); + + // Insert default types. + // Doing this for mPrefCombo is enough because the list is shared by all + // combos. + for( it = defaultTypes.begin(); it != defaultTypes.end(); ++it ) { + if ( !mTypeCombo->hasType( *it ) ) + mTypeCombo->insertType( list, *it, Address( *it ) ); + } + + mTypeCombo->updateTypes(); + + // find preferred address which will be shown + int preferred = KABC::Address::Home; // default if no preferred address set + uint i; + for (i = 0; i < list.count(); i++) + if ( list[i].type() & KABC::Address::Pref ) { + preferred = list[i].type(); + break; + } + + mTypeCombo->selectType( preferred ); + + updateAddressEdit(); +} + +void AddressEditWidget::edit() +{ + AddressEditDialog dialog( mAddressList, mTypeCombo->currentItem(), this ); + if ( dialog.exec() ) { + if ( dialog.changed() ) { + mAddressList = dialog.addresses(); + + bool hasHome = false, hasWork = false; + KABC::Address::List::Iterator it; + for ( it = mAddressList.begin(); it != mAddressList.end(); ++it ) { + if ( (*it).type() == KABC::Address::Home ) { + if ( !(*it).isEmpty() ) + hasHome = true; + } + if ( (*it).type() == KABC::Address::Work ) { + if ( !(*it).isEmpty() ) + hasWork = true; + } + } + + mConfig->setUid( mAddressee.uid() ); + QValueList<int> configList; + if ( !hasHome ) { + configList << KABC::Address::Home; + } + if ( !hasWork ) { + configList << KABC::Address::Work; + } + mConfig->setNoDefaultAddrTypes( configList ); + + mTypeCombo->updateTypes(); + updateAddressEdit(); + emit modified(); + } + } +} + +void AddressEditWidget::updateAddressEdit() +{ + KABC::Address::List::Iterator it = mTypeCombo->selectedElement(); + + bool block = signalsBlocked(); + blockSignals( true ); + + mAddressTextEdit->setText( "" ); + + if ( it != mAddressList.end() ) { + KABC::Address a = *it; + if ( !a.isEmpty() ) { +#if KDE_VERSION >= 319 + if ( a.type() & KABC::Address::Work ) { + mAddressTextEdit->setText( a.formattedAddress( mAddressee.realName(), + mAddressee.organization() ) ); + } else { + mAddressTextEdit->setText( a.formattedAddress( mAddressee.realName() ) ); + } +#else + QString text; + if ( !a.street().isEmpty() ) + text += a.street() + "\n"; + + if ( !a.postOfficeBox().isEmpty() ) + text += a.postOfficeBox() + "\n"; + + text += a.locality() + QString(" ") + a.region(); + + if ( !a.postalCode().isEmpty() ) + text += QString(", ") + a.postalCode(); + + text += "\n"; + + if ( !a.country().isEmpty() ) + text += a.country() + "\n"; + + text += a.extended(); + + mAddressTextEdit->setText( text ); +#endif + } + } + + blockSignals( block ); +} + +AddressEditDialog::AddressEditDialog( const KABC::Address::List &list, + int selected, QWidget *parent, + const char *name ) + : KDialogBase( Plain, i18n( "Edit Address" ), Ok | Cancel, Ok, + parent, name, true, true ), + mPreviousAddress( 0 ) +{ + mAddressList = list; + + QWidget *page = plainPage(); + + QGridLayout *topLayout = new QGridLayout( page, 8, 2 ); + topLayout->setSpacing( spacingHintSmall() ); + + mTypeCombo = new AddressTypeCombo( mAddressList, page ); + topLayout->addMultiCellWidget( mTypeCombo, 0, 0, 0, 1 ); + + QLabel *label = new QLabel( i18n( "Street:" ), page ); + label->setAlignment( Qt::AlignTop | Qt::AlignLeft ); + topLayout->addWidget( label, 1, 0 ); + +#ifndef KAB_EMBEDDED + mStreetTextEdit = new QTextEdit( page ); +#else //KAB_EMBEDDED + mStreetTextEdit = new QMultiLineEdit( page ); +//US qDebug("AddressEditDialog::AddressEditDialog has to be changed"); +#endif //KAB_EMBEDDED + + label->setBuddy( mStreetTextEdit ); + topLayout->addWidget( mStreetTextEdit, 1, 1 ); + + label = new QLabel( i18n( "Post office box:" ), page ); + topLayout->addWidget( label, 2 , 0 ); + mPOBoxEdit = new KLineEdit( page ); + label->setBuddy( mPOBoxEdit ); + topLayout->addWidget( mPOBoxEdit, 2, 1 ); + int maxwid = QApplication::desktop()->width(); + maxwid -= (spacingHintSmall()+label->sizeHint().width() ); + label = new QLabel( i18n( "Locality:" ), page ); + topLayout->addWidget( label, 3, 0 ); + mLocalityEdit = new KLineEdit( page ); + label->setBuddy( mLocalityEdit ); + topLayout->addWidget( mLocalityEdit, 3, 1 ); + + label = new QLabel( i18n( "Region:" ), page ); + topLayout->addWidget( label, 4, 0 ); + mRegionEdit = new KLineEdit( page ); + label->setBuddy( mRegionEdit ); + topLayout->addWidget( mRegionEdit, 4, 1 ); + + label = new QLabel( i18n( "Postal code:" ), page ); + topLayout->addWidget( label, 5, 0 ); + mPostalCodeEdit = new KLineEdit( page ); + label->setBuddy( mPostalCodeEdit ); + topLayout->addWidget( mPostalCodeEdit, 5, 1 ); + + label = new QLabel( i18n( "Country:" ), page ); + topLayout->addWidget( label, 6, 0 ); + mCountryCombo = new KComboBox( page ); + + mCountryCombo->setMaximumWidth( maxwid -10 ); + mCountryCombo->setEditable( true ); + mCountryCombo->setDuplicatesEnabled( false ); + mCountryCombo->setAutoCompletion( true ); + fillCountryCombo(); + label->setBuddy( mCountryCombo ); + topLayout->addWidget( mCountryCombo, 6, 1 ); + mCountryCombo->setSizeLimit( 8); + mPreferredCheckBox = new QCheckBox( i18n( "This is the preferred address" ), page ); + topLayout->addMultiCellWidget( mPreferredCheckBox, 7, 7, 0, 1 ); + /* + KSeparator *sep = new KSeparator( KSeparator::HLine, page ); + topLayout->addMultiCellWidget( sep, 8, 8, 0, 1 ); + */ + QHBox *buttonBox = new QHBox( page ); + buttonBox->setSpacing( spacingHint() ); + topLayout->addMultiCellWidget( buttonBox, 9, 9, 0, 1 ); + + QPushButton *addButton = new QPushButton( i18n( "New..." ), buttonBox ); + connect( addButton, SIGNAL( clicked() ), SLOT( addAddress() ) ); + + mRemoveButton = new QPushButton( i18n( "Remove" ), buttonBox ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeAddress() ) ); + + mChangeTypeButton = new QPushButton( i18n( "Change Type" ), buttonBox ); + connect( mChangeTypeButton, SIGNAL( clicked() ), SLOT( changeType() ) ); + + mTypeCombo->updateTypes(); + mTypeCombo->setCurrentItem( selected ); + + updateAddressEdits(); + + connect( mTypeCombo, SIGNAL( activated( int ) ), + SLOT( updateAddressEdits() ) ); + connect( mStreetTextEdit, SIGNAL( textChanged() ), SLOT( modified() ) ); + connect( mPOBoxEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mLocalityEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mRegionEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mPostalCodeEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mCountryCombo, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mPreferredCheckBox, SIGNAL( toggled( bool ) ), SLOT( modified() ) ); + +#ifndef KAB_EMBEDDED + KAcceleratorManager::manage( this ); +#else //KAB_EMBEDDED +//US qDebug("AddressEditDialog::AddressEditDialog has to be changed 2"); +#endif //KAB_EMBEDDED + + mChanged = false; + + bool state = (mAddressList.count() > 0); + mRemoveButton->setEnabled( state ); + mChangeTypeButton->setEnabled( state ); +#ifndef DESKTOP_VERSION + showMaximized(); +#endif +} + +AddressEditDialog::~AddressEditDialog() +{ +} + +KABC::Address::List AddressEditDialog::addresses() +{ + saveAddress( *(mTypeCombo->selectedElement()) ); + + return mAddressList; +} + +bool AddressEditDialog::changed() const +{ + return mChanged; +} + +void AddressEditDialog::addAddress() +{ + AddressTypeDialog dlg( mTypeCombo->selectedType(), this ); + if ( dlg.exec() ) { + mAddressList.append( Address( dlg.type() ) ); + + mTypeCombo->updateTypes(); + mTypeCombo->setCurrentItem( mTypeCombo->count() - 1 ); + updateAddressEdits(); + + modified(); + + mRemoveButton->setEnabled( true ); + mChangeTypeButton->setEnabled( true ); + } +} + +void AddressEditDialog::removeAddress() +{ + if ( mAddressList.count() > 0 ) { + KABC::Address::List::Iterator it = mTypeCombo->selectedElement(); + if ( mPreviousAddress && mPreviousAddress->id() == (*it).id() ) + mPreviousAddress = 0; + + mAddressList.remove( it ); + mTypeCombo->updateTypes(); + updateAddressEdits(); + + modified(); + } + + bool state = ( mAddressList.count() > 0 ); + mRemoveButton->setEnabled( state ); + mChangeTypeButton->setEnabled( state ); +} + +void AddressEditDialog::changeType() +{ + KABC::Address::List::Iterator a = mTypeCombo->selectedElement(); + + AddressTypeDialog dlg( (*a).type(), this ); + if ( dlg.exec() ) { + (*a).setType( dlg.type() ); + + mTypeCombo->updateTypes(); + + modified(); + } +} + +void AddressEditDialog::updateAddressEdits() +{ + if ( mPreviousAddress ) + saveAddress( *mPreviousAddress ); + + KABC::Address::List::Iterator it = mTypeCombo->selectedElement(); + KABC::Address a = *it; + mPreviousAddress = &(*it); + + bool tmp = mChanged; + + mStreetTextEdit->setText( a.street() ); + mRegionEdit->setText( a.region() ); + mLocalityEdit->setText( a.locality() ); + mPostalCodeEdit->setText( a.postalCode() ); + mPOBoxEdit->setText( a.postOfficeBox() ); + +#ifndef KAB_EMBEDDED + mCountryCombo->setCurrentText( a.country() ); +#else //KAB_EMBEDDED + mCountryCombo->setEditText( a.country() ); +//US qDebug("AddressEditDialog::updateAddressEdits has to be changed 1"); +#endif //KAB_EMBEDDED + + mPreferredCheckBox->setChecked( a.type() & KABC::Address::Pref ); + + mStreetTextEdit->setFocus(); + + mChanged = tmp; +} + +void AddressEditDialog::modified() +{ + mChanged = true; +} + +void AddressEditDialog::saveAddress( KABC::Address &addr ) +{ + addr.setLocality( mLocalityEdit->text() ); + addr.setRegion( mRegionEdit->text() ); + addr.setPostalCode( mPostalCodeEdit->text() ); + addr.setCountry( mCountryCombo->currentText() ); + addr.setPostOfficeBox( mPOBoxEdit->text() ); + addr.setStreet( mStreetTextEdit->text() ); + + + if ( mPreferredCheckBox->isChecked() ) { + KABC::Address::List::Iterator it; + for ( it = mAddressList.begin(); it != mAddressList.end(); ++it ) + (*it).setType( (*it).type() & ~( KABC::Address::Pref ) ); + + addr.setType( addr.type() | KABC::Address::Pref ); + } +} + +void AddressEditDialog::fillCountryCombo() +{ + QString country[] = { + i18n( "Afghanistan" ), i18n( "Albania" ), i18n( "Algeria" ), + i18n( "American Samoa" ), i18n( "Andorra" ), i18n( "Angola" ), + i18n( "Anguilla" ), i18n( "Antarctica" ), i18n( "Antigua and Barbuda" ), + i18n( "Argentina" ), i18n( "Armenia" ), i18n( "Aruba" ), + i18n( "Ashmore and Cartier Islands" ), i18n( "Australia" ), + i18n( "Austria" ), i18n( "Azerbaijan" ), i18n( "Bahamas" ), + i18n( "Bahrain" ), i18n( "Bangladesh" ), i18n( "Barbados" ), + i18n( "Belarus" ), i18n( "Belgium" ), i18n( "Belize" ), + i18n( "Benin" ), i18n( "Bermuda" ), i18n( "Bhutan" ), + i18n( "Bolivia" ), i18n( "Bosnia and Herzegovina" ), i18n( "Botswana" ), + i18n( "Brazil" ), i18n( "Brunei" ), i18n( "Bulgaria" ), + i18n( "Burkina Faso" ), i18n( "Burundi" ), i18n( "Cambodia" ), + i18n( "Cameroon" ), i18n( "Canada" ), i18n( "Cape Verde" ), + i18n( "Cayman Islands" ), i18n( "Central African Republic" ), + i18n( "Chad" ), i18n( "Chile" ), i18n( "China" ), i18n( "Colombia" ), + i18n( "Comoros" ), i18n( "Congo" ), i18n( "Congo, Dem. Rep." ), + i18n( "Costa Rica" ), i18n( "Croatia" ), + i18n( "Cuba" ), i18n( "Cyprus" ), i18n( "Czech Republic" ), + i18n( "Denmark" ), i18n( "Djibouti" ), + i18n( "Dominica" ), i18n( "Dominican Republic" ), i18n( "Ecuador" ), + i18n( "Egypt" ), i18n( "El Salvador" ), i18n( "Equatorial Guinea" ), + i18n( "Eritrea" ), i18n( "Estonia" ), i18n( "England" ), + i18n( "Ethiopia" ), i18n( "European Union" ), i18n( "Faroe Islands" ), + i18n( "Fiji" ), i18n( "Finland" ), i18n( "France" ), + i18n( "French Polynesia" ), i18n( "Gabon" ), i18n( "Gambia" ), + i18n( "Georgia" ), i18n( "Germany" ), i18n( "Ghana" ), + i18n( "Greece" ), i18n( "Greenland" ), i18n( "Grenada" ), + i18n( "Guam" ), i18n( "Guatemala" ), i18n( "Guinea" ), + i18n( "Guinea-Bissau" ), i18n( "Guyana" ), i18n( "Haiti" ), + i18n( "Honduras" ), i18n( "Hong Kong" ), i18n( "Hungary" ), + i18n( "Iceland" ), i18n( "India" ), i18n( "Indonesia" ), + i18n( "Iran" ), i18n( "Iraq" ), i18n( "Ireland" ), + i18n( "Israel" ), i18n( "Italy" ), i18n( "Ivory Coast" ), + i18n( "Jamaica" ), i18n( "Japan" ), i18n( "Jordan" ), + i18n( "Kazakhstan" ), i18n( "Kenya" ), i18n( "Kiribati" ), + i18n( "Korea, North" ), i18n( "Korea, South" ), + i18n( "Kuwait" ), i18n( "Kyrgyzstan" ), i18n( "Laos" ), + i18n( "Latvia" ), i18n( "Lebanon" ), i18n( "Lesotho" ), + i18n( "Liberia" ), i18n( "Libya" ), i18n( "Liechtenstein" ), + i18n( "Lithuania" ), i18n( "Luxembourg" ), i18n( "Macau" ), + i18n( "Madagascar" ), i18n( "Malawi" ), i18n( "Malaysia" ), + i18n( "Maldives" ), i18n( "Mali" ), i18n( "Malta" ), + i18n( "Marshall Islands" ), i18n( "Martinique" ), i18n( "Mauritania" ), + i18n( "Mauritius" ), i18n( "Mexico" ), + i18n( "Micronesia, Federated States Of" ), i18n( "Moldova" ), + i18n( "Monaco" ), i18n( "Mongolia" ), i18n( "Montserrat" ), + i18n( "Morocco" ), i18n( "Mozambique" ), i18n( "Myanmar" ), + i18n( "Namibia" ), + i18n( "Nauru" ), i18n( "Nepal" ), i18n( "Netherlands" ), + i18n( "Netherlands Antilles" ), i18n( "New Caledonia" ), + i18n( "New Zealand" ), i18n( "Nicaragua" ), i18n( "Niger" ), + i18n( "Nigeria" ), i18n( "Niue" ), i18n( "North Korea" ), + i18n( "Northern Ireland" ), i18n( "Northern Mariana Islands" ), + i18n( "Norway" ), i18n( "Oman" ), i18n( "Pakistan" ), i18n( "Palau" ), + i18n( "Palestinian" ), i18n( "Panama" ), i18n( "Papua New Guinea" ), + i18n( "Paraguay" ), i18n( "Peru" ), i18n( "Philippines" ), + i18n( "Poland" ), i18n( "Portugal" ), i18n( "Puerto Rico" ), + i18n( "Qatar" ), i18n( "Romania" ), i18n( "Russia" ), i18n( "Rwanda" ), + i18n( "St. Kitts and Nevis" ), i18n( "St. Lucia" ), + i18n( "St. Vincent and the Grenadines" ), i18n( "San Marino" ), + i18n( "Sao Tome and Principe" ), i18n( "Saudi Arabia" ), + i18n( "Senegal" ), i18n( "Serbia & Montenegro" ), i18n( "Seychelles" ), + i18n( "Sierra Leone" ), i18n( "Singapore" ), i18n( "Slovakia" ), + i18n( "Slovenia" ), i18n( "Solomon Islands" ), i18n( "Somalia" ), + i18n( "South Africa" ), i18n( "South Korea" ), i18n( "Spain" ), + i18n( "Sri Lanka" ), i18n( "St. Kitts and Nevis" ), i18n( "Sudan" ), + i18n( "Suriname" ), i18n( "Swaziland" ), i18n( "Sweden" ), + i18n( "Switzerland" ), i18n( "Syria" ), i18n( "Taiwan" ), + i18n( "Tajikistan" ), i18n( "Tanzania" ), i18n( "Thailand" ), + i18n( "Tibet" ), i18n( "Togo" ), i18n( "Tonga" ), + i18n( "Trinidad and Tobago" ), i18n( "Tunisia" ), i18n( "Turkey" ), + i18n( "Turkmenistan" ), i18n( "Turks and Caicos Islands" ), + i18n( "Tuvalu" ), i18n( "Uganda " ), i18n( "Ukraine" ), + i18n( "United Arab Emirates" ), i18n( "United Kingdom" ), + i18n( "United States" ), i18n( "Uruguay" ), i18n( "Uzbekistan" ), + i18n( "Vanuatu" ), i18n( "Vatican City" ), i18n( "Venezuela" ), + i18n( "Vietnam" ), i18n( "Western Samoa" ), i18n( "Yemen" ), + i18n( "Yugoslavia" ), i18n( "Zaire" ), i18n( "Zambia" ), + i18n( "Zimbabwe" ), + "" + }; + + QStringList countries; + for ( int i = 0; !country[ i ].isEmpty(); ++i ) + countries.append( country[ i ] ); + + countries.sort(); + + mCountryCombo->insertStringList( countries ); +} + + +AddressTypeDialog::AddressTypeDialog( int type, QWidget *parent ) + : KDialogBase( Plain, i18n( "Edit Address Type" ), Ok | Cancel, Ok, + parent, "AddressTypeDialog" ) +{ + QWidget *page = plainPage(); + QVBoxLayout *layout = new QVBoxLayout( page ); + + mGroup = new QButtonGroup( 2, Horizontal, i18n( "Address Types" ), page ); + layout->addWidget( mGroup ); + + mTypeList = KABC::Address::typeList(); + mTypeList.remove( KABC::Address::Pref ); + + KABC::Address::TypeList::Iterator it; + for ( it = mTypeList.begin(); it != mTypeList.end(); ++it ) + new QCheckBox( KABC::Address::typeLabel( *it ), mGroup ); + + for ( int i = 0; i < mGroup->count(); ++i ) { + QCheckBox *box = (QCheckBox*)mGroup->find( i ); + box->setChecked( type & mTypeList[ i ] ); + } +} + +AddressTypeDialog::~AddressTypeDialog() +{ +} + +int AddressTypeDialog::type() const +{ + int type = 0; + for ( int i = 0; i < mGroup->count(); ++i ) { + QCheckBox *box = (QCheckBox*)mGroup->find( i ); + if ( box->isChecked() ) + type += mTypeList[ i ]; + } + + return type; +} + +#ifndef KAB_EMBEDDED +#include "addresseditwidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/addresseditwidget.h b/kaddressbook/addresseditwidget.h new file mode 100644 index 0000000..bc96d74 --- a/dev/null +++ b/kaddressbook/addresseditwidget.h @@ -0,0 +1,159 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef ADDRESSEDITWIDGET_H +#define ADDRESSEDITWIDGET_H + +#include <qwidget.h> + +#include <kdialogbase.h> +#include <kabc/address.h> +#include <kabc/addressee.h> + +#include "addresseeconfig.h" +#include "typecombo.h" + +class QButtonGroup; +class QCheckBox; +class QListView; +#ifndef KAB_EMBEDDED +class QTextEdit; +#else //KAB_EMBEDDED +class QMultiLineEdit; +#endif //KAB_EMBEDDED +class QToolButton; + +class KComboBox; +class KLineEdit; +class KListView; + +typedef TypeCombo<KABC::Address> AddressTypeCombo; + +/** + Editor widget for addresses. + */ +class AddressEditWidget : public QWidget +{ + Q_OBJECT + + public: + AddressEditWidget( QWidget *parent, const char *name = 0 ); + ~AddressEditWidget(); + + KABC::Address::List addresses(); + void setAddresses( const KABC::Addressee &addr, + const KABC::Address::List &list ); + + void updateTypeCombo( const KABC::Address::List&, KComboBox* ); + KABC::Address currentAddress( KComboBox*, int ); + + signals: + void modified(); + + protected slots: + void updateAddressEdit(); + + void edit(); + + private: + AddresseeConfig * mConfig; + AddressTypeCombo *mTypeCombo; + + QPushButton *mEditButton; +#ifndef KAB_EMBEDDED + QTextEdit *mAddressTextEdit; +#else //KAB_EMBEDDED + QMultiLineEdit *mAddressTextEdit; +#endif //KAB_EMBEDDED + + KABC::Address::List mAddressList; + KABC::Addressee mAddressee; + int mIndex; +}; + +/** + Dialog for editing address details. + */ +class AddressEditDialog : public KDialogBase +{ + Q_OBJECT + + public: + AddressEditDialog( const KABC::Address::List &list, int selected, + QWidget *parent, const char *name = 0 ); + ~AddressEditDialog(); + + KABC::Address::List addresses(); + bool changed() const; + + protected slots: + void addAddress(); + void removeAddress(); + void changeType(); + + void updateAddressEdits(); + void modified(); + + private: + void saveAddress( KABC::Address &addr ); + void fillCountryCombo(); + + AddressTypeCombo *mTypeCombo; +#ifndef KAB_EMBEDDED + QTextEdit *mStreetTextEdit; +#else //KAB_EMBEDDED + QMultiLineEdit *mStreetTextEdit; +#endif //KAB_EMBEDDED + KComboBox *mCountryCombo; + KLineEdit *mRegionEdit; + KLineEdit *mLocalityEdit; + KLineEdit *mPostalCodeEdit; + KLineEdit *mPOBoxEdit; + QCheckBox *mPreferredCheckBox; + + QPushButton *mRemoveButton; + QPushButton *mChangeTypeButton; + + KABC::Address::List mAddressList; + KABC::Address *mPreviousAddress; + bool mChanged; +}; + +/** + Dialog for selecting an address type. + */ +class AddressTypeDialog : public KDialogBase +{ + public: + AddressTypeDialog( int type, QWidget *parent ); + ~AddressTypeDialog(); + + int type() const; + + private: + QButtonGroup *mGroup; + + KABC::Address::TypeList mTypeList; +}; + +#endif diff --git a/kaddressbook/addresseeconfig.cpp b/kaddressbook/addresseeconfig.cpp new file mode 100644 index 0000000..ea0436f --- a/dev/null +++ b/kaddressbook/addresseeconfig.cpp @@ -0,0 +1,94 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "addresseeconfig.h" +#include "kabprefs.h" +//US +#include <kstandarddirs.h> +#include <qfileinfo.h> + +using namespace KABC; + +static AddresseeConfig* extern_AddresseeConfig = 0; +static KConfig * extern_Config = 0; + +AddresseeConfig::AddresseeConfig() +{ + + +} +AddresseeConfig::~AddresseeConfig() +{ + delete AddresseeConfig::config(); +} + + +AddresseeConfig* AddresseeConfig::instance() +{ + if ( ! extern_AddresseeConfig ) + extern_AddresseeConfig = new AddresseeConfig(); + return extern_AddresseeConfig; +} +KConfig* AddresseeConfig::config() +{ + if ( ! extern_Config ) { + QString conf = locateLocal("config", "kaddressrc"); + extern_Config= new KConfig( conf ); + } + return extern_Config; +} + + +void AddresseeConfig::setUid( const QString & uid ) +{ + AddresseeConfig::config()->setGroup( uid ); + mUid = uid; +} + +void AddresseeConfig::setAutomaticNameParsing( bool value ) +{ + AddresseeConfig::config()->writeEntry( "AutomaticNameParsing", value ); +} + + bool AddresseeConfig::automaticNameParsing() +{ + + return AddresseeConfig::config()->readBoolEntry( "AutomaticNameParsing", + KABPrefs::instance()->mAutomaticNameParsing ); +} + +void AddresseeConfig::setNoDefaultAddrTypes( const QValueList<int> &types ) +{ + AddresseeConfig::config()->writeEntry( "NoDefaultAddrTypes", types ); + AddresseeConfig::config()->sync(); +} + + QValueList<int> AddresseeConfig::noDefaultAddrTypes() const +{ + return AddresseeConfig::config()->readIntListEntry( "NoDefaultAddrTypes" ); +} + +void AddresseeConfig::remove( const QString & uid ) +{ + AddresseeConfig::config()->deleteGroup( uid ); +} diff --git a/kaddressbook/addresseeconfig.h b/kaddressbook/addresseeconfig.h new file mode 100644 index 0000000..47fbdd6 --- a/dev/null +++ b/kaddressbook/addresseeconfig.h @@ -0,0 +1,55 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef ADDRESSEECONFIG_H +#define ADDRESSEECONFIG_H + +#include <kabc/addressee.h> +#include <kconfig.h> + +using namespace KABC; + +class AddresseeConfig +{ + public: + AddresseeConfig(); + ~AddresseeConfig(); + static AddresseeConfig* instance(); + static KConfig* config(); + + Addressee addressee(); + + void setUid( const QString & uid ); + void setAutomaticNameParsing( bool value ); + bool automaticNameParsing(); + + void setNoDefaultAddrTypes( const QValueList<int> &types ); + QValueList<int> noDefaultAddrTypes() const; + + void remove( const QString & uid); + + private: + QString mUid; +}; + +#endif diff --git a/kaddressbook/addresseeeditordialog.cpp b/kaddressbook/addresseeeditordialog.cpp new file mode 100644 index 0000000..102138e --- a/dev/null +++ b/kaddressbook/addresseeeditordialog.cpp @@ -0,0 +1,129 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> + +#include "addresseeeditorwidget.h" +#include "kabcore.h" + +#include "addresseeeditordialog.h" + +AddresseeEditorDialog::AddresseeEditorDialog( KABCore *core, QWidget *parent, + const char *name ) + : KDialogBase( KDialogBase::Plain, i18n( "Edit Contact" ), + KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Apply, + KDialogBase::Ok, parent, name, false ) +{ +#ifdef KAB_EMBEDDED + resize( KMIN(KGlobal::getDesktopWidth()-10, 490), KMIN(KGlobal::getDesktopHeight()-50, 300)); +#endif //KAB_EMBEDDED + + kdDebug(5720) << "AddresseeEditorDialog()" << endl; + + QWidget *page = plainPage(); + + QVBoxLayout *layout = new QVBoxLayout( page ); + + mEditorWidget = new AddresseeEditorWidget( core, false, page ); + connect( mEditorWidget, SIGNAL( modified( const KABC::Addressee::List& ) ), + SLOT( widgetModified() ) ); + layout->addWidget( mEditorWidget ); + + enableButton( KDialogBase::Apply, false ); +} + +AddresseeEditorDialog::~AddresseeEditorDialog() +{ + kdDebug(5720) << "~AddresseeEditorDialog()" << endl; + + emit editorDestroyed( mEditorWidget->addressee().uid() ); +} + +void AddresseeEditorDialog::setAddressee( const KABC::Addressee &addr ) +{ + enableButton( KDialogBase::Apply, false ); + + mEditorWidget->setAddressee( addr ); +} + +KABC::Addressee AddresseeEditorDialog::addressee() +{ + return mEditorWidget->addressee(); +} + +bool AddresseeEditorDialog::dirty() +{ + return mEditorWidget->dirty(); +} + +void AddresseeEditorDialog::slotApply() +{ + if ( mEditorWidget->dirty() ) { + mEditorWidget->save(); + emit contactModified( mEditorWidget->addressee() ); + } + + enableButton( KDialogBase::Apply, false ); + + KDialogBase::slotApply(); +} + +void AddresseeEditorDialog::slotOk() +{ + slotApply(); + + KDialogBase::slotOk(); + + // Destroy this dialog +#ifndef KAB_EMBEDDED + delayedDestruct(); +#else //KAB_EMBEDDED + delete this; +#endif //KAB_EMBEDDED +} + +void AddresseeEditorDialog::widgetModified() +{ + enableButton( KDialogBase::Apply, true ); +} + +void AddresseeEditorDialog::slotCancel() +{ + KDialogBase::slotCancel(); + + // Destroy this dialog +#ifndef KAB_EMBEDDED + delayedDestruct(); +#else //KAB_EMBEDDED + delete this; +#endif //KAB_EMBEDDED + +} + +#ifndef KAB_EMBEDDED +#include "addresseeeditordialog.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/addresseeeditordialog.h b/kaddressbook/addresseeeditordialog.h new file mode 100644 index 0000000..1a00d3a --- a/dev/null +++ b/kaddressbook/addresseeeditordialog.h @@ -0,0 +1,62 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef ADDRESSEEEDITORDIALOG_H +#define ADDRESSEEEDITORDIALOG_H + +#include <kdialogbase.h> + +#include <kabc/addressbook.h> + +class AddresseeEditorWidget; +class QWidget; +class KABCore; + +class AddresseeEditorDialog : public KDialogBase +{ + Q_OBJECT + + public: + AddresseeEditorDialog( KABCore *core, QWidget *parent, const char *name = 0 ); + ~AddresseeEditorDialog(); + + void setAddressee( const KABC::Addressee& ); + KABC::Addressee addressee(); + + bool dirty(); + + signals: + void contactModified( const KABC::Addressee& ); + void editorDestroyed( const QString& ); + + protected slots: + virtual void slotApply(); + virtual void slotOk(); + virtual void slotCancel(); + void widgetModified(); + + private: + AddresseeEditorWidget *mEditorWidget; +}; + +#endif diff --git a/kaddressbook/addresseeeditorwidget.cpp b/kaddressbook/addresseeeditorwidget.cpp new file mode 100644 index 0000000..4365ee5 --- a/dev/null +++ b/kaddressbook/addresseeeditorwidget.cpp @@ -0,0 +1,1284 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qcheckbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qpushbutton.h> +#include <qtabwidget.h> + +#ifndef KAB_EMBEDDED +#include <qtextedit.h> + +#include <kaccelmanager.h> +#include "keywidget.h" +#include "soundwidget.h" + +#else //KAB_EMBEDDED +#include <qmultilineedit.h> +#endif //KAB_EMBEDDED + + +#include "keywidget.h" +#include "geowidget.h" +#include "imagewidget.h" +#include "nameeditdialog.h" +#include "phoneeditwidget.h" +#include "secrecywidget.h" + + +#include <qtoolbutton.h> +#include <qtooltip.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kseparator.h> +#include <ksqueezedtextlabel.h> + +#include <libkdepim/categoryeditdialog.h> +#include <libkdepim/categoryselectdialog.h> + +#include <libkdepim/kdateedit.h> + +#include "addresseditwidget.h" +#include "emaileditwidget.h" +#include "kabcore.h" +#include "kabprefs.h" + +#include "addresseeeditorwidget.h" + + + +AddresseeEditorWidget::AddresseeEditorWidget( KABCore *core, bool isExtension, + QWidget *parent, const char *name ) + : ExtensionWidget( core, parent, name ), mIsExtension( isExtension ), + mBlockSignals( false ) +{ + + mAConfig = AddresseeConfig::instance(); + + kdDebug(5720) << "AddresseeEditorWidget()" << endl; + mFormattedNameType = NameEditDialog::CustomName; + initGUI(); + mCategoryDialog = 0; + mCategoryEditDialog = 0; + + // Load the empty addressee as defaults + load(); + + mDirty = false; +} + +AddresseeEditorWidget::~AddresseeEditorWidget() +{ + kdDebug(5720) << "~AddresseeEditorWidget()" << endl; +} + +void AddresseeEditorWidget::contactsSelectionChanged() +{ + KABC::Addressee::List list = selectedContacts(); + + mAddressee = list[ 0 ]; + load(); +} + +void AddresseeEditorWidget::setAddressee( const KABC::Addressee &addr ) +{ + mAddressee = addr; + load(); +} + +const KABC::Addressee &AddresseeEditorWidget::addressee() +{ + return mAddressee; +} + +void AddresseeEditorWidget::textChanged( const QString& ) +{ + emitModified(); +} + +void AddresseeEditorWidget::initGUI() +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + + mTabWidget = new QTabWidget( this ); + layout->addWidget( mTabWidget ); + + setupTab1(); + setupTab1_1(); + setupTab2(); + setupTab2_1(); + setupTab3(); + setupTab3_1(); + + mNameEdit->setFocus(); + + connect( mTabWidget, SIGNAL( currentChanged(QWidget*) ), + SLOT( pageChanged(QWidget*) ) ); +} + +void AddresseeEditorWidget::setupTab1() +{ + // This is the General tab + QWidget *tab1 = new QWidget( mTabWidget ); + +//US QGridLayout *layout = new QGridLayout( tab1, 11, 7 ); + QGridLayout *layout = new QGridLayout( tab1, 7, 1 ); + layout->setMargin( KDialogBase::marginHintSmall() ); + layout->setSpacing( KDialogBase::spacingHintSmall() ); + + QLabel *label; + KSeparator* bar; + QPushButton *button; + + ////////////////////////////////// + // Upper left group (person info) + + // Person icon + /* LR + label = new QLabel( tab1 ); +//US ambiguous call. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop, 0 ) ); + layout->addMultiCellWidget( label, 0, 1, 0, 0 ); + */ + // First name + button = new QPushButton( i18n( "Name..." ), tab1 ); +//US QToolTip::add( button, i18n( "Edit the contact's name" ) ); + mNameEdit = new KLineEdit( tab1, "mNameEdit" ); + connect( mNameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( nameTextChanged( const QString& ) ) ); + connect( button, SIGNAL( clicked() ), SLOT( nameButtonClicked() ) ); + + mNameLabel = new KSqueezedTextLabel( tab1 ); + mNameLabel->hide(); + + layout->addWidget( button, 0, 0 ); + layout->addWidget( mNameEdit, 0, 1 ); + layout->addWidget( mNameLabel, 0, 1 ); + + label = new QLabel( i18n( "Role:" ), tab1 ); + mRoleEdit = new KLineEdit( tab1 ); + connect( mRoleEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mRoleEdit ); + layout->addWidget( label, 1, 0 ); + layout->addWidget( mRoleEdit, 1, 1 ); + + // Organization + label = new QLabel( i18n( "Organization:" ), tab1 ); + mOrgEdit = new KLineEdit( tab1 ); + label->setBuddy( mOrgEdit ); + connect( mOrgEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + layout->addWidget( label, 2, 0 ); + layout->addWidget( mOrgEdit, 2, 1 ); + + // File as (formatted name) + label = new QLabel( i18n( "Formatted name:" ), tab1 ); + mFormattedNameLabel = new KSqueezedTextLabel( tab1 ); + layout->addWidget( label, 3, 0 ); + layout->addWidget( mFormattedNameLabel, 3, 1 ); + /* LR + // Left hand separator. This separator doesn't go all the way + // across so the dialog still flows from top to bottom + bar = new KSeparator( KSeparator::HLine, tab1 ); + layout->addMultiCellWidget( bar, 4, 4, 0, 2 ); + */ + ////////////////////////////////////// + + /* LR + // Phone numbers (upper right) + label = new QLabel( tab1 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "kaddressbook", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "kaddressbook", KIcon::Desktop, 0 ) ); +//US layout->addMultiCellWidget( label, 0, 1, 3, 3 ); + layout->addMultiCellWidget( label, 5, 6, 0, 0 ); + */ + mPhoneEditWidget = new PhoneEditWidget( tab1 ); + connect( mPhoneEditWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); +//US layout->addMultiCellWidget( mPhoneEditWidget, 0, 3, 4, 6 ); + int iii; +#ifndef DESKTOP_VERSION + iii = 7; +#else + iii = 8; +#endif + layout->addMultiCellWidget( mPhoneEditWidget, 4, iii, 0, 1 ); + ++iii; + /* LR + bar = new KSeparator( KSeparator::HLine, tab1 ); +//US layout->addMultiCellWidget( bar, 4, 4, 3, 6 ); + layout->addMultiCellWidget( bar, 9, 9, 0, 2 ); + */ +/*US + ////////////////////////////////////// + // Addresses (lower left) + label = new QLabel( tab1 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "gohome", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "gohome", KIcon::Desktop, 0 ) ); + layout->addMultiCellWidget( label, 5, 6, 0, 0 ); + + mAddressEditWidget = new AddressEditWidget( tab1 ); + connect( mAddressEditWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); + layout->addMultiCellWidget( mAddressEditWidget, 5, 9, 1, 2 ); + + ////////////////////////////////////// + // Email / Web (lower right) + label = new QLabel( tab1 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "email", KIcon::Desktop) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "email", KIcon::Desktop, 0) ); + layout->addMultiCellWidget( label, 5, 6, 3, 3 ); + + mEmailWidget = new EmailEditWidget( tab1 ); + connect( mEmailWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); + layout->addMultiCellWidget( mEmailWidget, 5, 6, 4, 6 ); + + // add the separator + bar = new KSeparator( KSeparator::HLine, tab1 ); + layout->addMultiCellWidget( bar, 7, 7, 3, 6 ); + + label = new QLabel( tab1 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "homepage", KIcon::Desktop) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "homepage", KIcon::Desktop, 0) ); + layout->addMultiCellWidget( label, 8, 9, 3, 3 ); + + label = new QLabel( i18n( "URL:" ), tab1 ); + mURLEdit = new KLineEdit( tab1 ); + connect( mURLEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mURLEdit ); + layout->addWidget( label, 8, 4 ); + layout->addMultiCellWidget( mURLEdit, 8, 8, 5, 6 ); + + label = new QLabel( i18n( "&IM address:" ), tab1 ); + mIMAddressEdit = new KLineEdit( tab1 ); + connect( mIMAddressEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mIMAddressEdit ); + layout->addWidget( label, 9, 4 ); + layout->addMultiCellWidget( mIMAddressEdit, 9, 9, 5, 6 ); + + layout->addColSpacing( 6, 50 ); + + bar = new KSeparator( KSeparator::HLine, tab1 ); + layout->addMultiCellWidget( bar, 10, 10, 0, 6 ); +*/ + /////////////////////////////////////// + QHBox *categoryBox = new QHBox( tab1 ); + categoryBox->setSpacing( KDialogBase::spacingHint() ); + categoryBox->setMargin( KDialogBase::marginHintSmall() ); + + // Categories + button = new QPushButton( i18n( "Categories" ), categoryBox ); + connect( button, SIGNAL( clicked() ), SLOT( categoryButtonClicked() ) ); + + mCategoryEdit = new KLineEdit( categoryBox ); + mCategoryEdit->setReadOnly( true ); + connect( mCategoryEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + + mSecrecyWidget = new SecrecyWidget( categoryBox ); + connect( mSecrecyWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + +//US layout->addMultiCellWidget( categoryBox, 11, 11, 0, 6 ); + layout->addMultiCellWidget( categoryBox, iii, iii, 0, 1 ); + + // Build the layout and add to the tab widget + layout->activate(); // required + + mTabWidget->addTab( tab1, i18n( "&General" ) ); +} + + +void AddresseeEditorWidget::setupTab1_1() +{ + // This is the Address tab + QWidget *tab1_1 = new QWidget( mTabWidget ); + +//US QGridLayout *layout = new QGridLayout( tab1_1, 11, 7 ); + QGridLayout *layout = new QGridLayout( tab1_1, 7, 2 ); + layout->setMargin( KDialogBase::marginHintSmall() ); + layout->setSpacing( KDialogBase::spacingHintSmall() ); + + QLabel *label; + KSeparator* bar; + QPushButton *button; + +/*US + ////////////////////////////////// + // Upper left group (person info) + + // Person icon + label = new QLabel( tab1 ); +//US ambiguous call. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop, 0 ) ); + layout->addMultiCellWidget( label, 0, 1, 0, 0 ); + + // First name + button = new QPushButton( i18n( "Name..." ), tab1 ); + QToolTip::add( button, i18n( "Edit the contact's name" ) ); + mNameEdit = new KLineEdit( tab1, "mNameEdit" ); + connect( mNameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( nameTextChanged( const QString& ) ) ); + connect( button, SIGNAL( clicked() ), SLOT( nameButtonClicked() ) ); + +#ifndef KAB_EMBEDDED + mNameLabel = new KSqueezedTextLabel( tab1 ); + mNameLabel->hide(); +#else //KAB_EMBEDDED +qDebug("AddresseeEditorWidget::setupTab1 has to be changed"); +#endif //KAB_EMBEDDED + + layout->addWidget( button, 0, 1 ); + layout->addWidget( mNameEdit, 0, 2 ); + +#ifndef KAB_EMBEDDED + layout->addWidget( mNameLabel, 0, 2 ); +#else //KAB_EMBEDDED +qDebug("AddresseeEditorWidget::setupTab1 has to be changed"); +#endif //KAB_EMBEDDED + + label = new QLabel( i18n( "Role:" ), tab1 ); + mRoleEdit = new KLineEdit( tab1 ); + connect( mRoleEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mRoleEdit ); + layout->addWidget( label, 1, 1 ); + layout->addWidget( mRoleEdit, 1, 2 ); + + // Organization + label = new QLabel( i18n( "Organization:" ), tab1 ); + mOrgEdit = new KLineEdit( tab1 ); + label->setBuddy( mOrgEdit ); + connect( mOrgEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + layout->addWidget( label, 2, 1 ); + layout->addWidget( mOrgEdit, 2, 2 ); + + // File as (formatted name) + label = new QLabel( i18n( "Formatted name:" ), tab1 ); +#ifndef KAB_EMBEDDED + mFormattedNameLabel = new KSqueezedTextLabel( tab1 ); +#else //KAB_EMBEDDED +qDebug("AddresseeEditorWidget::setupTab1 has to be changed"); +#endif //KAB_EMBEDDED + layout->addWidget( label, 3, 1 ); +#ifndef KAB_EMBEDDED + layout->addWidget( mFormattedNameLabel, 3, 2 ); +#else //KAB_EMBEDDED +qDebug("AddresseeEditorWidget::setupTab1 has to be changed"); +#endif //KAB_EMBEDDED + + // Left hand separator. This separator doesn't go all the way + // across so the dialog still flows from top to bottom + bar = new KSeparator( KSeparator::HLine, tab1 ); + layout->addMultiCellWidget( bar, 4, 4, 0, 2 ); + + ////////////////////////////////////// + // Phone numbers (upper right) + label = new QLabel( tab1 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "kaddressbook", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "kaddressbook", KIcon::Desktop, 0 ) ); + layout->addMultiCellWidget( label, 0, 1, 3, 3 ); + + mPhoneEditWidget = new PhoneEditWidget( tab1 ); + connect( mPhoneEditWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); + layout->addMultiCellWidget( mPhoneEditWidget, 0, 3, 4, 6 ); + + bar = new KSeparator( KSeparator::HLine, tab1 ); + layout->addMultiCellWidget( bar, 4, 4, 3, 6 ); +*/ + ////////////////////////////////////// + // Addresses (lower left) + /* LR + label = new QLabel( tab1_1 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "gohome", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "gohome", KIcon::Desktop, 0 ) ); +//US layout->addMultiCellWidget( label, 5, 6, 0, 0 ); + layout->addMultiCellWidget( label, 0, 1, 0, 0 ); + */ + + mAddressEditWidget = new AddressEditWidget( tab1_1 ); + connect( mAddressEditWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); +//US layout->addMultiCellWidget( mAddressEditWidget, 5, 9, 1, 2 ); + layout->addMultiCellWidget( mAddressEditWidget, 0, 4, 0, 1 ); + +//US +/* LR + bar = new KSeparator( KSeparator::HLine, tab1_1 ); + layout->addMultiCellWidget( bar, 5, 5, 0, 3 ); +*/ + + ////////////////////////////////////// + // Email / Web (lower right) + /* LR + label = new QLabel( tab1_1 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "email", KIcon::Desktop) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "email", KIcon::Desktop, 0) ); +//US layout->addMultiCellWidget( label, 5, 6, 3, 3 ); + layout->addMultiCellWidget( label, 6, 7, 0, 0 ); + */ + mEmailWidget = new EmailEditWidget( tab1_1 ); + connect( mEmailWidget, SIGNAL( modified() ), SLOT( emitModified() ) ); +//US layout->addMultiCellWidget( mEmailWidget, 5, 6, 4, 6 ); + layout->addMultiCellWidget( mEmailWidget, 5, 6, 0, 1 ); + + /* LR + // add the separator + bar = new KSeparator( KSeparator::HLine, tab1_1 ); +//US layout->addMultiCellWidget( bar, 7, 7, 3, 6 ); + layout->addMultiCellWidget( bar, 8, 8, 0, 3 ); + + label = new QLabel( tab1_1 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "homepage", KIcon::Desktop) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "homepage", KIcon::Desktop, 0) ); +//US layout->addMultiCellWidget( label, 8, 9, 3, 3 ); + layout->addMultiCellWidget( label, 9, 10, 0, 0 ); + */ + label = new QLabel( i18n( "URL:" ), tab1_1 ); + mURLEdit = new KLineEdit( tab1_1 ); + connect( mURLEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mURLEdit ); +//US layout->addWidget( label, 8, 4 ); + layout->addWidget( label, 7,0 ); +//US layout->addMultiCellWidget( mURLEdit, 8, 8, 5, 6 ); + layout->addWidget( mURLEdit, 7, 1); + + label = new QLabel( i18n( "&IM address:" ), tab1_1 ); + mIMAddressEdit = new KLineEdit( tab1_1 ); + connect( mIMAddressEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mIMAddressEdit ); +//US layout->addWidget( label, 9, 4 ); + layout->addWidget( label, 8, 0 ); +//US layout->addMultiCellWidget( mIMAddressEdit, 9, 9, 5, 6 ); + layout->addWidget( mIMAddressEdit, 8,1 ); + +//US layout->addColSpacing( 6, 50 ); + +//US bar = new KSeparator( KSeparator::HLine, tab1_1 ); +//US layout->addMultiCellWidget( bar, 10, 10, 0, 6 ); + +/*US + /////////////////////////////////////// + QHBox *categoryBox = new QHBox( tab1 ); + categoryBox->setSpacing( KDialogBase::spacingHintSmall() ); + + // Categories + button = new QPushButton( i18n( "Categories" ), categoryBox ); + connect( button, SIGNAL( clicked() ), SLOT( categoryButtonClicked() ) ); + + mCategoryEdit = new KLineEdit( categoryBox ); + mCategoryEdit->setReadOnly( true ); + connect( mCategoryEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + + mSecrecyWidget = new SecrecyWidget( categoryBox ); + connect( mSecrecyWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + + layout->addMultiCellWidget( categoryBox, 11, 11, 0, 6 ); +*/ + // Build the layout and add to the tab widget + layout->activate(); // required + + mTabWidget->addTab( tab1_1, i18n( "&Address" ) ); +} + + + +void AddresseeEditorWidget::setupTab2() +{ + // This is the Details tab + QWidget *tab2 = new QWidget( mTabWidget ); + + QGridLayout *layout = new QGridLayout( tab2, 8, 3 ); + layout->setMargin( KDialogBase::marginHintSmall() ); + layout->setSpacing( KDialogBase::spacingHintSmall() ); + + QLabel *label; + KSeparator* bar; + + /////////////////////// + // Office info + + // Department + label = new QLabel( tab2 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "folder", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "folder", KIcon::Desktop, 0 ) ); + layout->addMultiCellWidget( label, 0, 1, 0, 0 ); + + label = new QLabel( i18n( "Department:" ), tab2 ); + layout->addWidget( label, 0, 1 ); + mDepartmentEdit = new KLineEdit( tab2 ); + connect( mDepartmentEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mDepartmentEdit ); + layout->addWidget( mDepartmentEdit, 0, 2 ); + + label = new QLabel( i18n( "Office:" ), tab2 ); + layout->addWidget( label, 1, 1 ); + mOfficeEdit = new KLineEdit( tab2 ); + connect( mOfficeEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mOfficeEdit ); + layout->addWidget( mOfficeEdit, 1, 2 ); + + label = new QLabel( i18n( "Profession:" ), tab2 ); + layout->addWidget( label, 2, 1 ); + mProfessionEdit = new KLineEdit( tab2 ); + connect( mProfessionEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mProfessionEdit ); + layout->addWidget( mProfessionEdit, 2, 2 ); + + label = new QLabel( i18n( "Manager\'s name:" ), tab2 ); +//US layout->addWidget( label, 0, 3 ); + layout->addWidget( label, 3, 1 ); + mManagerEdit = new KLineEdit( tab2 ); + connect( mManagerEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mManagerEdit ); +//US layout->addMultiCellWidget( mManagerEdit, 0, 0, 4, 5 ); + layout->addWidget( mManagerEdit, 3, 2 ); + + label = new QLabel( i18n( "Assistant's name:" ), tab2 ); +//US layout->addWidget( label, 1, 3 ); + layout->addWidget( label, 4, 1 ); + mAssistantEdit = new KLineEdit( tab2 ); + connect( mAssistantEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mAssistantEdit ); +//US layout->addMultiCellWidget( mAssistantEdit, 1, 1, 4, 5 ); + layout->addWidget( mAssistantEdit, 4, 2 ); + + bar = new KSeparator( KSeparator::HLine, tab2 ); +//US layout->addMultiCellWidget( bar, 3, 3, 0, 5 ); + layout->addMultiCellWidget( bar, 5, 5, 0, 2 ); + + ///////////////////////////////////////////////// + // Personal info + + label = new QLabel( tab2 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop, 0 ) ); +//US layout->addMultiCellWidget( label, 4, 5, 0, 0 ); + layout->addMultiCellWidget( label, 6, 7, 0, 0 ); + + label = new QLabel( i18n( "Nick name:" ), tab2 ); +//US layout->addWidget( label, 4, 1 ); + layout->addWidget( label, 6, 1 ); + mNicknameEdit = new KLineEdit( tab2 ); + connect( mNicknameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mNicknameEdit ); +//US layout->addWidget( mNicknameEdit, 4, 2 ); + layout->addWidget( mNicknameEdit, 6, 2 ); + + label = new QLabel( i18n( "Spouse's name:" ), tab2 ); +//US layout->addWidget( label, 5, 1 ); + layout->addWidget( label, 7, 1 ); + mSpouseEdit = new KLineEdit( tab2 ); + connect( mSpouseEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mSpouseEdit ); +//US layout->addWidget( mSpouseEdit, 5, 2 ); + layout->addWidget( mSpouseEdit, 7, 2 ); + + label = new QLabel( i18n( "Birthday:" ), tab2 ); +//US layout->addWidget( label, 4, 3 ); + layout->addWidget( label, 8, 1 ); + mBirthdayPicker = new KDateEdit( tab2 ); + mBirthdayPicker->setHandleInvalid( true ); + connect( mBirthdayPicker, SIGNAL( dateChanged( QDate ) ), + SLOT( dateChanged( QDate ) ) ); + + +#ifndef KAB_EMBEDDED + //US invalid dates are handdled by the KDateEdit widget itself + connect( mBirthdayPicker, SIGNAL( invalidDateEntered() ), + SLOT( invalidDate() ) ); + connect( mBirthdayPicker, SIGNAL( textChanged( const QString& ) ), + SLOT( emitModified() ) ); +#endif //KAB_EMBEDDED + + label->setBuddy( mBirthdayPicker ); +//US layout->addWidget( mBirthdayPicker, 4, 4 ); + layout->addWidget( mBirthdayPicker, 8, 2 ); + + label = new QLabel( i18n( "Anniversary:" ), tab2 ); +//US layout->addWidget( label, 5, 3 ); + layout->addWidget( label, 9, 1 ); + mAnniversaryPicker = new KDateEdit( tab2 ); + mAnniversaryPicker->setHandleInvalid( true ); + connect( mAnniversaryPicker, SIGNAL( dateChanged( QDate ) ), + SLOT( dateChanged( QDate ) ) ); +#ifndef KAB_EMBEDDED + //US invalid dates are handled by the KDateEdit widget itself + connect( mAnniversaryPicker, SIGNAL( invalidDateEntered() ), + SLOT( invalidDate() ) ); + connect( mAnniversaryPicker, SIGNAL( textChanged( const QString& ) ), + SLOT( emitModified() ) ); +#endif //KAB_EMBEDDED + + label->setBuddy( mAnniversaryPicker ); +//US layout->addWidget( mAnniversaryPicker, 5, 4 ); + layout->addWidget( mAnniversaryPicker, 9, 2 ); + +/*US + bar = new KSeparator( KSeparator::HLine, tab2 ); + layout->addMultiCellWidget( bar, 6, 6, 0, 5 ); + + ////////////////////////////////////// + // Notes + label = new QLabel( i18n( "Note:" ), tab2 ); + label->setAlignment( Qt::AlignTop | Qt::AlignLeft ); + layout->addWidget( label, 7, 0 ); +#ifndef KAB_EMBEDDED + mNoteEdit = new QTextEdit( tab2 ); + mNoteEdit->setWordWrap( QTextEdit::WidgetWidth ); + mNoteEdit->setMinimumSize( mNoteEdit->sizeHint() ); +#else //KAB_EMBEDDED + mNoteEdit = new QMultiLineEdit( tab2 ); +//US mNoteEdit->setWordWrap( QTextEdit::WidgetWidth ); +//US mNoteEdit->setMinimumSize( mNoteEdit->sizeHint() ); +qDebug("AddresseeEditorWidget::setupTab2 has to be changed"); +#endif //KAB_EMBEDDED + connect( mNoteEdit, SIGNAL( textChanged() ), SLOT( emitModified() ) ); + label->setBuddy( mNoteEdit ); + layout->addMultiCellWidget( mNoteEdit, 7, 7, 1, 5 ); +*/ + // Build the layout and add to the tab widget + layout->activate(); // required + + mTabWidget->addTab( tab2, i18n( "&Details" ) ); +} + +void AddresseeEditorWidget::setupTab2_1() +{ + // This is the Details tab + QWidget *tab2_2 = new QWidget( mTabWidget ); + + QGridLayout *layout = new QGridLayout( tab2_2, 1, 2 ); + layout->setMargin( KDialogBase::marginHintSmall() ); + layout->setSpacing( KDialogBase::spacingHintSmall() ); + + QLabel *label; + KSeparator* bar; + +/*US + /////////////////////// + // Office info + + // Department + label = new QLabel( tab2 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "folder", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "folder", KIcon::Desktop, 0 ) ); + layout->addMultiCellWidget( label, 0, 1, 0, 0 ); + + label = new QLabel( i18n( "Department:" ), tab2 ); + layout->addWidget( label, 0, 1 ); + mDepartmentEdit = new KLineEdit( tab2 ); + connect( mDepartmentEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mDepartmentEdit ); + layout->addWidget( mDepartmentEdit, 0, 2 ); + + label = new QLabel( i18n( "Office:" ), tab2 ); + layout->addWidget( label, 1, 1 ); + mOfficeEdit = new KLineEdit( tab2 ); + connect( mOfficeEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mOfficeEdit ); + layout->addWidget( mOfficeEdit, 1, 2 ); + + label = new QLabel( i18n( "Profession:" ), tab2 ); + layout->addWidget( label, 2, 1 ); + mProfessionEdit = new KLineEdit( tab2 ); + connect( mProfessionEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mProfessionEdit ); + layout->addWidget( mProfessionEdit, 2, 2 ); + + label = new QLabel( i18n( "Manager\'s name:" ), tab2 ); + layout->addWidget( label, 0, 3 ); + mManagerEdit = new KLineEdit( tab2 ); + connect( mManagerEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mManagerEdit ); + layout->addMultiCellWidget( mManagerEdit, 0, 0, 4, 5 ); + + label = new QLabel( i18n( "Assistant's name:" ), tab2 ); + layout->addWidget( label, 1, 3 ); + mAssistantEdit = new KLineEdit( tab2 ); + connect( mAssistantEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mAssistantEdit ); + layout->addMultiCellWidget( mAssistantEdit, 1, 1, 4, 5 ); + + bar = new KSeparator( KSeparator::HLine, tab2 ); + layout->addMultiCellWidget( bar, 3, 3, 0, 5 ); + + ///////////////////////////////////////////////// + // Personal info + + label = new QLabel( tab2 ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop, 0 ) ); + layout->addMultiCellWidget( label, 4, 5, 0, 0 ); + + label = new QLabel( i18n( "Nick name:" ), tab2 ); + layout->addWidget( label, 4, 1 ); + mNicknameEdit = new KLineEdit( tab2 ); + connect( mNicknameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mNicknameEdit ); + layout->addWidget( mNicknameEdit, 4, 2 ); + + label = new QLabel( i18n( "Spouse's name:" ), tab2 ); + layout->addWidget( label, 5, 1 ); + mSpouseEdit = new KLineEdit( tab2 ); + connect( mSpouseEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + label->setBuddy( mSpouseEdit ); + layout->addWidget( mSpouseEdit, 5, 2 ); + + label = new QLabel( i18n( "Birthday:" ), tab2 ); + layout->addWidget( label, 4, 3 ); + mBirthdayPicker = new KDateEdit( tab2 ); + mBirthdayPicker->setHandleInvalid( true ); + connect( mBirthdayPicker, SIGNAL( dateChanged( QDate ) ), + SLOT( dateChanged( QDate ) ) ); + connect( mBirthdayPicker, SIGNAL( invalidDateEntered() ), + SLOT( invalidDate() ) ); + connect( mBirthdayPicker, SIGNAL( textChanged( const QString& ) ), + SLOT( emitModified() ) ); + label->setBuddy( mBirthdayPicker ); + layout->addWidget( mBirthdayPicker, 4, 4 ); + + label = new QLabel( i18n( "Anniversary:" ), tab2 ); + layout->addWidget( label, 5, 3 ); + mAnniversaryPicker = new KDateEdit( tab2 ); + mAnniversaryPicker->setHandleInvalid( true ); + connect( mAnniversaryPicker, SIGNAL( dateChanged( QDate ) ), + SLOT( dateChanged( QDate ) ) ); + connect( mAnniversaryPicker, SIGNAL( invalidDateEntered() ), + SLOT( invalidDate() ) ); + connect( mAnniversaryPicker, SIGNAL( textChanged( const QString& ) ), + SLOT( emitModified() ) ); + label->setBuddy( mAnniversaryPicker ); + layout->addWidget( mAnniversaryPicker, 5, 4 ); + + bar = new KSeparator( KSeparator::HLine, tab2 ); + layout->addMultiCellWidget( bar, 6, 6, 0, 5 ); +*/ + ////////////////////////////////////// + // Notes + label = new QLabel( i18n( "Note:" ), tab2_2 ); + label->setAlignment( Qt::AlignTop | Qt::AlignLeft ); +//US layout->addWidget( label, 7, 0 ); + layout->addWidget( label, 0, 0 ); +#ifndef KAB_EMBEDDED + mNoteEdit = new QTextEdit( tab2_2 ); + mNoteEdit->setWordWrap( QTextEdit::WidgetWidth ); + mNoteEdit->setMinimumSize( mNoteEdit->sizeHint() ); +#else //KAB_EMBEDDED + mNoteEdit = new QMultiLineEdit( tab2_2 ); + mNoteEdit->setWordWrap( QMultiLineEdit::WidgetWidth ); + mNoteEdit->setMinimumSize( mNoteEdit->sizeHint() ); +#endif //KAB_EMBEDDED + + connect( mNoteEdit, SIGNAL( textChanged() ), SLOT( emitModified() ) ); + label->setBuddy( mNoteEdit ); +//US layout->addMultiCellWidget( mNoteEdit, 7, 7, 1, 5 ); + layout->addWidget( mNoteEdit, 1, 0); + + // Build the layout and add to the tab widget + layout->activate(); // required + + mTabWidget->addTab( tab2_2, i18n( "&Notes" ) ); +} + + + +void AddresseeEditorWidget::setupTab3() +{ + // This is the Misc tab + QWidget *tab3 = new QWidget( mTabWidget ); + + QGridLayout *layout = new QGridLayout( tab3, 1, 1 ); + layout->setMargin( KDialogBase::marginHintSmall() ); + layout->setSpacing( KDialogBase::spacingHintSmall() ); +//US layout->setColStretch( 2, 1 ); + + ////////////////////////////////////// + // Geo + mGeoWidget = new GeoWidget( tab3 ); + // mGeoWidget->setMinimumSize( mGeoWidget->sizeHint() ); + connect( mGeoWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + layout->addWidget( mGeoWidget, 0, 0 ); +/*US + ////////////////////////////////////// + // Sound +#ifndef KAB_EMBEDDED + mSoundWidget = new SoundWidget( tab3 ); + mSoundWidget->setMinimumSize( mSoundWidget->sizeHint() ); + connect( mSoundWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + layout->addWidget( mSoundWidget, 0, 1, Qt::AlignTop ); +#else //KAB_EMBEDDED +qDebug("AddresseeEditorWidget::setupTab2 sound part is not supported = has to be changed"); +#endif //KAB_EMBEDDED + + ////////////////////////////////////// + // Images + mImageWidget = new ImageWidget( tab3 ); + mImageWidget->setMinimumSize( mImageWidget->sizeHint() ); + connect( mImageWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + layout->addWidget( mImageWidget, 1, 0, Qt::AlignTop ); +*/ +//US +/* + KSeparator* bar = new KSeparator( KSeparator::HLine, tab3 ); + layout->addMultiCellWidget( bar, 1, 1, 0, 0 ); +*/ + ////////////////////////////////////// + // Keys + mKeyWidget = new KeyWidget( tab3 ); + //mKeyWidget->setMinimumSize( mKeyWidget->sizeHint() ); + connect( mKeyWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); +//US layout->addWidget( mKeyWidget, 1, 1, Qt::AlignTop ); + layout->addWidget( mKeyWidget, 1, 0 ); + + mTabWidget->addTab( tab3, i18n( "&Misc" ) ); +} + +void AddresseeEditorWidget::setupTab3_1() +{ + // This is the Misc tab + QWidget *tab3 = new QWidget( mTabWidget ); + +//US QGridLayout *layout = new QGridLayout( tab3, 2, 3 ); + QGridLayout *layout = new QGridLayout( tab3, 1, 1 ); + layout->setMargin( KDialogBase::marginHint() ); + layout->setSpacing( KDialogBase::spacingHint() ); +//US layout->setColStretch( 2, 1 ); + +/*US + ////////////////////////////////////// + // Geo + mGeoWidget = new GeoWidget( tab3 ); + mGeoWidget->setMinimumSize( mGeoWidget->sizeHint() ); + connect( mGeoWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + layout->addWidget( mGeoWidget, 0, 0, Qt::AlignTop ); +*/ + ////////////////////////////////////// + // Sound +#ifndef KAB_EMBEDDED + mSoundWidget = new SoundWidget( tab3 ); + mSoundWidget->setMinimumSize( mSoundWidget->sizeHint() ); + connect( mSoundWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + layout->addWidget( mSoundWidget, 0, 1, Qt::AlignTop ); +#else //KAB_EMBEDDED +//US qDebug("AddresseeEditorWidget::setupTab2 sound part is not supported = has to be changed"); +#endif //KAB_EMBEDDED + + ////////////////////////////////////// + // Images + mImageWidget = new ImageWidget( tab3 ); + mImageWidget->setMinimumSize( mImageWidget->sizeHint() ); + connect( mImageWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + layout->addWidget( mImageWidget, 0, 0, Qt::AlignTop ); +/*US + ////////////////////////////////////// + // Keys + mKeyWidget = new KeyWidget( tab3 ); + mKeyWidget->setMinimumSize( mKeyWidget->sizeHint() ); + connect( mKeyWidget, SIGNAL( changed() ), SLOT( emitModified() ) ); + layout->addWidget( mKeyWidget, 1, 1, Qt::AlignTop ); +*/ + mTabWidget->addTab( tab3, i18n( "&Images" ) ); +} + + +void AddresseeEditorWidget::load() +{ + kdDebug(5720) << "AddresseeEditorWidget::load()" << endl; + + // Block signals in case anything tries to emit modified + // CS: This doesn't seem to work. + bool block = signalsBlocked(); + blockSignals( true ); + mBlockSignals = true; // used for internal signal blocking + + mNameEdit->setText( mAddressee.assembledName() ); + + if ( mAddressee.formattedName().isEmpty() ) { +//US KConfig config( "kaddressbookrc" ); + KConfig config( locateLocal("config", "kaddressbookrc") ); + config.setGroup( "General" ); + mFormattedNameType = config.readNumEntry( "FormattedNameType", 1 ); + mAddressee.setFormattedName( NameEditDialog::formattedName( mAddressee, mFormattedNameType ) ); + } else { + if ( mAddressee.formattedName() == NameEditDialog::formattedName( mAddressee, NameEditDialog::SimpleName ) ) + mFormattedNameType = NameEditDialog::SimpleName; + else if ( mAddressee.formattedName() == NameEditDialog::formattedName( mAddressee, NameEditDialog::FullName ) ) + mFormattedNameType = NameEditDialog::FullName; + else if ( mAddressee.formattedName() == NameEditDialog::formattedName( mAddressee, NameEditDialog::ReverseName ) ) + mFormattedNameType = NameEditDialog::ReverseName; + else + mFormattedNameType = NameEditDialog::CustomName; + } + + mFormattedNameLabel->setText( mAddressee.formattedName() ); + + mRoleEdit->setText( mAddressee.role() ); + mOrgEdit->setText( mAddressee.organization() ); + +//US mURLEdit->setURL( mAddressee.url().url() ); + mURLEdit->setText( mAddressee.url().prettyURL() ); +//US?? mURLEdit->home( false ); + + // mNoteEdit->setText( mAddressee.note() ); + mNoteEdit->setText( mAddressee.note() ); + mEmailWidget->setEmails( mAddressee.emails() ); + mPhoneEditWidget->setPhoneNumbers( mAddressee.phoneNumbers() ); + mAddressEditWidget->setAddresses( mAddressee, mAddressee.addresses() ); + mBirthdayPicker->setDate( mAddressee.birthday().date() ); + +//US mAnniversaryPicker->setDate( QDate::fromString( mAddressee.custom( +//US "KADDRESSBOOK", "X-Anniversary" ), Qt::ISODate) ); + QDate dt = KGlobal::locale()->readDate( mAddressee.custom("KADDRESSBOOK", "X-Anniversary" ), + "%Y-%m-%d"); // = Qt::ISODate + mAnniversaryPicker->setDate( dt ); + + + mNicknameEdit->setText( mAddressee.nickName() ); + mCategoryEdit->setText( mAddressee.categories().join( "," ) ); + + mGeoWidget->setGeo( mAddressee.geo() ); + mImageWidget->setPhoto( mAddressee.photo() ); + mImageWidget->setLogo( mAddressee.logo() ); + mKeyWidget->setKeys( mAddressee.keys() ); + mSecrecyWidget->setSecrecy( mAddressee.secrecy() ); +#ifndef KAB_EMBEDDED + mSoundWidget->setSound( mAddressee.sound() ); +#else //KAB_EMBEDDED +//US qDebug("AddresseeEditorWidget::load has to be changed 2"); +#endif //KAB_EMBEDDED + + // Load customs + mIMAddressEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-IMAddress" ) ); + mSpouseEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-SpousesName" ) ); + mManagerEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-ManagersName" ) ); + mAssistantEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-AssistantsName" ) ); + mDepartmentEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-Department" ) ); + mOfficeEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-Office" ) ); + mProfessionEdit->setText( mAddressee.custom( "KADDRESSBOOK", "X-Profession" ) ); + + blockSignals( block ); + mBlockSignals = false; + + mDirty = false; +} + +void AddresseeEditorWidget::save() +{ + if ( !mDirty ) return; + + mAddressee.setRole( mRoleEdit->text() ); + mAddressee.setOrganization( mOrgEdit->text() ); + mAddressee.setUrl( KURL( mURLEdit->text() ) ); + mAddressee.setNote( mNoteEdit->text() ); + if ( mBirthdayPicker->inputIsValid() ) + mAddressee.setBirthday( QDateTime( mBirthdayPicker->date() ) ); + else + mAddressee.setBirthday( QDateTime() ); + + mAddressee.setNickName( mNicknameEdit->text() ); + mAddressee.setCategories( QStringList::split( ",", mCategoryEdit->text() ) ); + + mAddressee.setGeo( mGeoWidget->geo() ); + mAddressee.setPhoto( mImageWidget->photo() ); + mAddressee.setLogo( mImageWidget->logo() ); + mAddressee.setKeys( mKeyWidget->keys() ); +#ifndef KAB_EMBEDDED + mAddressee.setSound( mSoundWidget->sound() ); +#else //KAB_EMBEDDED +//US qDebug("AddresseeEditorWidget::save sound not supported"); +#endif //KAB_EMBEDDED + mAddressee.setSecrecy( mSecrecyWidget->secrecy() ); + + // save custom fields + mAddressee.insertCustom( "KADDRESSBOOK", "X-IMAddress", mIMAddressEdit->text() ); + mAddressee.insertCustom( "KADDRESSBOOK", "X-SpousesName", mSpouseEdit->text() ); + mAddressee.insertCustom( "KADDRESSBOOK", "X-ManagersName", mManagerEdit->text() ); + mAddressee.insertCustom( "KADDRESSBOOK", "X-AssistantsName", mAssistantEdit->text() ); + mAddressee.insertCustom( "KADDRESSBOOK", "X-Department", mDepartmentEdit->text() ); + mAddressee.insertCustom( "KADDRESSBOOK", "X-Office", mOfficeEdit->text() ); + mAddressee.insertCustom( "KADDRESSBOOK", "X-Profession", mProfessionEdit->text() ); + if ( mAnniversaryPicker->inputIsValid() ) { + +//US mAddressee.insertCustom( "KADDRESSBOOK", "X-Anniversary", +//US mAnniversaryPicker->date().toString( Qt::ISODate ) ); + int orgformat = KGlobal::locale()->getIntDateFormat(); + QDate da = mAnniversaryPicker->date(); + KGlobal::locale()->setIntDateFormat( 2 ); // = Qt::ISODate + QString dt = KGlobal::locale()->formatDate(da, true); + KGlobal::locale()->setIntDateFormat(orgformat ); + mAddressee.insertCustom( "KADDRESSBOOK", "X-Anniversary", dt); + } + else + mAddressee.removeCustom( "KADDRESSBOOK", "X-Anniversary" ); + + // Save the email addresses + QStringList emails = mAddressee.emails(); + QStringList::Iterator iter; + for ( iter = emails.begin(); iter != emails.end(); ++iter ) + mAddressee.removeEmail( *iter ); + + emails = mEmailWidget->emails(); + bool first = true; + for ( iter = emails.begin(); iter != emails.end(); ++iter ) { + mAddressee.insertEmail( *iter, first ); + first = false; + } + + // Save the phone numbers + KABC::PhoneNumber::List phoneNumbers; + KABC::PhoneNumber::List::Iterator phoneIter; + phoneNumbers = mAddressee.phoneNumbers(); + for ( phoneIter = phoneNumbers.begin(); phoneIter != phoneNumbers.end(); + ++phoneIter ) + mAddressee.removePhoneNumber( *phoneIter ); + + phoneNumbers = mPhoneEditWidget->phoneNumbers(); + for ( phoneIter = phoneNumbers.begin(); phoneIter != phoneNumbers.end(); + ++phoneIter ) + mAddressee.insertPhoneNumber( *phoneIter ); + + // Save the addresses + KABC::Address::List addresses; + KABC::Address::List::Iterator addressIter; + addresses = mAddressee.addresses(); + for ( addressIter = addresses.begin(); addressIter != addresses.end(); + ++addressIter ) + mAddressee.removeAddress( *addressIter ); + + addresses = mAddressEditWidget->addresses(); + for ( addressIter = addresses.begin(); addressIter != addresses.end(); + ++addressIter ) + mAddressee.insertAddress( *addressIter ); + mDirty = false; +} + +bool AddresseeEditorWidget::dirty() +{ + return mDirty; +} + +void AddresseeEditorWidget::nameTextChanged( const QString &text ) +{ + // use the addressee class to parse the name for us + mAConfig->setUid( mAddressee.uid() ); + if ( mAConfig->automaticNameParsing() ) { + if ( !mAddressee.formattedName().isEmpty() ) { + QString fn = mAddressee.formattedName(); + mAddressee.setNameFromString( text ); + mAddressee.setFormattedName( fn ); + } else { + // use extra addressee to avoid a formatted name assignment + Addressee addr; + addr.setNameFromString( text ); + mAddressee.setPrefix( addr.prefix() ); + mAddressee.setGivenName( addr.givenName() ); + mAddressee.setAdditionalName( addr.additionalName() ); + mAddressee.setFamilyName( addr.familyName() ); + mAddressee.setSuffix( addr.suffix() ); + } + } + + nameBoxChanged(); + + emitModified(); +} + +void AddresseeEditorWidget::nameBoxChanged() +{ + KABC::Addressee addr; + mAConfig->setUid( mAddressee.uid() ); + if ( mAConfig->automaticNameParsing() ) { + addr.setNameFromString( mNameEdit->text() ); + mNameLabel->hide(); + mNameEdit->show(); + } else { + addr = mAddressee; + mNameEdit->hide(); + mNameLabel->setText( mNameEdit->text() ); + mNameLabel->show(); + } + + if ( mFormattedNameType != NameEditDialog::CustomName ) { + mFormattedNameLabel->setText( NameEditDialog::formattedName( mAddressee, mFormattedNameType ) ); + mAddressee.setFormattedName( NameEditDialog::formattedName( mAddressee, mFormattedNameType ) ); + } +} + +void AddresseeEditorWidget::nameButtonClicked() +{ + // show the name dialog. + NameEditDialog dialog( mAddressee, mFormattedNameType, this ); + + if ( dialog.exec() ) { + if ( dialog.changed() ) { + mAddressee.setFamilyName( dialog.familyName() ); + mAddressee.setGivenName( dialog.givenName() ); + mAddressee.setPrefix( dialog.prefix() ); + mAddressee.setSuffix( dialog.suffix() ); + mAddressee.setAdditionalName( dialog.additionalName() ); + mFormattedNameType = dialog.formattedNameType(); + if ( mFormattedNameType == NameEditDialog::CustomName ) { + mFormattedNameLabel->setText( dialog.customFormattedName() ); + mAddressee.setFormattedName( dialog.customFormattedName() ); + } + // Update the name edit. + bool block = mNameEdit->signalsBlocked(); + mNameEdit->blockSignals( true ); + mNameEdit->setText( mAddressee.assembledName() ); + mNameEdit->blockSignals( block ); + + // Update the combo box. + nameBoxChanged(); + + emitModified(); + } + } +} + +void AddresseeEditorWidget::categoryButtonClicked() +{ + // Show the category dialog + if ( mCategoryDialog == 0 ) { + mCategoryDialog = new KPIM::CategorySelectDialog( KABPrefs::instance(), this ); + connect( mCategoryDialog, SIGNAL( categoriesSelected( const QStringList& ) ), + SLOT(categoriesSelected( const QStringList& ) ) ); + connect( mCategoryDialog, SIGNAL( editCategories() ), SLOT( editCategories() ) ); + } + + mCategoryDialog->setCategories(); + mCategoryDialog->setSelected( QStringList::split( ",", mCategoryEdit->text() ) ); + mCategoryDialog->show(); + mCategoryDialog->raise(); +} + +void AddresseeEditorWidget::categoriesSelected( const QStringList &list ) +{ + mCategoryEdit->setText( list.join( "," ) ); +} + +void AddresseeEditorWidget::editCategories() +{ + if ( mCategoryEditDialog == 0 ) { + mCategoryEditDialog = new KPIM::CategoryEditDialog( KABPrefs::instance(), this ); + connect( mCategoryEditDialog, SIGNAL( categoryConfigChanged() ), + SLOT( categoryButtonClicked() ) ); + } + + mCategoryEditDialog->show(); + mCategoryEditDialog->raise(); +} + +void AddresseeEditorWidget::emitModified() +{ + mDirty = true; + + KABC::Addressee::List list; + + if ( mIsExtension && !mBlockSignals ) { + save(); + list.append( mAddressee ); + } + + emit modified( list ); +} + +void AddresseeEditorWidget::dateChanged( QDate ) +{ + emitModified(); +} + +//US invalid dates are handdled by the KDateEdit widget itself +void AddresseeEditorWidget::invalidDate() +{ + KMessageBox::sorry( this, i18n( "You must specify a valid date" ) ); +} + + +void AddresseeEditorWidget::pageChanged( QWidget *wdg ) +{ +#ifndef KAB_EMBEDDED + if ( wdg ) + KAcceleratorManager::manage( wdg ); +#else //KAB_EMBEDDED +//US +#endif //KAB_EMBEDDED + +} + +QString AddresseeEditorWidget::title() const +{ + return i18n( "Contact Editor" ); +} + +QString AddresseeEditorWidget::identifier() const +{ + return i18n( "contact_editor" ); +} + +#ifndef KAB_EMBEDDED +#include "addresseeeditorwidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/addresseeeditorwidget.h b/kaddressbook/addresseeeditorwidget.h new file mode 100644 index 0000000..b9d9e25 --- a/dev/null +++ b/kaddressbook/addresseeeditorwidget.h @@ -0,0 +1,184 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef ADDRESSEEEDITORWIDGET_H +#define ADDRESSEEEDITORWIDGET_H + +#include <qdatetime.h> + +#include <kabc/addressee.h> +#include <kdialogbase.h> +#include <kjanuswidget.h> + +#include "extensionwidget.h" + +class AddresseeConfig; +class QCheckBox; +class QSpinBox; +class QTabWidget; + +#ifndef KAB_EMBEDDED +class QTextEdit; +#else //KAB_EMBEDDED +class QMultiLineEdit; +#endif //KAB_EMBEDDED + +class KComboBox; +class KDateEdit; +class KLineEdit; +class KSqueezedTextLabel; + +class AddressEditWidget; +class EmailEditWidget; +class GeoWidget; +class ImageWidget; +class KABCore; +class KeyWidget; +class PhoneEditWidget; +class SecrecyWidget; +class SoundWidget; + +namespace KPIM +{ + class CategorySelectDialog; + class CategoryEditDialog; +} + +namespace KABC { class AddressBook; } + +class AddresseeEditorWidget : public ExtensionWidget +{ + Q_OBJECT + + public: + AddresseeEditorWidget( KABCore *core, bool isExtension, + QWidget *parent, const char *name = 0 ); + ~AddresseeEditorWidget(); + + void setAddressee( const KABC::Addressee& ); + const KABC::Addressee &addressee(); + + void contactsSelectionChanged(); + + void load(); + void save(); + + bool dirty(); + + QString title() const; + QString identifier() const; + + protected slots: + void textChanged( const QString& ); + void pageChanged( QWidget *wdg ); + + /** + Emits the modified signal and sets the dirty flag. Any slot + that modifies data should use this method instead of calling emit + modified() directly. + */ + void emitModified(); + + void dateChanged( QDate ); + void invalidDate(); + void nameTextChanged( const QString& ); + void nameBoxChanged(); + void nameButtonClicked(); + void categoryButtonClicked(); + + /** + Called whenever the categories change in the categories dialog. + */ + void categoriesSelected( const QStringList& ); + + /** + Edits which categories are available in the CategorySelectDialog. + */ + void editCategories(); + + private: + AddresseeConfig * mAConfig; + void initGUI(); + void setupTab1(); + void setupTab1_1(); + void setupTab2(); + void setupTab2_1(); + void setupTab3(); + void setupTab3_1(); + + KABC::Addressee mAddressee; + int mFormattedNameType; + bool mDirty; + bool mIsExtension; + bool mBlockSignals; + + // GUI + KPIM::CategorySelectDialog *mCategoryDialog; + KPIM::CategoryEditDialog *mCategoryEditDialog; + QTabWidget *mTabWidget; + + // Tab1 and Tab1_1 + KLineEdit *mNameEdit; + KLineEdit *mRoleEdit; + KLineEdit *mOrgEdit; + + KSqueezedTextLabel *mFormattedNameLabel; + AddressEditWidget *mAddressEditWidget; + EmailEditWidget *mEmailWidget; + PhoneEditWidget *mPhoneEditWidget; + KLineEdit *mURLEdit; + KLineEdit *mIMAddressEdit; + KLineEdit *mCategoryEdit; + SecrecyWidget *mSecrecyWidget; + KSqueezedTextLabel *mNameLabel; + + // Tab2 and Tab2_2 + KLineEdit *mDepartmentEdit; + KLineEdit *mOfficeEdit; + KLineEdit *mProfessionEdit; + KLineEdit *mManagerEdit; + KLineEdit *mAssistantEdit; + KLineEdit *mNicknameEdit; + KLineEdit *mSpouseEdit; + KDateEdit *mBirthdayPicker; + KDateEdit *mAnniversaryPicker; +#ifndef KAB_EMBEDDED + QTextEdit *mNoteEdit; +#else //KAB_EMBEDDED + QMultiLineEdit *mNoteEdit; +#endif //KAB_EMBEDDED + + QSpinBox *mTimeZoneSpin; + QSpinBox *mGeoLat; + QSpinBox *mGeoLon; + + // Tab3 + GeoWidget *mGeoWidget; + ImageWidget *mImageWidget; +#ifndef KAB_EMBEDDED + SoundWidget *mSoundWidget; +#endif //KAB_EMBEDDED + KeyWidget *mKeyWidget; +}; + +#endif diff --git a/kaddressbook/addresseeutil.cpp b/kaddressbook/addresseeutil.cpp new file mode 100644 index 0000000..366384a --- a/dev/null +++ b/kaddressbook/addresseeutil.cpp @@ -0,0 +1,66 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kabc/stdaddressbook.h> +#include <kabc/vcardconverter.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "addresseeutil.h" + +QString AddresseeUtil::addresseesToClipboard( const KABC::Addressee::List &list ) +{ + KABC::VCardConverter converter; + QString vcard; + + KABC::Addressee::List::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + QString tmp; + if ( converter.addresseeToVCard( *it, tmp ) ) + vcard += tmp + "\r\n"; + } + + return vcard; +} + +KABC::Addressee::List AddresseeUtil::clipboardToAddressees( const QString &data ) +{ + uint numVCards = data.contains( "BEGIN:VCARD", false ); + QStringList dataList = QStringList::split( "\r\n\r\n", data ); + + KABC::Addressee::List addrList; + for ( uint i = 0; i < numVCards && i < dataList.count(); ++i ) { + KABC::VCardConverter converter; + KABC::Addressee addr; + + if ( !converter.vCardToAddressee( dataList[ i ].stripWhiteSpace(), addr ) ) { + KMessageBox::error( 0, i18n( "Invalid vCard format in clipboard" ) ); + continue; + } + + addrList.append( addr ); + } + + return addrList; +} diff --git a/kaddressbook/addresseeutil.h b/kaddressbook/addresseeutil.h new file mode 100644 index 0000000..2eefc1c --- a/dev/null +++ b/kaddressbook/addresseeutil.h @@ -0,0 +1,61 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef ADDRESSEEUTIL_H +#define ADDRESSEEUTIL_H + +#include <qstring.h> +#include <kabc/addressee.h> + +/** + This class provides some utility methods for transposing an + addressee to different types (ie: clipboard). This class + is probably just temporary until these function stablize and move + to KABC. + + NOTE: Currently these methods are not implemented properly. The + vCard parser in KABC needs to be updated and there is no way to get from + KABC::Addressee to vCard. +*/ +class AddresseeUtil +{ + public: + /** + Same as above function, except that an entire list of KABC::Addressee + objects will be converted to vCard and put in the string. + */ + static QString addresseesToClipboard( const KABC::Addressee::List &addrList ); + + /** + Convert a string from the clipboard into a list of addressee objects. + If the clipboard text was not a valid vcard, an empty list + will be returned. + */ + static KABC::Addressee::List clipboardToAddressees( const QString &clipboard ); + + private: + AddresseeUtil() {} + ~AddresseeUtil() {} +}; + +#endif diff --git a/kaddressbook/addviewdialog.cpp b/kaddressbook/addviewdialog.cpp new file mode 100644 index 0000000..6def26b --- a/dev/null +++ b/kaddressbook/addviewdialog.cpp @@ -0,0 +1,118 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KAB_EMBEDDED +#endif //KAB_EMBEDDED + +#include <qradiobutton.h> +#include <qbuttongroup.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qlayout.h> + +#include <klocale.h> +#include <kglobal.h> +#include "kaddressbookview.h" +#include "addviewdialog.h" + +AddViewDialog::AddViewDialog( QDict<ViewFactory> *viewFactoryDict, + QWidget *parent, const char *name ) + : KDialogBase( KDialogBase::Plain, i18n( "Add View" ), + KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, + parent, name ), + mViewFactoryDict( viewFactoryDict ) +{ +//US setMinimumSize( KMIN(KGlobal::getDesktopWidth(), 300), KMIN(KGlobal::getDesktopHeight(), 300)); + + mTypeId = 0; + + QWidget *page = plainPage(); + + QGridLayout *layout = new QGridLayout( page, 2, 2 ); + layout->setSpacing( spacingHint() ); + layout->setRowStretch( 1, 1 ); + layout->setColStretch( 1, 1 ); + + QLabel *label = new QLabel( i18n( "View name:" ), page ); + layout->addWidget( label, 0, 0 ); + + mViewNameEdit = new QLineEdit( page ); + connect( mViewNameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + layout->addWidget( mViewNameEdit, 0, 1 ); + + mTypeGroup = new QButtonGroup( 2, Qt::Horizontal, i18n( "View Type" ), page ); + connect( mTypeGroup, SIGNAL( clicked( int ) ), this, SLOT( clicked( int ) ) ); + layout->addMultiCellWidget( mTypeGroup, 1, 1, 0, 1 ); + + // Now create the radio buttons. This needs some layout work. + QDictIterator<ViewFactory> iter( *mViewFactoryDict ); + for ( iter.toFirst(); iter.current(); ++iter ) { +//US i am not quit sure, why I can nopt use (*iter)-> here +//US new QRadioButton( (*iter)->type(), mTypeGroup ); +//US label = new QLabel( (*iter)->description(), mTypeGroup ); +#ifdef DESKTOP_VERSION + new QRadioButton( (*iter)->type(), mTypeGroup ); + label = new QLabel( (*iter)->description(), mTypeGroup ); +#else + new QRadioButton( (*iter).type(), mTypeGroup ); + label = new QLabel( (*iter).description(), mTypeGroup ); + +#endif + label->setAlignment( Qt::AlignLeft | Qt::AlignTop | Qt::WordBreak ); + } + + mTypeGroup->setButton( 0 ); + mViewNameEdit->setFocus(); + enableButton( KDialogBase::Ok, false ); + + +} + +AddViewDialog::~AddViewDialog() +{ +} + +QString AddViewDialog::viewName()const +{ + return mViewNameEdit->text(); +} + +QString AddViewDialog::viewType()const +{ + return mTypeGroup->find( mTypeId )->text(); +} + +void AddViewDialog::clicked( int id ) +{ + mTypeId = id; +} + +void AddViewDialog::textChanged( const QString &text ) +{ + enableButton( KDialogBase::Ok, !text.isEmpty() ); +} + +#ifndef KAB_EMBEDDED +#include "addviewdialog.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/addviewdialog.h b/kaddressbook/addviewdialog.h new file mode 100644 index 0000000..8cc12f5 --- a/dev/null +++ b/kaddressbook/addviewdialog.h @@ -0,0 +1,73 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef ADDVIEWDIALOG_H +#define ADDVIEWDIALOG_H + +#include <kdialogbase.h> +#include <qdict.h> +#include <qstring.h> + +class ViewFactory; +class QButtonGroup; +class QLineEdit; + + +/** + Modal dialog used for adding a new view. The dialog asks for the name of + the view as well as the type. Someday it would be nice for this to be a + wizard. + */ +class AddViewDialog : public KDialogBase +{ + Q_OBJECT + + public: + AddViewDialog( QDict<ViewFactory> *viewFactoryDict, QWidget *parent, + const char *name = 0 ); + ~AddViewDialog(); + + QString viewName()const; + + QString viewType()const ; + + protected slots: + /** + Called when the user selects a type radio button. + */ + void clicked( int id ); + + /** + Called when the user changes the text in the name of the view. + */ + void textChanged( const QString &text ); + + private: + QDict<ViewFactory> *mViewFactoryDict; + QLineEdit *mViewNameEdit; + QButtonGroup *mTypeGroup; + + int mTypeId; +}; + +#endif diff --git a/kaddressbook/configurewidget.cpp b/kaddressbook/configurewidget.cpp new file mode 100644 index 0000000..eb57c3a --- a/dev/null +++ b/kaddressbook/configurewidget.cpp @@ -0,0 +1,54 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kabc/addressbook.h> + +#include "configurewidget.h" + + +ConfigureWidget::ConfigureWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name ) + : QWidget( parent, name ), mAddressBook( ab ) +{ + //qDebug("new ConfigureWidget %x ", parent); +} + +ConfigureWidget::~ConfigureWidget() +{ + //qDebug("ConfigureWidget::~ConfigureWidget() "); +} + +void ConfigureWidget::restoreSettings( KConfig* ) +{ + // should be reimplemented in the views, extensions etc. +} + +void ConfigureWidget::saveSettings( KConfig* ) +{ + // should be reimplemented in the views, extensions etc. +} + +KABC::AddressBook *ConfigureWidget::addressBook() const +{ + return mAddressBook; +} diff --git a/kaddressbook/configurewidget.h b/kaddressbook/configurewidget.h new file mode 100644 index 0000000..2528c9d --- a/dev/null +++ b/kaddressbook/configurewidget.h @@ -0,0 +1,67 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef CONFIGUREWIDGET_H +#define CONFIGUREWIDGET_H + + +#include <qwidget.h> +#include <kconfig.h> + +namespace KABC { +class AddressBook; +} + +class ConfigureWidget : public QWidget +{ + public: + ConfigureWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + ~ConfigureWidget(); + + /** + This method is called before the configure dialog is shown. + The widget should reimplement it and fill the GUI with the + values from the config file. + Important: Don't change the group of cfg! + */ + virtual void restoreSettings( KConfig *cfg ); + + /** + This method is called after the user clicked the 'Ok' button. + The widget should reimplement it and save all values from + the GUI to the config file. + Important: Don't change the group of cfg! + */ + virtual void saveSettings( KConfig *cfg ); + + + /** + Returns a pointer to the address book of this widget. + */ + KABC::AddressBook *addressBook() const; + + private: + KABC::AddressBook *mAddressBook; +}; + +#endif diff --git a/kaddressbook/details/detailsviewcontainer.cpp b/kaddressbook/details/detailsviewcontainer.cpp new file mode 100644 index 0000000..8f566cf --- a/dev/null +++ b/kaddressbook/details/detailsviewcontainer.cpp @@ -0,0 +1,171 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qcombobox.h> +#include <qframe.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qwidgetstack.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kdialog.h> + +#include "look_basic.h" +//#include "look_details.h" +#include "look_html.h" + +#ifdef KAB_EMBEDDED +#include "kabprefs.h" +#endif //KAB_EMBEDDED + + +#include "detailsviewcontainer.h" + +ViewContainer::ViewContainer( QWidget *parent, const char* name ) + : QWidget( parent, name ), mCurrentLook( 0 ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); + //topLayout->setMargin( KDialog::marginHint() ); + //topLayout->setSpacing( KDialog::spacingHint() ); + topLayout->setMargin( 0 ); + topLayout->setSpacing( 0 ); + + QBoxLayout *styleLayout = new QHBoxLayout( topLayout ); + + QLabel *label = new QLabel( i18n("Style:"), this ); + styleLayout->addWidget( label ); + + mStyleCombo = new QComboBox( this ); + styleLayout->addWidget( mStyleCombo ); + + QFrame *frameRuler = new QFrame( this ); +//US frameRuler->setFrameShape( QFrame::HLine ); +//US frameRuler->setFrameShadow( QFrame::Sunken ); +//US topLayout->addWidget( frameRuler ); + + mDetailsStack = new QWidgetStack( this ); + topLayout->addWidget( mDetailsStack, 1 ); + + registerLooks(); + +#if 1 + // Hide detailed view selection combo box, because we currently have + // only one. Reenable it when there are more detailed views. + label->hide(); + mStyleCombo->hide(); + frameRuler->hide(); +#endif +} + +KABBasicLook *ViewContainer::currentLook() +{ + return mCurrentLook; +} + +void ViewContainer::registerLooks() +{ + mLookFactories.append( new KABHtmlViewFactory( mDetailsStack ) ); +// mLookFactories.append( new KABDetailedViewFactory( mDetailsStack ) ); + mStyleCombo->clear(); + + for ( uint i = 0; i < mLookFactories.count(); ++i ) + mStyleCombo->insertItem( mLookFactories.at( i )->description() ); + + if ( !mLookFactories.isEmpty() ) + slotStyleSelected( 0 ); +} + +void ViewContainer::slotStyleSelected( int index ) +{ +#ifndef KAB_EMBEDDED + KConfig *config = kapp->config(); +#else //KAB_EMBEDDED + //US I hope I got the same config object as above expected. + KConfig *config = KABPrefs::instance()->getConfig(); +#endif //KAB_EMBEDDED + KABC::Addressee addr; + + if ( index >= 0 && index < mStyleCombo->count() ) { + if ( mCurrentLook != 0 ) { + mCurrentLook->saveSettings( config ); + addr = mCurrentLook->addressee(); + + delete mCurrentLook; + mCurrentLook = 0; + } + + KABLookFactory *factory = mLookFactories.at( index ); + kdDebug(5720) << "ViewContainer::slotStyleSelected: " + << "creating look " + << factory->description() << endl; + + mCurrentLook = factory->create(); + mDetailsStack->raiseWidget( mCurrentLook ); + + connect( mCurrentLook, SIGNAL( sendEmail( const QString& ) ), this, + SIGNAL( sendEmail( const QString& ) ) ); + connect( mCurrentLook, SIGNAL( browse( const QString& ) ), this, + SIGNAL( browse( const QString& ) ) ); + } + + mCurrentLook->restoreSettings( config ); + mCurrentLook->setAddressee( addr ); +} +void ViewContainer::refreshView() +{ + if ( mCurrentLook ) + mCurrentLook->setAddressee( mCurrentAddressee ); +} + +void ViewContainer::setAddressee( const KABC::Addressee& addressee ) +{ + if ( mCurrentLook != 0 ) { + if ( addressee == mCurrentAddressee ) + return; + else { + mCurrentAddressee = addressee; + mCurrentLook->setAddressee( mCurrentAddressee ); + } + } +} + +KABC::Addressee ViewContainer::addressee() +{ + static KABC::Addressee empty; // do not use! + + if ( !mCurrentLook ) + return empty; + else + return mCurrentLook->addressee(); +} + +void ViewContainer::setReadOnly( bool state ) +{ + if ( mCurrentLook ) + mCurrentLook->setReadOnly( state ); +} + +#ifndef KAB_EMBEDDED +#include "detailsviewcontainer.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/details/detailsviewcontainer.h b/kaddressbook/details/detailsviewcontainer.h new file mode 100644 index 0000000..b561d12 --- a/dev/null +++ b/kaddressbook/details/detailsviewcontainer.h @@ -0,0 +1,103 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef DETAILSVIEWCONTAINER_H +#define DETAILSVIEWCONTAINER_H + +#include <qptrlist.h> + +#include "look_basic.h" + +class QComboBox; +class QWidgetStack; + +class ViewContainer : public QWidget +{ + Q_OBJECT + + public: + ViewContainer( QWidget *parent = 0, const char* name = 0 ); + + /** + Return the look currently selected. If there is none, it + returns zero. Do not use this pointer to store a reference + to a look, the user might select another one (e.g., create + a new object) at any time. + */ + KABBasicLook *currentLook(); + void refreshView(); + /** + Return the contact currently displayed. + */ + KABC::Addressee addressee(); + + public slots: + /** + Set the contact currently displayed. + */ + void setAddressee( const KABC::Addressee& addressee ); + + /** + Set read-write state. + */ + void setReadOnly( bool state ); + + signals: + /** + The contact has been changed. + */ + void addresseeChanged(); + + /** + The user acticated the email address displayed. This may happen + by, for example, clicking on the displayed mailto-URL. + */ + void sendEmail( const QString& ); + + /** + The user activated one of the displayed HTTP URLs. For example + by clicking on the displayed homepage address. + */ + void browse( const QString& ); + + protected: + /** + A style has been selected. Overloaded from base class. + */ + void slotStyleSelected( int ); + + /** + Register the available looks. + */ + void registerLooks(); + + private: + KABC::Addressee mCurrentAddressee; + KABBasicLook *mCurrentLook; + QPtrList<KABLookFactory> mLookFactories; + + QComboBox *mStyleCombo; + QWidgetStack *mDetailsStack; +}; + +#endif diff --git a/kaddressbook/details/global.h b/kaddressbook/details/global.h new file mode 100644 index 0000000..3c52bc2 --- a/dev/null +++ b/kaddressbook/details/global.h @@ -0,0 +1,28 @@ +#ifndef KAB3_GLOBAL_H +#define KAB3_GLOBAL_H + +// keys of configuration file settings: + +#define ConfigGeneral "General" + +#define ConfigGeneral_RememberLastContact "RememberLastContact" +#define ConfigGeneral_ShowContactInHeader "ShowContactInHeader" + +#define ConfigView "View" + +#define ConfigView_View "ConfigView" + +#define ConfigView_UseKDEDefaultFonts "UseKDEDefaultFonts" +#define ConfigView_DefaultBackgroundImage "DefaultBackgroundImage" +#define ConfigView_DefaultBackgroundColor "DefaultBackgroundColor" +#define ConfigView_UseDefaultBackground "UseDefaultBackground" + +#define ConfigView_HeadlineBGColor "HeadlineBGColor" +#define ConfigView_UseHeadlineBGColor "UseHeadlineBGColor" +#define ConfigView_HeadlineTextColor "HeadlineTextColor" +#define ConfigView_HeadlineFont "HeadlineFont" +#define ConfigView_BodyFont "BodyFont" +#define ConfigView_DetailsFont "DetailsFont" + + +#endif diff --git a/kaddressbook/details/look_basic.cpp b/kaddressbook/details/look_basic.cpp new file mode 100644 index 0000000..0245686 --- a/dev/null +++ b/kaddressbook/details/look_basic.cpp @@ -0,0 +1,75 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kdebug.h> + +#include "look_basic.h" + +KABBasicLook::KABBasicLook( QWidget *parent, const char *name ) + : QVBox( parent, name ), mReadOnly( false ) +{ +} + +void KABBasicLook::setReadOnly( bool state ) +{ + mReadOnly = state; +} + +bool KABBasicLook::isReadOnly() const +{ + return mReadOnly; +} + +void KABBasicLook::setAddressee( const KABC::Addressee &addr ) +{ + if ( mAddressee == addr ) + return; + + mAddressee = addr; + repaint( false ); +} + +KABC::Addressee KABBasicLook::addressee() +{ + return mAddressee; +} + +void KABBasicLook::restoreSettings( KConfig* ) +{ +} + +void KABBasicLook::saveSettings( KConfig* ) +{ +} + +KABLookFactory::KABLookFactory( QWidget *parent, const char *name ) + : mParent( parent ), mName( name ) +{ +} + +KABLookFactory::~KABLookFactory() +{ +} +#ifndef KAB_EMBEDDED +#include "look_basic.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/details/look_basic.h b/kaddressbook/details/look_basic.h new file mode 100644 index 0000000..7e8baff --- a/dev/null +++ b/kaddressbook/details/look_basic.h @@ -0,0 +1,134 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef LOOK_KABBASIC_H +#define LOOK_KABBASIC_H + +#include <kabc/addressbook.h> +#include <qvbox.h> + +class KConfig; + +/** + This is a pure virtual base class that defines the + interface for how to display and change entries of + the KDE addressbook. + + This basic widget does not show anything in its client space. + Derive it and implement its look and how the user may edit the + entry. + + The paintEvent() has to paint the whole widget, since repaint() + calls will not delete the widgets background. + */ +class KABBasicLook : public QVBox +{ + Q_OBJECT + + public: + /** + The constructor. + */ + KABBasicLook( QWidget *parent = 0, const char *name = 0 ); + + /** + Set the entry. It will be displayed automatically. + */ + virtual void setAddressee( const KABC::Addressee& addressee ); + + /** + Get the current entry. + */ + virtual KABC::Addressee addressee(); + + /** + Configure the view from the configuration file. + */ + virtual void restoreSettings( KConfig* ); + + /** + Save the view settings to the configuration file. + */ + virtual void saveSettings( KConfig* ); + + /** + Retrieve read-write state. + */ + bool isReadOnly() const; + + signals: + /** + This signal is emitted when the user changed the entry. + */ + void entryChanged(); + + /** + This signal indicates that the entry needs to be changed + immidiately in the database. This might be due to changes in + values that are available in menus. + */ + void saveMe(); + + /** + The user acticated the email address displayed. This may happen + by, for example, clicking on the displayed mailto-URL. + */ + void sendEmail( const QString &email ); + + /** + The user activated one of the displayed HTTP URLs. For example + by clicking on the displayed homepage address. + */ + void browse( const QString &url ); + + public slots: + /** + Set read-write state. + */ + virtual void setReadOnly( bool state ); + + private: + KABC::Addressee mAddressee; + bool mReadOnly; +}; + +class KABLookFactory +{ + public: + KABLookFactory( QWidget *parent = 0, const char *name = 0 ); + virtual ~KABLookFactory(); + + virtual KABBasicLook *create() = 0; + + /** + Overload this method to provide a one-liner description + for your look. + */ + virtual QString description() = 0; + + protected: + QWidget *mParent; + const char* mName; +}; + +#endif diff --git a/kaddressbook/details/look_details.cpp b/kaddressbook/details/look_details.cpp new file mode 100644 index 0000000..51ec0c0 --- a/dev/null +++ b/kaddressbook/details/look_details.cpp @@ -0,0 +1,419 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kconfig.h> +#include <kdebug.h> +#include <kglobalsettings.h> +#include <kinstance.h> +#include <klocale.h> +#include <kstandarddirs.h> + +#include <qcursor.h> +#include <qdir.h> +#include <qpainter.h> +#include <qpopupmenu.h> + +#include "global.h" +#include "kabentrypainter.h" + +#include "look_details.h" + +#define GRID 5 + +const QString KABDetailedView::mBorderedBGDir = "kab3part/backgrounds/bordered/"; +const QString KABDetailedView::mTiledBGDir = "kab3part/backgrounds/tiled/"; + +KABDetailedView::KABDetailedView( QWidget *parent, const char *name ) + : KABBasicLook( parent, name ), mPainter( 0 ), mBackgroundStyle( None ), + mDefaultBGColor( white ), mHeadLineBGColor( darkBlue ), + mHeadLineTextColor( yellow ), mGrid( 3 ), mMenuBorderedBG( 0 ), + mMenuTiledBG( 0 ) +{ + KToggleAction** actions[] = { + &mActionShowAddresses, + &mActionShowEmails, + &mActionShowPhones, + &mActionShowURLs + }; + + QString actionTexts[] = { + i18n( "Show Postal Addresses" ), + i18n( "Show Email Addresses" ), + i18n( "Show Telephone Numbers" ), + i18n( "Show Web Pages (URLs)" ) + }; + + QFont general = KGlobalSettings::generalFont(); + QFont fixed = KGlobalSettings::fixedFont(); + QString gfont = general.family(); + QString ffont = fixed.family(); + + int gpointsize = general.pixelSize(); + if ( gpointsize == -1 ) + gpointsize = general.pointSize(); + + int fpointsize = fixed.pixelSize(); + if ( fpointsize == -1 ) + fpointsize = fixed.pointSize(); + + mPainter = new KABEntryPainter; + + mPainter->setForegroundColor( black ); + mPainter->setHeaderColor( mHeadLineTextColor ); + mPainter->setUseHeaderColor( mUseHeadLineBGColor ); + mPainter->setBackgroundColor( mHeadLineBGColor ); + + mPainter->setHeaderFont( QFont( gfont, gpointsize + 4, QFont::Bold, true ) ); + mPainter->setHeadLineFont( QFont( gfont, gpointsize + 2, QFont::Bold, true ) ); + mPainter->setBodyFont( QFont( gfont, gpointsize, QFont::Normal, false ) ); + mPainter->setFixedFont( QFont( ffont, fpointsize, QFont::Normal, false ) ); + mPainter->setCommentFont( QFont( gfont, gpointsize, QFont::Normal, false ) ); + + const int numActions = sizeof( actions ) / sizeof( actions[ 0 ] ); + + for ( int count = 0; count < numActions; ++count ) { + *actions[ count ] = new KToggleAction( actionTexts[ count ] ); + (*actions[ count ])->setChecked( true ); + } + + setMouseTracking( true ); + + setBackgroundMode( NoBackground ); +} + +KABDetailedView::~KABDetailedView() +{ + delete mPainter; + mPainter = 0; +} + +bool KABDetailedView::getBackground( QString path, QPixmap& image ) +{ + QMap<QString, QPixmap>::iterator pos; + + pos = mBackgroundMap.find( path ); + if ( pos == mBackgroundMap.end() ) { // the image has not been loaded previously + if ( image.load( path ) ) { + mBackgroundMap[ path ] = image; + return true; + } else + return false; + } else { // image found in cache + image = pos.data(); + return true; + } +} + +void KABDetailedView::paintEvent( QPaintEvent* ) +{ + const int BorderSpace = mGrid; + QPixmap pm( width(), height() ); + QPainter p; + + QRect entryArea = QRect( BorderSpace, mGrid, width() - mGrid - BorderSpace, + height() - 2 * mGrid ); + p.begin( &pm ); + + p.setPen( darkBlue ); + p.setBrush( mDefaultBGColor ); + p.drawRect( 0, 0, width(), height() ); + switch ( mBackgroundStyle ) { + case Tiled: + p.drawTiledPixmap( 1, 1, width() - 2, height() - 2, mCurrentBackground ); + break; + case Bordered: + p.drawTiledPixmap( 1, 1, QMIN( width() - 2, mCurrentBackground.width() ), + height() - 2, mCurrentBackground ); + break; + case None: // no BG image defined for this entry: + default: + if ( mUseDefaultBGImage ) + p.drawTiledPixmap( 1, 1, width() - 2, height() - 2, mDefaultBGImage ); + break; + }; + + p.setViewport( entryArea ); + + mPainter->setShowAddresses( mActionShowAddresses->isChecked() ); + mPainter->setShowEmails( mActionShowEmails->isChecked() ); + mPainter->setShowPhones( mActionShowPhones->isChecked() ); + mPainter->setShowURLs( mActionShowURLs->isChecked() ); + mPainter->printAddressee( addressee(), QRect( 0, 0, entryArea.width(), + entryArea.height() ), &p ); + p.end(); + bitBlt( this, 0, 0, &pm ); +} + +void KABDetailedView::mouseMoveEvent( QMouseEvent *e ) +{ + QPoint bias( mGrid, mGrid ); + int rc; + bool hit = false; + + if ( ( rc = mPainter->hitsEmail( e->pos() - bias ) ) != -1 ) + hit = true; + else if ( ( rc = mPainter->hitsURL( e->pos() - bias ) ) != -1 ) + hit = true; + else if ( ( rc = mPainter->hitsPhone( e->pos() - bias ) ) != -1 ) + hit = true; + else if ( ( rc = mPainter->hitsTalk( e->pos() - bias ) ) != -1 ) + hit = true; + + if ( hit ) { + if ( cursor().shape() != PointingHandCursor ) + setCursor( PointingHandCursor ); + else if( cursor().shape() != ArrowCursor ) + setCursor(ArrowCursor); + } +} + +void KABDetailedView::mousePressEvent( QMouseEvent *e ) +{ + QPopupMenu menu( this ); + QPopupMenu *menuBG = new QPopupMenu( &menu ); + mMenuBorderedBG = new QPopupMenu( &menu ); + mMenuTiledBG = new QPopupMenu( &menu ); + + menu.insertItem( i18n( "Select Background" ), menuBG ); + menuBG->insertItem( i18n( "Bordered Backgrounds" ), mMenuBorderedBG ); + menuBG->insertItem( i18n( "Tiled Backgrounds" ), mMenuTiledBG ); + menu.insertSeparator(); + + QPoint point = e->pos() - QPoint( mGrid, mGrid ); + int rc; + QStringList dirsBorderedBG, dirsTiledBG; + QDir dir; + + switch( e->button() ) { + case QMouseEvent::RightButton: + if ( isReadOnly() ) + menu.setItemEnabled( menu.idAt( 0 ), false ); + else { + // TODO: settings need to be saved in view options + dirsBorderedBG = KGlobal::instance()->dirs()->findDirs( "data", mBorderedBGDir ); + if ( dirsBorderedBG.count() > 0 ) { + dir.setPath( dirsBorderedBG[ 0 ] ); + mBorders = dir.entryList( QDir::Files ); + for ( uint count = 0; count < mBorders.count(); ++count ) + mMenuBorderedBG->insertItem( mBorders[ count ], count ); + + connect( mMenuBorderedBG, SIGNAL( activated( int ) ), + SLOT( slotBorderedBGSelected( int ) ) ); + } else + menuBG->setItemEnabled( menuBG->idAt( 0 ), false ); + + dirsTiledBG = KGlobal::instance()->dirs()->findDirs( "data", mTiledBGDir ); + if ( dirsTiledBG.count() > 0 ) { + dir.setPath( dirsTiledBG[ 0 ] ); + mTiles = dir.entryList( QDir::Files ); + for ( uint count = 0; count < mTiles.count(); ++count ) + mMenuTiledBG->insertItem( mTiles[ count ], count ); + + connect( mMenuTiledBG, SIGNAL( activated( int ) ), + SLOT( slotTiledBGSelected( int ) ) ); + } else + menuBG->setItemEnabled( menuBG->idAt( 1 ), false ); + } + + mActionShowAddresses->plug( &menu ); + mActionShowEmails->plug( &menu ); + mActionShowPhones->plug( &menu ); + mActionShowURLs->plug( &menu ); + + menu.exec( e->globalPos() ); + break; + + case QMouseEvent::LeftButton: + // find whether the pointer touches an email address, URL, + // talk address or telephone number: + if ( ( rc = mPainter->hitsEmail( point ) ) != -1 ) { + emit sendEmail( addressee().emails()[ rc ] ); + break; + } + if ( ( rc = mPainter->hitsURL( point ) ) != -1 ) { + emit browse( addressee().url().prettyURL() ); + break; + } + if ( ( rc = mPainter->hitsPhone( point ) ) != -1 ) { + // not implemented yet + break; + } + if ( ( rc = mPainter->hitsTalk( point ) ) != -1 ) { + // not implemented yet + break; + } + break; + default: + break; + } + + mMenuBorderedBG = 0; + mMenuTiledBG = 0; +} + +void KABDetailedView::setAddressee( const KABC::Addressee &addr ) +{ + BackgroundStyle style = None; + QString dir, file, styleSetting; + KABBasicLook::setAddressee( addr ); + + // TODO: preload path and styleSetting with possible preference values + styleSetting = addressee().custom( "kab", "BackgroundStyle" ); + style = (BackgroundStyle)styleSetting.toInt(); + file = addressee().custom( "kab", "BackgroundImage" ); + if ( !file.isEmpty() ) { + switch ( style ) { + case Tiled: + dir = mTiledBGDir; + break; + case Bordered: + dir = mBorderedBGDir; + break; + case None: + default: + break; + } + + QStringList dirs = KGlobal::instance()->dirs()->findDirs( "data", dir ); + mBackgroundStyle = None; + if ( !dirs.isEmpty() ) { + uint count = 0; + for ( ; count < dirs.count(); ++count ) { + QDir folder; + folder.setPath( dirs[ count ] ); + file = folder.absPath() + "/" + file; + if ( getBackground( file, mCurrentBackground ) ) { + mBackgroundStyle = style; + break; + } + } + + if ( count == dirs.count() ) { + kdDebug(5720) << "KABDetailedView::setEntry: " << file + << " not locatable." << endl; + } + } + } else { // no background here + mBackgroundStyle = None; + mCurrentBackground.resize( 0, 0 ); + } + + repaint( false ); +} + +void KABDetailedView::slotBorderedBGSelected( int index ) +{ + if ( index >= 0 && (uint)index < mBorders.count() && !isReadOnly() ) { + // get the selection and make it a full path + QString path = mBorders[ index ]; + mBackgroundStyle = Bordered; + addressee().insertCustom( "kab", "BackgroundStyle", + QString().setNum( mBackgroundStyle ) ); + addressee().insertCustom( "kab", "BackgroundImage", path ); + setAddressee( addressee() ); + } +} + +void KABDetailedView::slotTiledBGSelected( int index ) +{ + if ( index >= 0 && (uint)index < mTiles.count() && !isReadOnly() ) { + QString path = mTiles[ index ]; + mBackgroundStyle = Tiled; + addressee().insertCustom( "kab", "BackgroundStyle", + QString().setNum( mBackgroundStyle ) ); + addressee().insertCustom( "kab", "BackgroundImage", path ); + setAddressee( addressee() ); + } +} + +void KABDetailedView::setReadOnly( bool state ) +{ + KABBasicLook::setReadOnly( state ); + repaint( false ); +} + +void KABDetailedView::restoreSettings( KConfig *config ) +{ + QFont general = KGlobalSettings::generalFont(); + QFont fixed = KGlobalSettings::fixedFont(); + QString gfont = general.family(); + QString ffont = fixed.family(); + + int gpointsize = general.pixelSize(); + if ( gpointsize == -1 ) + gpointsize = general.pointSize(); + + int fpointsize = fixed.pixelSize(); + if ( fpointsize == -1 ) + fpointsize = fixed.pointSize(); + + config->setGroup( ConfigView ); + + // load the default background image: + QString bgImage; + mUseDefaultBGImage = config->readBoolEntry( ConfigView_UseDefaultBackground, true ); + mDefaultBGColor = config->readColorEntry( ConfigView_DefaultBackgroundColor, &white ); + bgImage = config->readEntry( ConfigView_DefaultBackgroundImage, "konqueror/tiles/kenwimer.png" ); + + if ( mUseDefaultBGImage ) { + uint count = 0; + QStringList dirs = KGlobal::instance()->dirs()->findDirs( "data", "/" ); + if ( !dirs.isEmpty() ) { + for ( count = 0; count < dirs.count(); ++count ) { + if ( getBackground( dirs[ count ] + "/" + bgImage, mDefaultBGImage ) ) + break; + } + } + + if ( count == dirs.count() ) { + mUseDefaultBGImage = getBackground( bgImage, mDefaultBGImage ); + if ( !mUseDefaultBGImage ) + kdDebug(5720) << "KABDetailedView::configure: " + << "default BG image selected, but could not be loaded." + << endl; + } + } + + mDefaultBGColor = config->readColorEntry( ConfigView_DefaultBackgroundColor, &white ); + mHeadLineBGColor = config->readColorEntry( ConfigView_HeadlineBGColor, &darkBlue ); + mHeadLineTextColor = config->readColorEntry( ConfigView_HeadlineTextColor, &yellow ); + mUseHeadLineBGColor = config->readBoolEntry( ConfigView_UseHeadlineBGColor, true ); + + if ( !mPainter ) + mPainter = new KABEntryPainter; + + mPainter->setForegroundColor( black ); + mPainter->setHeaderColor( mHeadLineTextColor ); + mPainter->setUseHeaderColor( mUseHeadLineBGColor ); + mPainter->setBackgroundColor( mHeadLineBGColor ); + + mPainter->setHeaderFont( QFont( gfont, gpointsize + 4, QFont::Bold, true ) ); + mPainter->setHeadLineFont( QFont( gfont, gpointsize + 2, QFont::Bold, true ) ); + mPainter->setBodyFont( QFont( gfont, gpointsize, QFont::Normal, false ) ); + mPainter->setFixedFont( QFont( ffont, fpointsize, QFont::Normal, false ) ); + mPainter->setCommentFont( QFont( gfont, gpointsize, QFont::Normal, false ) ); +} + +#ifndef KAB_EMBEDDED +#include "look_details.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/details/look_details.h b/kaddressbook/details/look_details.h new file mode 100644 index 0000000..e8d50a9 --- a/dev/null +++ b/kaddressbook/details/look_details.h @@ -0,0 +1,157 @@ +/* + This file is part of KAddressBook. + Copyright (c) 1996-2002 Mirko Boehm <mirko@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef LOOK_DETAILS_H +#define LOOK_DETAILS_H + +#include <kabc/addressbook.h> +#include <kaction.h> +#include <klocale.h> + +#include <qmap.h> +#include <qpixmap.h> +#include <qptrlist.h> +#include <qrect.h> + +#include "look_basic.h" + +class KABEntryPainter; +class QComboBox; + +/** + This class implements the detailed view. + Currently, there is no possibility to change the entry in this + view. + */ + +class KABDetailedView : public KABBasicLook +{ + Q_OBJECT + + public: + /** + Enum to select how the background is drawn. + */ + enum BackgroundStyle + { + None, + Tiled, + Bordered + }; + + /** + The constructor. + */ + KABDetailedView( QWidget *parent = 0, const char* name = 0 ); + + /** + The virtual destructor. + */ + virtual ~KABDetailedView(); + + /** + Set the addressee. + */ + void setAddressee( const KABC::Addressee& ); + + /** + Overloaded from KABBasicLook. + */ + void setReadOnly( bool ); + + /** + Overloaded from KABBasicLook. + */ + void restoreSettings( KConfig* ); + + public slots: + void slotBorderedBGSelected( int index ); + void slotTiledBGSelected( int index ); + + protected: + void paintEvent( QPaintEvent* ); + void mousePressEvent( QMouseEvent* ); + void mouseMoveEvent( QMouseEvent* ); + + /** + A method to retrieve a background image according to the path + stored in the entry. It is either loaded + from backgrounds, that acts as a cache, or from the file + and added to @see backgrounds. + */ + bool getBackground( QString path, QPixmap& image ); + + private: + QPtrList<QRect> mURLRects; + QPtrList<QRect> mEmailRects; + QPtrList<QRect> mPhoneRects; + KABEntryPainter *mPainter; + + QMap<QString, QPixmap> mBackgroundMap; + QPixmap mCurrentBackground; + + BackgroundStyle mBackgroundStyle; + + bool mUseDefaultBGImage; + bool mUseHeadLineBGColor; + + QColor mDefaultBGColor; + QColor mHeadLineBGColor; + QColor mHeadLineTextColor; + + QPixmap mDefaultBGImage; + + KToggleAction *mActionShowAddresses; + KToggleAction *mActionShowEmails; + KToggleAction *mActionShowPhones; + KToggleAction *mActionShowURLs; + + const int mGrid; + QStringList mBorders; + QStringList mTiles; + + QPopupMenu *mMenuBorderedBG; + QPopupMenu *mMenuTiledBG; + + static const QString mBorderedBGDir; + static const QString mTiledBGDir; +}; + +class KABDetailedViewFactory : public KABLookFactory +{ + public: + KABDetailedViewFactory( QWidget *parent = 0, const char *name = 0 ) + : KABLookFactory( parent, name ) {} + + KABBasicLook *create() + { + return new KABDetailedView( mParent, mName ); + } + + QString description() + { + return i18n( "Detailed Style: Display all details, no modifications." ); + } +}; + +#endif diff --git a/kaddressbook/details/look_html.cpp b/kaddressbook/details/look_html.cpp new file mode 100644 index 0000000..2a70273 --- a/dev/null +++ b/kaddressbook/details/look_html.cpp @@ -0,0 +1,45 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <libkdepim/addresseeview.h> + +#include "look_html.h" +#include <qscrollview.h> +KABHtmlView::KABHtmlView( QWidget *parent, const char *name ) + : KABBasicLook( parent, name ) +{ + mView = new KPIM::AddresseeView( this ); +} + +KABHtmlView::~KABHtmlView() +{ +} + +void KABHtmlView::setAddressee( const KABC::Addressee &addr ) +{ + mView->setAddressee( addr ); +} + +#ifndef KAB_EMBEDDED +#include "look_html.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/details/look_html.h b/kaddressbook/details/look_html.h new file mode 100644 index 0000000..68a02d9 --- a/dev/null +++ b/kaddressbook/details/look_html.h @@ -0,0 +1,75 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef LOOK_HTML_H +#define LOOK_HTML_H + +#include <klocale.h> + +#include "look_basic.h" + +namespace KABC { class Addressee; } +namespace KPIM { class AddresseeView; } + +class KABHtmlView : public KABBasicLook +{ + Q_OBJECT + + public: + /** + The constructor. + */ + KABHtmlView( QWidget *parent = 0, const char* name = 0 ); + + /** + The virtual destructor. + */ + virtual ~KABHtmlView(); + + /** + Set the addressee. + */ + void setAddressee( const KABC::Addressee& ); + + private: + KPIM::AddresseeView *mView; +}; + +class KABHtmlViewFactory : public KABLookFactory +{ + public: + KABHtmlViewFactory( QWidget *parent = 0, const char *name = 0 ) + : KABLookFactory( parent, name ) {} + + KABBasicLook *create() + { + return new KABHtmlView( mParent, mName ); + } + + QString description() + { + return i18n( "HTML table style." ); + } +}; + +#endif diff --git a/kaddressbook/emaileditwidget.cpp b/kaddressbook/emaileditwidget.cpp new file mode 100644 index 0000000..0e01b02 --- a/dev/null +++ b/kaddressbook/emaileditwidget.cpp @@ -0,0 +1,275 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qtoolbutton.h> +#include <qtooltip.h> +#include <qlistbox.h> + +#ifndef KAB_EMBEDDED +#include <kaccelmanager.h> +#endif //KAB_EMBEDDED +#include <kconfig.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "emaileditwidget.h" + +EmailEditWidget::EmailEditWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QGridLayout *topLayout = new QGridLayout( this, 2, 2 ); + topLayout->setSpacing( KDialog::spacingHint() ); + QLabel* label = new QLabel( this ); + + label->setPixmap( KGlobal::iconLoader()->loadIcon( "mail_send", KIcon::Desktop, 0) ); + + topLayout->addWidget( label, 0, 0 ); + label->setAlignment( AlignCenter ); + QPushButton *editButton = new QPushButton( i18n( "Edit Email Addresses..." ), this); + topLayout->addWidget( editButton, 0, 1 ); + label = new QLabel( i18n( "Email:" ), this ); + topLayout->addWidget( label, 1, 0 ); + + mEmailEdit = new KLineEdit( this ); + connect( mEmailEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + connect( mEmailEdit, SIGNAL( textChanged( const QString& ) ), + SIGNAL( modified() ) ); + label->setBuddy( mEmailEdit ); + topLayout->addWidget( mEmailEdit, 1, 1 ); + + + connect( editButton, SIGNAL( clicked() ), SLOT( edit() ) ); + + topLayout->activate(); +} + +EmailEditWidget::~EmailEditWidget() +{ +} + +void EmailEditWidget::setEmails( const QStringList &list ) +{ + mEmailList = list; + + bool blocked = mEmailEdit->signalsBlocked(); + mEmailEdit->blockSignals( true ); + if ( list.count() > 0 ) + mEmailEdit->setText( list[ 0 ] ); + else + mEmailEdit->setText( "" ); + mEmailEdit->blockSignals( blocked ); +} + +QStringList EmailEditWidget::emails() +{ + if ( mEmailEdit->text().isEmpty() ) { + if ( mEmailList.count() > 0 ) + mEmailList.remove( mEmailList.begin() ); + } else { + if ( mEmailList.count() > 0 ) + mEmailList.remove( mEmailList.begin() ); + + mEmailList.prepend( mEmailEdit->text() ); + } + + return mEmailList; +} + +void EmailEditWidget::edit() +{ + EmailEditDialog dlg( mEmailList, this ); + + if ( dlg.exec() ) { + if ( dlg.changed() ) { + mEmailList = dlg.emails(); + mEmailEdit->setText( mEmailList[ 0 ] ); + emit modified(); + } + } +} + +void EmailEditWidget::textChanged( const QString &text ) +{ + if ( mEmailList.count() > 0 ) + mEmailList.remove( mEmailList.begin() ); + + mEmailList.prepend( text ); +} + + +EmailEditDialog::EmailEditDialog( const QStringList &list, QWidget *parent, + const char *name ) + : KDialogBase( KDialogBase::Plain, i18n( "Edit Email Addresses" ), + KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, + parent, name, true ) +{ + QWidget *page = plainPage(); + + QGridLayout *topLayout = new QGridLayout( page, 4, 3 ); + + QLabel *label = new QLabel( i18n( "Email address:" ), page ); + topLayout->addWidget( label, 0, 0 ); + + mEmailEdit = new KLineEdit( page ); + label->setBuddy( mEmailEdit ); + topLayout->addWidget( mEmailEdit, 0, 1 ); + connect( mEmailEdit, SIGNAL( returnPressed() ), SLOT( add() ) ); + connect( mEmailEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( emailChanged() ) ); + + mAddButton = new QPushButton( i18n( "Add" ), page ); + mAddButton->setEnabled( false ); + connect( mAddButton, SIGNAL( clicked() ), SLOT( add() ) ); + topLayout->addWidget( mAddButton, 0, 2 ); + + mEmailListBox = new QListBox( page ); + + // Make sure there is room for the scrollbar + mEmailListBox->setMinimumHeight( mEmailListBox->sizeHint().height() + 30 ); + connect( mEmailListBox, SIGNAL( highlighted( int ) ), + SLOT( selectionChanged( int ) ) ); + topLayout->addMultiCellWidget( mEmailListBox, 1, 3, 0, 1 ); + + mEditButton = new QPushButton( i18n( "Change" ), page ); + connect( mEditButton, SIGNAL( clicked() ), SLOT( edit() ) ); + topLayout->addWidget( mEditButton, 1, 2 ); + + mRemoveButton = new QPushButton( i18n( "Remove" ), page ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( remove() ) ); + topLayout->addWidget( mRemoveButton, 2, 2 ); + + mStandardButton = new QPushButton( i18n( "Set Standard" ), page ); + connect( mStandardButton, SIGNAL( clicked() ), SLOT( standard() ) ); + topLayout->addWidget( mStandardButton, 3, 2 ); + + topLayout->activate(); + QStringList items = list; + +qDebug("EmailEditDialog::EmailEditDialog has to be changed (lowPrio)"); +//US must be fixed !!! +/* + if ( items.remove( "" ) > 0 ) + mChanged = true; + else + mChanged = false; +*/ + + mEmailListBox->insertStringList( items ); + // set default state + selectionChanged( -1 ); + +#ifndef KAB_EMBEDDED + KAcceleratorManager::manage( this ); +#else //KAB_EMBEDDED +//US qDebug("EmailEditDialog::EmailEditDialog has to be changed"); +#endif //KAB_EMBEDDED + +} + +EmailEditDialog::~EmailEditDialog() +{ +} + +QStringList EmailEditDialog::emails() const +{ + QStringList emails; + + for ( uint i = 0; i < mEmailListBox->count(); ++i ) + emails << mEmailListBox->text( i ); + + return emails; +} + +void EmailEditDialog::add() +{ + mEmailListBox->insertItem( mEmailEdit->text() ); + + mEmailEdit->clear(); + mEmailEdit->setFocus(); + + mChanged = true; +} + +void EmailEditDialog::edit() +{ + mEmailEdit->setText( mEmailListBox->currentText() ); + mEmailEdit->setFocus(); +} + +void EmailEditDialog::remove() +{ + QString address = mEmailListBox->currentText(); + + QString text = i18n( "<qt>Are you sure that you want to remove the email address <b>%1</b>?</qt>" ).arg( address ); + QString caption = i18n( "Confirm Remove" ); + + if ( KMessageBox::questionYesNo( this, text, caption ) == KMessageBox::Yes ) { + mEmailListBox->removeItem( mEmailListBox->currentItem() ); + mChanged = true; + } +} + +bool EmailEditDialog::changed() const +{ + return mChanged; +} + +void EmailEditDialog::standard() +{ + QString text = mEmailListBox->currentText(); + mEmailListBox->removeItem( mEmailListBox->currentItem() ); + mEmailListBox->insertItem( text, 0 ); + mEmailListBox->setSelected( 0, true ); + + mChanged = true; +} + +void EmailEditDialog::selectionChanged( int index ) +{ + bool value = ( index >= 0 ); // An item is selected + + mRemoveButton->setEnabled( value ); + mEditButton->setEnabled( value ); + mStandardButton->setEnabled( value ); +} + +void EmailEditDialog::emailChanged() +{ + mAddButton->setEnabled( !mEmailEdit->text().isEmpty() ); +} + +#ifndef KAB_EMBEDDED +#include "emaileditwidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/emaileditwidget.h b/kaddressbook/emaileditwidget.h new file mode 100644 index 0000000..acdecaf --- a/dev/null +++ b/kaddressbook/emaileditwidget.h @@ -0,0 +1,101 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef EMAILEDITWIDGET_H +#define EMAILEDITWIDGET_H + +#include <kabc/addressee.h> +#include <kdialogbase.h> + +#include "addresseeconfig.h" + +class QButtonGroup; +class QCheckBox; +class QListView; +class QListBox; +class QTextEdit; +class QToolButton; + +class KComboBox; +class KLineEdit; +class KListView; + +/** + This widget displays a list box of the email addresses as well as buttons + to manipulate them (up, down, add, remove). +*/ +class EmailEditWidget : public QWidget +{ + Q_OBJECT + + public: + EmailEditWidget( QWidget *parent, const char *name = 0 ); + ~EmailEditWidget(); + + void setEmails( const QStringList &list ); + QStringList emails(); + + signals: + void modified(); + + private slots: + void edit(); + void textChanged( const QString& ); + + private: + KLineEdit *mEmailEdit; + QStringList mEmailList; +}; + +class EmailEditDialog : public KDialogBase +{ + Q_OBJECT + + public: + EmailEditDialog( const QStringList &list, QWidget *parent, + const char *name = 0 ); + ~EmailEditDialog(); + + QStringList emails() const; + bool changed() const; + + protected slots: + void add(); + void remove(); + void edit(); + void standard(); + void selectionChanged( int ); + void emailChanged(); + + private: + KLineEdit *mEmailEdit; + QListBox *mEmailListBox; + QPushButton *mAddButton; + QPushButton *mRemoveButton; + QPushButton *mEditButton; + QPushButton *mStandardButton; + + bool mChanged; +}; + +#endif diff --git a/kaddressbook/extensionmanager.cpp b/kaddressbook/extensionmanager.cpp new file mode 100644 index 0000000..9114cdc --- a/dev/null +++ b/kaddressbook/extensionmanager.cpp @@ -0,0 +1,246 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#include <qlayout.h> +#include <qapplication.h> +#include <kactionclasses.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> + +#ifndef KAB_EMBEDDED +#include <ktrader.h> +#else //KAB_EMBEDDED +#include <features/mergewidget.h> +#include <features/distributionlistwidget.h> +#endif //KAB_EMBEDDED + +#include "addresseeeditorwidget.h" +#include "kabcore.h" +#include "kabprefs.h" + +#include "extensionmanager.h" + +ExtensionManager::ExtensionManager( KABCore *core, QWidget *parent, + const char *name ) + : QScrollView( parent, name ), mCore( core ), mCurrentExtensionWidget( 0 ) +{ +#ifdef KAB_EMBEDDED +//US QPopupMenu *settingsmenu = (QPopupMenu*)mCore->getSettingsMenu(); + QWidget *settingsmenu = (QWidget*)mCore->getSettingsMenu(); +#endif //KAB_EMBEDDED + + mActionExtensions = new KSelectAction( i18n( "Show Extension Bar" ), 0, + mCore->actionCollection(), + "options_show_extensions" ); + + mActionExtensions->plug( settingsmenu ); + + connect( mActionExtensions, SIGNAL( activated( int ) ), + SLOT( setActiveExtension( int ) ) ); + mWidgetBox = new QWidget( viewport() ); + addChild( mWidgetBox ); + setResizePolicy(AutoOneFit); + createExtensionWidgets(); + hide(); +} + +ExtensionManager::~ExtensionManager() +{ +} + +void ExtensionManager::restoreSettings() +{ + mActionExtensions->setCurrentItem( KABPrefs::instance()->mCurrentExtension ); + int i = 1; + mCurrentExtensionWidget = mExtensionWidgetList.at( i-1 ); + while ( mCurrentExtensionWidget ) { + if( i != KABPrefs::instance()->mCurrentExtension ) + mCurrentExtensionWidget->hide(); + mCurrentExtensionWidget = mExtensionWidgetList.at( ++i-1 ); + + } + setActiveExtension( mActionExtensions->currentItem() ); +} + +void ExtensionManager::saveSettings() +{ + KABPrefs::instance()->mCurrentExtension = mActionExtensions->currentItem(); +} + +void ExtensionManager::reconfigure() +{ + saveSettings(); + createExtensionWidgets(); + restoreSettings(); +} + +bool ExtensionManager::isQuickEditVisible() const +{ + return ( mCurrentExtensionWidget && + mCurrentExtensionWidget->identifier() == "contact_editor" ); +} + +void ExtensionManager::setSelectionChanged() +{ + if ( mCurrentExtensionWidget ) + mCurrentExtensionWidget->contactsSelectionChanged(); +} + +void ExtensionManager::setActiveExtension( int id ) +{ + //qDebug("+++++++++++++++++++ExtensionManager::setActiveExtension %d ", id); + if ( id == 0 ) { + hide(); + mCurrentExtensionWidget = 0; +#ifndef DESKTOP_VERSION +//US our screen is so small, that we better hide the detailscreen, just in case. + mCore->setDetailsToState( ); +#endif //KAB_EMBEDDED + } else if ( id > 0 ) { + if ( mCurrentExtensionWidget ) + mCurrentExtensionWidget->hide(); + + mCurrentExtensionWidget = mExtensionWidgetList.at( id - 1 ); + + if ( mCurrentExtensionWidget ) { +#ifndef DESKTOP_VERSION +//US our screen is so small, that we better hide the detailscreen, just in case. + mCore->setDetailsVisible( false ); +#endif //KAB_EMBEDDED + show(); + mWidgetBox->show(); + mCurrentExtensionWidget->show(); + } else { + hide(); + mCurrentExtensionWidget = 0; +#ifndef DESKTOP_VERSION +//US our screen is so small, that we better hide the detailscreen, just in case. + mCore->setDetailsToState( ); +#endif //KAB_EMBEDDED + } + } +} + +void ExtensionManager::createExtensionWidgets() +{ + // clear extension widget list + mExtensionWidgetList.setAutoDelete( true ); + QPtrListIterator<ExtensionWidget> wdgIt( mExtensionWidgetList ); + ExtensionWidget *wdg = 0; + while ( ( wdg = wdgIt.current() ) != 0 ) + mExtensionWidgetList.remove( wdg ); + + mExtensionWidgetList.setAutoDelete( false ); + + QStringList extensionNames( i18n( "None" ) ); + + // add addressee editor as default + + QHBoxLayout *hbl = new QHBoxLayout (mWidgetBox ); + + wdg = new AddresseeEditorWidget( mCore, true, mWidgetBox ); + hbl->addWidget( wdg ); + //wdg->hide(); + connect( wdg, SIGNAL( modified( const KABC::Addressee::List& ) ), + SIGNAL( modified( const KABC::Addressee::List& ) ) ); + mExtensionWidgetList.append( wdg ); + extensionNames.append( wdg->title() ); + + // load the other extensions + QStringList activeExtensions = KABPrefs::instance()->mActiveExtensions; + +#ifndef KAB_EMBEDDED + KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/Extension" ); + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + if ( !(*it)->hasServiceType( "KAddressBook/Extension" ) ) + continue; + + KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().latin1() ); + if ( !factory ) { + kdDebug(5720) << "ExtensionManager::loadExtensions(): Factory creation failed" << endl; + continue; + } + + ExtensionFactory *extensionFactory = static_cast<ExtensionFactory*>( factory ); + + if ( !extensionFactory ) { + kdDebug(5720) << "ExtensionManager::loadExtensions(): Cast failed" << endl; + continue; + } + + if ( !activeExtensions.contains( extensionFactory->identifier() ) ) + continue; + + wdg = extensionFactory->extension( mCore, this ); + if ( wdg ) { + //wdg->hide(); + connect( wdg, SIGNAL( modified( const KABC::Addressee::List& ) ), + SIGNAL( modified( const KABC::Addressee::List& ) ) ); + mExtensionWidgetList.append( wdg ); + extensionNames.append( wdg->title() ); + } + } +#else //KAB_EMBEDDED + //load Mergefactory/extension + ExtensionFactory *extensionFactory = new MergeFactory(); + if ( activeExtensions.contains( extensionFactory->identifier() ) ) + { + wdg = extensionFactory->extension( mCore, mWidgetBox ); + if ( wdg ) { + hbl->addWidget( wdg ); + //wdg->hide(); + connect( wdg, SIGNAL( modified( const KABC::Addressee::List& ) ), + SIGNAL( modified( const KABC::Addressee::List& ) ) ); + mExtensionWidgetList.append( wdg ); + extensionNames.append( wdg->title() ); + } + } + + //load DistributionListfactory/extension + extensionFactory = new DistributionListFactory(); + if (activeExtensions.contains( extensionFactory->identifier() ) ) + { + wdg = extensionFactory->extension( mCore, mWidgetBox ); + if ( wdg ) { + hbl->addWidget( wdg ); + //wdg->hide(); + connect( wdg, SIGNAL( modified( const KABC::Addressee::List& ) ), + SIGNAL( modified( const KABC::Addressee::List& ) ) ); + mExtensionWidgetList.append( wdg ); + extensionNames.append( wdg->title() ); + } + } + + hbl->addStretch(); + +#endif //KAB_EMBEDDED + + + mActionExtensions->setItems( extensionNames ); + mCurrentExtensionWidget = 0; +} + +#ifndef KAB_EMBEDDED +#include "extensionmanager.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/extensionmanager.h b/kaddressbook/extensionmanager.h new file mode 100644 index 0000000..8f64a50 --- a/dev/null +++ b/kaddressbook/extensionmanager.h @@ -0,0 +1,88 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef EXTENSIONMANAGER_H +#define EXTENSIONMANAGER_H + +#include <qhbox.h> +#include <qscrollview.h> +#include <qptrlist.h> + +#include <extensionwidget.h> + +class KABCore; +class KSelectAction; + + +class ExtensionManager : public QScrollView +{ + Q_OBJECT + + public: + ExtensionManager( KABCore *core, QWidget *parent, const char *name = 0 ); + ~ExtensionManager(); + + /** + Restores the extension manager specific settings. + */ + void restoreSettings(); + + /** + Saves the extension manager specific settings. + */ + void saveSettings(); + + /** + Rereads the extension manager specific settings with some + additional initialization stuff. + */ + void reconfigure(); + + /** + Returns whether the quickedit extension is currently visible. + */ + bool isQuickEditVisible() const; + + public slots: + void setSelectionChanged(); + + signals: + void modified( const KABC::Addressee::List& ); + + private slots: + void setActiveExtension( int id ); + + private: + void createExtensionWidgets(); + + KABCore *mCore; + QWidget *mWidgetBox; + + ExtensionWidget *mCurrentExtensionWidget; + QPtrList<ExtensionWidget> mExtensionWidgetList; + + KSelectAction *mActionExtensions; + +}; + +#endif diff --git a/kaddressbook/extensionwidget.cpp b/kaddressbook/extensionwidget.cpp new file mode 100644 index 0000000..69f4aa8 --- a/dev/null +++ b/kaddressbook/extensionwidget.cpp @@ -0,0 +1,84 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "configurewidget.h" +#include "kabcore.h" + +#include "extensionwidget.h" + +ExtensionWidget::ExtensionWidget( KABCore *core, QWidget *parent, + const char *name ) + : QWidget( parent, name ), mCore( core ) +{ +} + +ExtensionWidget::~ExtensionWidget() +{ +} + +KABCore *ExtensionWidget::core() const +{ + return mCore; +} + +bool ExtensionWidget::contactsSelected() const +{ + return mCore->selectedUIDs().count() != 0; +} + +KABC::Addressee::List ExtensionWidget::selectedContacts() +{ + KABC::Addressee::List list; + + QStringList uids = mCore->selectedUIDs(); + QStringList::Iterator it; + for ( it = uids.begin(); it != uids.end(); ++it ) + list.append( mCore->addressBook()->findByUid( *it ) ); + + return list; +} + +void ExtensionWidget::contactsSelectionChanged() +{ + // do nothing +} + +QString ExtensionWidget::title() const +{ + return "<bug!!!>"; +} + +QString ExtensionWidget::identifier() const +{ + return "<bug!!!>"; +} + +ConfigureWidget *ExtensionFactory::configureWidget( QWidget*, const char* ) +{ + return 0; +} + +#ifndef KAB_EMBEDDED +#include "extensionwidget.moc" +#endif //KAB_EMBEDDED + diff --git a/kaddressbook/extensionwidget.h b/kaddressbook/extensionwidget.h new file mode 100644 index 0000000..fc91f21 --- a/dev/null +++ b/kaddressbook/extensionwidget.h @@ -0,0 +1,119 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef EXTENSIONWIDGET_H +#define EXTENSIONWIDGET_H + +#include <qwidget.h> + +#include <kabc/addressbook.h> +#ifndef KAB_EMBEDDED +#include <klibloader.h> +#endif //KAB_EMBEDDED + +class ConfigureWidget; +class KABCore; + +class ExtensionWidget : public QWidget +{ + Q_OBJECT + + public: + ExtensionWidget( KABCore *core, QWidget *parent, const char *name = 0 ); + ~ExtensionWidget(); + + /** + @return A pointer to the core object + */ + KABCore *core() const; + + /** + Returns whether there are selected contacts in the view. + */ + bool contactsSelected() const; + + /** + Returns a list of contacts that are selected in the view. + Use @ref addresseesSelected() to test if there exists selected + contacts. + */ + KABC::Addressee::List selectedContacts(); + + /** + This method is called whenever the selection in the view changed. + */ + virtual void contactsSelectionChanged(); + + /** + This method should be reimplemented and return the i18ned title of this + widget. + */ + virtual QString title() const; + + /** + This method should be reimplemented and return a unique identifier. + */ + virtual QString identifier() const; + + signals: + void modified( const KABC::Addressee::List &list ); + + private: + KABCore *mCore; + + class ExtensionWidgetPrivate; + ExtensionWidgetPrivate *d; +}; + +#ifndef KAB_EMBEDDED +//MOC_SKIP_BEGIN +class ExtensionFactory : public KLibFactory +//MOC_SKIP_END +#else //KAB_EMBEDDED +class ExtensionFactory +#endif //KAB_EMBEDDED +{ + public: + virtual ExtensionWidget *extension( KABCore *core, QWidget *parent, + const char *name = 0 ) = 0; + + virtual ConfigureWidget *configureWidget( QWidget *parent, + const char *name = 0 ); + + virtual bool configureWidgetAvailable() { return false; } + + /** + This method should return the same identifier like the config + widget. + */ + virtual QString identifier() const = 0; + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } +}; + +#endif diff --git a/kaddressbook/features/distributionlistwidget.cpp b/kaddressbook/features/distributionlistwidget.cpp new file mode 100644 index 0000000..bfcb121 --- a/dev/null +++ b/kaddressbook/features/distributionlistwidget.cpp @@ -0,0 +1,501 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qbuttongroup.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qradiobutton.h> + +#ifndef KAB_EMBEDDED +#include <kaccelmanager.h> +#endif //KAB_EMBEDDED + + +#include <kdebug.h> +#include <klineeditdlg.h> +#include <klocale.h> +#include <kglobal.h> +#include <kmessagebox.h> + +#include <kabc/addressbook.h> +#include <kabc/addresseedialog.h> +#include <kabc/distributionlist.h> +#include <kabc/vcardconverter.h> + +#ifndef KAB_EMBEDDED +#include <libkdepim/kvcarddrag.h> +#endif //KAB_EMBEDDED + +#include "kabcore.h" + +#include "distributionlistwidget.h" + +#ifndef KAB_EMBEDDED + +class DistributionListFactory : public ExtensionFactory +{ + public: + ExtensionWidget *extension( KABCore *core, QWidget *parent, const char *name ) + { + return new DistributionListWidget( core, parent, name ); + } + + QString identifier() const + { + return "distribution_list_editor"; + } +}; + +extern "C" { + void *init_libkaddrbk_distributionlist() + { + return ( new DistributionListFactory ); + } +} +#endif //KAB_EMBEDDED + +class ContactItem : public QListViewItem +{ + public: + ContactItem( DistributionListView *parent, const KABC::Addressee &addressee, + const QString &email = QString::null ) : + QListViewItem( parent ), + mAddressee( addressee ), + mEmail( email ) + { + setText( 0, addressee.realName() ); + if( email.isEmpty() ) { + setText( 1, addressee.preferredEmail() ); + setText( 2, i18n( "Yes" ) ); + } else { + setText( 1, email ); + setText( 2, i18n( "No" ) ); + } + } + + KABC::Addressee addressee() const + { + return mAddressee; + } + + QString email() const + { + return mEmail; + } + + protected: + bool acceptDrop( const QMimeSource* ) + { + return true; + } + + private: + KABC::Addressee mAddressee; + QString mEmail; +}; + +DistributionListWidget::DistributionListWidget( KABCore *core, QWidget *parent, + const char *name ) + : ExtensionWidget( core, parent, name ), mManager( 0 ) +{ + QGridLayout *topLayout = new QGridLayout( this, 3, 4, KDialog::marginHint(), + KDialog::spacingHint() ); + + if (KGlobal::getOrientation() == KGlobal::Portrait) + { + mCreateListButton = new QPushButton( i18n( "New List" ), this ); + mEditListButton = new QPushButton( i18n( "Ren List" ), this ); + mRemoveListButton = new QPushButton( i18n( "Del List" ), this ); + mAddContactButton = new QPushButton( i18n( "Add Cont." ), this ); + mChangeEmailButton = new QPushButton( i18n( "Chge Email" ), this ); + mRemoveContactButton = new QPushButton( i18n( "Del Cont." ), this ); + } + else + { + mCreateListButton = new QPushButton( i18n( "New List..." ), this ); + mEditListButton = new QPushButton( i18n( "Rename List..." ), this ); + mRemoveListButton = new QPushButton( i18n( "Remove List" ), this ); + mAddContactButton = new QPushButton( i18n( "Add Contact" ), this ); + mChangeEmailButton = new QPushButton( i18n( "Change Email..." ), this ); + mRemoveContactButton = new QPushButton( i18n( "Remove Contact" ), this ); + } + mNameCombo = new QComboBox( this ); + topLayout->addWidget( mNameCombo, 0, 0 ); + connect( mNameCombo, SIGNAL( activated( int ) ), SLOT( updateContactView() ) ); + + topLayout->addWidget( mCreateListButton, 0, 1 ); + connect( mCreateListButton, SIGNAL( clicked() ), SLOT( createList() ) ); + + topLayout->addWidget( mEditListButton, 0, 2 ); + connect( mEditListButton, SIGNAL( clicked() ), SLOT( editList() ) ); + + topLayout->addWidget( mRemoveListButton, 0, 3 ); + connect( mRemoveListButton, SIGNAL( clicked() ), SLOT( removeList() ) ); + + mContactView = new DistributionListView( this ); + mContactView->addColumn( i18n( "Name" ) ); + mContactView->addColumn( i18n( "Email" ) ); + mContactView->addColumn( i18n( "Use Preferred" ) ); + mContactView->setEnabled( false ); + mContactView->setAllColumnsShowFocus( true ); + mContactView->setMinimumHeight( 30 ); + + topLayout->addMultiCellWidget( mContactView, 1, 1, 0, 3 ); + connect( mContactView, SIGNAL( selectionChanged() ), + SLOT( selectionContactViewChanged() ) ); + connect( mContactView, SIGNAL( dropped( QDropEvent*, QListViewItem* ) ), + SLOT( dropped( QDropEvent*, QListViewItem* ) ) ); + + mAddContactButton->setEnabled( false ); + topLayout->addWidget( mAddContactButton, 2, 0 ); + connect( mAddContactButton, SIGNAL( clicked() ), SLOT( addContact() ) ); + + topLayout->addWidget( mChangeEmailButton, 2, 2 ); + connect( mChangeEmailButton, SIGNAL( clicked() ), SLOT( changeEmail() ) ); + + topLayout->addWidget( mRemoveContactButton, 2, 3 ); + connect( mRemoveContactButton, SIGNAL( clicked() ), SLOT( removeContact() ) ); + + mManager = new KABC::DistributionListManager( core->addressBook() ); + mManager->load(); + + updateNameCombo(); + +#ifdef KAB_EMBEDDED +// if (KGlobal::getOrientation() == KGlobal::Portrait) +// parent->setMaximumSize( KGlobal::getDesktopWidth() , 150); +#endif //KAB_EMBEDDED + +#ifndef KAB_EMBEDDED + KAcceleratorManager::manage( this ); +#endif //KAB_EMBEDDED +} + +DistributionListWidget::~DistributionListWidget() +{ + delete mManager; +} + +void DistributionListWidget::save() +{ +qDebug("DistributionListWidget::save"); + mManager->save(); +} + +void DistributionListWidget::selectionContactViewChanged() +{ + ContactItem *contactItem = + static_cast<ContactItem *>( mContactView->selectedItem() ); + bool state = contactItem; + + mChangeEmailButton->setEnabled( state ); + mRemoveContactButton->setEnabled( state ); +} + +void DistributionListWidget::createList() +{ + KLineEditDlg dlg( i18n( "Please enter name:" ), QString::null, this ); +#ifdef KAB_EMBEDDED + dlg.setFixedSize(200, 50); +#endif //KAB_EMBEDDED + dlg.setCaption( i18n( "New Distribution List" ) ); + if ( !dlg.exec() ) + return; + + new KABC::DistributionList( mManager, dlg.text() ); + + mNameCombo->clear(); + mNameCombo->insertStringList( mManager->listNames() ); + mNameCombo->setCurrentItem( mNameCombo->count() - 1 ); + + updateContactView(); + + changed(); +} + +void DistributionListWidget::editList() +{ + QString oldName = mNameCombo->currentText(); + + KLineEditDlg dlg( i18n( "Please change name:" ), oldName, this ); +#ifdef KAB_EMBEDDED + dlg.setFixedSize(200, 50); +#endif //KAB_EMBEDDED + dlg.setCaption( i18n("Distribution List") ); + if ( !dlg.exec() ) + return; + + KABC::DistributionList *list = mManager->list( oldName ); + list->setName( dlg.text() ); + + mNameCombo->clear(); + mNameCombo->insertStringList( mManager->listNames() ); + mNameCombo->setCurrentItem( mNameCombo->count() - 1 ); + + updateContactView(); + + changed(); +} + +void DistributionListWidget::removeList() +{ + int result = KMessageBox::warningContinueCancel( this, + i18n( "<qt>Delete distribution list <b>%1</b>?</qt>" ) .arg( mNameCombo->currentText() ), + QString::null, i18n( "Delete" ) ); + + if ( result != KMessageBox::Continue ) + return; + + delete mManager->list( mNameCombo->currentText() ); + mNameCombo->removeItem( mNameCombo->currentItem() ); + + updateContactView(); + + changed(); +} + +void DistributionListWidget::addContact() +{ + KABC::DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) + return; + + KABC::Addressee::List addrList = selectedContacts(); + KABC::Addressee::List::Iterator it; + for ( it = addrList.begin(); it != addrList.end(); ++it ) + list->insertEntry( *it ); + + updateContactView(); + + changed(); +} + +void DistributionListWidget::removeContact() +{ + KABC::DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) + return; + + ContactItem *contactItem = + static_cast<ContactItem *>( mContactView->selectedItem() ); + if ( !contactItem ) + return; + + list->removeEntry( contactItem->addressee(), contactItem->email() ); + delete contactItem; + + changed(); +} + +void DistributionListWidget::changeEmail() +{ + KABC::DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) + return; + + ContactItem *contactItem = + static_cast<ContactItem *>( mContactView->selectedItem() ); + if ( !contactItem ) + return; + + QString email = EmailSelector::getEmail( contactItem->addressee().emails(), + contactItem->email(), this ); + list->removeEntry( contactItem->addressee(), contactItem->email() ); + list->insertEntry( contactItem->addressee(), email ); + + updateContactView(); + + changed(); +} + +void DistributionListWidget::updateContactView() +{ + mContactView->clear(); + + KABC::DistributionList *list = mManager->list( mNameCombo->currentText() ); + if ( !list ) { + mEditListButton->setEnabled( false ); + mRemoveListButton->setEnabled( false ); + mChangeEmailButton->setEnabled( false ); + mRemoveContactButton->setEnabled( false ); + mContactView->setEnabled( false ); + return; + } else { + mEditListButton->setEnabled( true ); + mRemoveListButton->setEnabled( true ); + mContactView->setEnabled( true ); + } + + KABC::DistributionList::Entry::List entries = list->entries(); + KABC::DistributionList::Entry::List::ConstIterator it; + for( it = entries.begin(); it != entries.end(); ++it ) + new ContactItem( mContactView, (*it).addressee, (*it).email ); + + ContactItem *contactItem = + static_cast<ContactItem *>( mContactView->selectedItem() ); + bool state = contactItem; + + mChangeEmailButton->setEnabled( state ); + mRemoveContactButton->setEnabled( state ); +} + +void DistributionListWidget::updateNameCombo() +{ + mNameCombo->insertStringList( mManager->listNames() ); + + updateContactView(); +} + +void DistributionListWidget::dropEvent( QDropEvent *e ) +{ + KABC::DistributionList *distributionList = mManager->list( mNameCombo->currentText() ); + if ( !distributionList ) + return; + + QString vcards; +#ifndef KAB_EMBEDDED + if ( KVCardDrag::decode( e, vcards ) ) { +#endif //KAB_EMBEDDED + QStringList list = QStringList::split( "\r\n\r\n", vcards ); + QStringList::Iterator it; + KABC::VCardConverter converter; + for ( it = list.begin(); it != list.end(); ++it ) { + KABC::Addressee addr; + if ( converter.vCardToAddressee( (*it).stripWhiteSpace(), addr ) ) + distributionList->insertEntry( addr ); + } + + changed(); + updateContactView(); +#ifndef KAB_EMBEDDED + } +#endif //KAB_EMBEDDED +} + +void DistributionListWidget::contactsSelectionChanged() +{ + mAddContactButton->setEnabled( contactsSelected() && mNameCombo->count() > 0 ); +} + +QString DistributionListWidget::title() const +{ + return i18n( "Distribution List Editor" ); +} + +QString DistributionListWidget::identifier() const +{ + return "distribution_list_editor"; +} + +void DistributionListWidget::dropped( QDropEvent *e, QListViewItem* ) +{ + dropEvent( e ); +} + +void DistributionListWidget::changed() +{ + save(); +} + + +DistributionListView::DistributionListView( QWidget *parent, const char* name ) + : KListView( parent, name ) +{ + setDragEnabled( true ); + setAcceptDrops( true ); + setAllColumnsShowFocus( true ); +} + +void DistributionListView::dragEnterEvent( QDragEnterEvent* e ) +{ +#ifndef KAB_EMBEDDED + bool canDecode = QTextDrag::canDecode( e ); + e->accept( canDecode ); +#endif //KAB_EMBEDDED +} + +void DistributionListView::viewportDragMoveEvent( QDragMoveEvent *e ) +{ +#ifndef KAB_EMBEDDED + bool canDecode = QTextDrag::canDecode( e ); + e->accept( canDecode ); +#endif //KAB_EMBEDDED +} + +void DistributionListView::viewportDropEvent( QDropEvent *e ) +{ + emit dropped( e, 0 ); +} + +void DistributionListView::dropEvent( QDropEvent *e ) +{ + emit dropped( e, 0 ); +} + + +EmailSelector::EmailSelector( const QStringList &emails, + const QString ¤t, QWidget *parent ) + : KDialogBase( KDialogBase::Plain, i18n("Select Email Address"), Ok, Ok, + parent ) +{ + QFrame *topFrame = plainPage(); + QBoxLayout *topLayout = new QVBoxLayout( topFrame ); + + mButtonGroup = new QButtonGroup( 1, Horizontal, i18n("Email Addresses"), + topFrame ); + topLayout->addWidget( mButtonGroup ); + + QStringList::ConstIterator it; + for( it = emails.begin(); it != emails.end(); ++it ) { + QRadioButton *button = new QRadioButton( *it, mButtonGroup ); + if ( (*it) == current ) { + button->setDown( true ); + } + } +} + +QString EmailSelector::selected() +{ + QButton *button = mButtonGroup->selected(); + if ( button ) + return button->text(); + + return QString::null; +} + +QString EmailSelector::getEmail( const QStringList &emails, + const QString ¤t, QWidget *parent ) +{ + EmailSelector dlg( emails, current, parent ); + dlg.exec(); + + return dlg.selected(); +} + + +#ifndef KAB_EMBEDDED +#include "distributionlistwidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/features/distributionlistwidget.h b/kaddressbook/features/distributionlistwidget.h new file mode 100644 index 0000000..82bac3d --- a/dev/null +++ b/kaddressbook/features/distributionlistwidget.h @@ -0,0 +1,143 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef DISTRIBUTIONLISTWIDGET_H +#define DISTRIBUTIONLISTWIDGET_H + +#include <kdialogbase.h> +#include <klistview.h> + +#include "extensionwidget.h" + +class QButtonGroup; +class QComboBox; +class QLabel; +class QListView; + +class DistributionListView; +class KABCore; + +namespace KABC { +class AddressBook; +class DistributionListManager; +} + +class DistributionListWidget : public ExtensionWidget +{ + Q_OBJECT + + public: + DistributionListWidget( KABCore*, QWidget *parent, const char *name = 0 ); + virtual ~DistributionListWidget(); + + void contactsSelectionChanged(); + + QString title() const; + QString identifier() const; + + public slots: + void save(); + void dropped( QDropEvent*, QListViewItem* ); + + private slots: + void createList(); + void editList(); + void removeList(); + void addContact(); + void removeContact(); + void changeEmail(); + void updateNameCombo(); + void updateContactView(); + void selectionContactViewChanged(); + void changed(); + + protected: + void dropEvent( QDropEvent* ); + + private: + QComboBox *mNameCombo; + QLabel *mListLabel; + DistributionListView *mContactView; + + KABC::DistributionListManager *mManager; + QPushButton *mCreateListButton; + QPushButton *mEditListButton; + QPushButton *mRemoveListButton; + QPushButton *mChangeEmailButton; + QPushButton *mAddContactButton; + QPushButton *mRemoveContactButton; +}; + +/** + @short Helper class +*/ +class DistributionListView : public KListView +{ + Q_OBJECT + + public: + DistributionListView( QWidget *parent, const char* name = 0 ); + + protected: + void dragEnterEvent( QDragEnterEvent *e ); + void dropEvent( QDropEvent *e ); + void viewportDragMoveEvent( QDragMoveEvent *e ); + void viewportDropEvent( QDropEvent *e ); +}; + +/** + @short Helper class +*/ +class EmailSelector : public KDialogBase +{ + public: + EmailSelector( const QStringList &emails, const QString ¤t, + QWidget *parent ); + + QString selected(); + + static QString getEmail( const QStringList &emails, const QString ¤t, + QWidget *parent ); + + private: + QButtonGroup *mButtonGroup; +}; + + +#ifdef KAB_EMBEDDED +class DistributionListFactory : public ExtensionFactory +{ + public: + ExtensionWidget *extension( KABCore *core, QWidget *parent, const char *name ) + { + return new DistributionListWidget( core, parent, name ); + } + + QString identifier() const + { + return "distribution_list_editor"; + } +}; +#endif //KAB_EMBEDDED + +#endif diff --git a/kaddressbook/features/mergewidget.cpp b/kaddressbook/features/mergewidget.cpp new file mode 100644 index 0000000..2476e42 --- a/dev/null +++ b/kaddressbook/features/mergewidget.cpp @@ -0,0 +1,374 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> +#include <qpushbutton.h> + +#ifndef KAB_EMBEDDED +#include <kaccelmanager.h> +#endif //KAB_EMBEDDED + +#include <kdebug.h> +#include <klistview.h> +#include <klocale.h> +#include <kglobal.h> +#include <kmessagebox.h> + +#include <kabc/addressbook.h> + +#include "kabcore.h" + +#include "mergewidget.h" + +#ifndef KAB_EMBEDDED +class MergeFactory : public ExtensionFactory +{ + public: + ExtensionWidget *extension( KABCore *core, QWidget *parent, const char *name ) + { + return new MergeWidget( core, parent, name ); + } + + QString identifier() const + { + return "merge"; + } +}; + +extern "C" { + void *init_libkaddrbk_merge() + { + return ( new MergeFactory ); + } +} +#endif //KAB_EMBEDDED + +class ContactItem : public QListViewItem +{ + public: + ContactItem( KListView *parent, const KABC::Addressee &addressee ) + : QListViewItem( parent ), mAddressee( addressee ) + { + KABC::Field::List fieldList = KABC::Field::defaultFields(); + KABC::Field::List::ConstIterator it; + + int i = 0; + for ( it = fieldList.begin(); it != fieldList.end(); ++it ) + setText( i++, (*it)->value( mAddressee ) ); + } + + KABC::Addressee addressee() const + { + return mAddressee; + } + + private: + KABC::Addressee mAddressee; +}; + +MergeWidget::MergeWidget( KABCore *core, QWidget *parent, const char *name ) + : ExtensionWidget( core, parent, name ), mBlockUpdate( false ) +{ +#ifdef KAB_EMBEDDED + if (KGlobal::getOrientation() == KGlobal::Portrait) + parent->setMaximumSize( KGlobal::getDesktopWidth() , 180); +#endif //KAB_EMBEDDED + + QGridLayout *topLayout = new QGridLayout( this, 3, 2, KDialog::marginHint(), + KDialog::spacingHint() ); + + mContactView = new KListView( this ); + KABC::Field::List fieldList = KABC::Field::defaultFields(); + KABC::Field::List::ConstIterator it; + + for ( it = fieldList.begin(); it != fieldList.end(); ++it ) + mContactView->addColumn( (*it)->label() ); + + mContactView->setEnabled( false ); + mContactView->setAllColumnsShowFocus( true ); + topLayout->addMultiCellWidget( mContactView, 0, 2, 0, 0 ); + + connect( mContactView, SIGNAL( selectionChanged() ), + SLOT( selectionContactViewChanged() ) ); + + mMergeAndRemoveButton = new QPushButton( i18n( "Merge and Remove" ), this ); + mMergeAndRemoveButton->setEnabled( false ); + topLayout->addWidget( mMergeAndRemoveButton, 0, 1 ); + connect( mMergeAndRemoveButton, SIGNAL( clicked() ), SLOT( mergeAndRemove() ) ); + + mMergeButton = new QPushButton( i18n( "Merge" ), this ); + mMergeButton->setEnabled( false ); + topLayout->addWidget( mMergeButton, 1, 1 ); + connect( mMergeButton, SIGNAL( clicked() ), SLOT( merge() ) ); + +#ifndef KAB_EMBEDDED + KAcceleratorManager::manage( this ); +#endif //KAB_EMBEDDED +} + +MergeWidget::~MergeWidget() +{ +} + +void MergeWidget::selectionContactViewChanged() +{ +#ifndef KAB_EMBEDDED + ContactItem *contactItem = + dynamic_cast<ContactItem*>( mContactView->selectedItem() ); +#else //KAB_EMBEDDED + ContactItem *contactItem =(ContactItem*)( mContactView->selectedItem() ); +#endif //KAB_EMBEDDED + + bool state = (contactItem != 0); + + mMergeAndRemoveButton->setEnabled( state ); + mMergeButton->setEnabled( state ); +} + +void MergeWidget::contactsSelectionChanged() +{ + if ( mBlockUpdate ) + return; + + if ( !contactsSelected() ) { + mContactView->setEnabled( false ); + mContactView->clear(); + mMergeAndRemoveButton->setEnabled( false ); + mMergeButton->setEnabled( false ); + } else { + KABC::Addressee::List list = selectedContacts(); + if ( list.count() > 1 ) { + mContactView->setEnabled( false ); + mContactView->clear(); + mMergeAndRemoveButton->setEnabled( false ); + mMergeButton->setEnabled( false ); + return; + } else { + mContactView->setEnabled( true ); + mMasterAddressee = list[ 0 ]; + updateView(); + } + } +} + +void MergeWidget::updateView() +{ + mContactView->clear(); + + KABC::AddressBook::Iterator it; + KABC::AddressBook *ab = core()->addressBook(); + if ( !ab ) + return; + + for ( it = ab->begin(); it != ab->end(); ++it ) + if ( (*it).uid() != mMasterAddressee.uid() ) + new ContactItem( mContactView, *it ); +} + +QString MergeWidget::title() const +{ + return i18n( "Merge Contacts Editor" ); +} + +QString MergeWidget::identifier() const +{ + return "merge"; +} + +void MergeWidget::mergeAndRemove() +{ +#ifndef KAB_EMBEDDED + ContactItem *item = dynamic_cast<ContactItem*>( mContactView->currentItem() ); +#else //KAB_EMBEDDED + ContactItem *item = (ContactItem*)( mContactView->currentItem() ); +#endif //KAB_EMBEDDED + if ( !item ) + return; + + QString oldUID = item->addressee().uid(); + + doMerge( item->addressee() ); + + KABC::Addressee::List retval; + retval << mMasterAddressee; + emit modified( retval ); + + mBlockUpdate = true; + core()->deleteContacts( oldUID ); + core()->setContactSelected( mMasterAddressee.uid() ); + mBlockUpdate = false; + + updateView(); +} + +void MergeWidget::merge() +{ +#ifndef KAB_EMBEDDED + ContactItem *item = dynamic_cast<ContactItem*>( mContactView->currentItem() ); +#else //KAB_EMBEDDED + ContactItem *item = (ContactItem*)( mContactView->currentItem() ); +#endif //KAB_EMBEDDED + if ( !item ) + return; + + doMerge( item->addressee() ); + + KABC::Addressee::List retval; + retval << mMasterAddressee; + emit modified( retval ); + + mBlockUpdate = true; + core()->setContactSelected( mMasterAddressee.uid() ); + mBlockUpdate = false; + + updateView(); +} + +void MergeWidget::doMerge( const KABC::Addressee &addr ) +{ + // ADR + LABEL + KABC::Address::List addresses = addr.addresses(); + KABC::Address::List masterAddresses = mMasterAddressee.addresses(); + KABC::Address::List::Iterator addrIt ; + for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) { + if ( !masterAddresses.contains( *addrIt ) ) + mMasterAddressee.insertAddress( *addrIt ); + } + + if ( mMasterAddressee.birthday().isNull() && !addr.birthday().isNull() ) + mMasterAddressee.setBirthday( addr.birthday() ); + + + // CATEGORIES + QStringList::Iterator it; + QStringList categories = addr.categories(); + QStringList masterCategories = mMasterAddressee.categories(); + QStringList newCategories( masterCategories ); + for ( it = categories.begin(); it != categories.end(); ++it ) + if ( !masterCategories.contains( *it ) ) + newCategories.append( *it ); + mMasterAddressee.setCategories( newCategories ); + + // CLASS + if ( !mMasterAddressee.secrecy().isValid() && addr.secrecy().isValid() ) + mMasterAddressee.setSecrecy( addr.secrecy() ); + + // EMAIL + QStringList emails = addr.emails(); + QStringList masterEmails = mMasterAddressee.emails(); + for ( it = emails.begin(); it != emails.end(); ++it ) + if ( !masterEmails.contains( *it ) ) + mMasterAddressee.insertEmail( *it, false ); + + // FN + if ( mMasterAddressee.formattedName().isEmpty() && !addr.formattedName().isEmpty() ) + mMasterAddressee.setFormattedName( addr.formattedName() ); + + // GEO + if ( !mMasterAddressee.geo().isValid() && addr.geo().isValid() ) + mMasterAddressee.setGeo( addr.geo() ); + +/* + // KEY + // LOGO +*/ + + // MAILER + if ( mMasterAddressee.mailer().isEmpty() && !addr.mailer().isEmpty() ) + mMasterAddressee.setMailer( addr.mailer() ); + + // N + if ( mMasterAddressee.assembledName().isEmpty() && !addr.assembledName().isEmpty() ) + mMasterAddressee.setNameFromString( addr.assembledName() ); + + // NICKNAME + if ( mMasterAddressee.nickName().isEmpty() && !addr.nickName().isEmpty() ) + mMasterAddressee.setNickName( addr.nickName() ); + + // NOTE + if ( mMasterAddressee.note().isEmpty() && !addr.note().isEmpty() ) + mMasterAddressee.setNote( addr.note() ); + + // ORG + if ( mMasterAddressee.organization().isEmpty() && !addr.organization().isEmpty() ) + mMasterAddressee.setOrganization( addr.organization() ); + +/* + // PHOTO +*/ + + // PROID + if ( mMasterAddressee.productId().isEmpty() && !addr.productId().isEmpty() ) + mMasterAddressee.setProductId( addr.productId() ); + + // REV + if ( mMasterAddressee.revision().isNull() && !addr.revision().isNull() ) + mMasterAddressee.setRevision( addr.revision() ); + + // ROLE + if ( mMasterAddressee.role().isEmpty() && !addr.role().isEmpty() ) + mMasterAddressee.setRole( addr.role() ); + + // SORT-STRING + if ( mMasterAddressee.sortString().isEmpty() && !addr.sortString().isEmpty() ) + mMasterAddressee.setSortString( addr.sortString() ); + +/* + // SOUND +*/ + + // TEL + KABC::PhoneNumber::List phones = addr.phoneNumbers(); + KABC::PhoneNumber::List masterPhones = mMasterAddressee.phoneNumbers(); + KABC::PhoneNumber::List::ConstIterator phoneIt; + for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) + if ( !masterPhones.contains( *it ) ) + mMasterAddressee.insertPhoneNumber( *it ); + + // TITLE + if ( mMasterAddressee.title().isEmpty() && !addr.title().isEmpty() ) + mMasterAddressee.setTitle( addr.title() ); + + // TZ + if ( !mMasterAddressee.timeZone().isValid() && addr.timeZone().isValid() ) + mMasterAddressee.setTimeZone( addr.timeZone() ); + + // UID // ignore UID + + // URL + if ( mMasterAddressee.url().isEmpty() && !addr.url().isEmpty() ) + mMasterAddressee.setUrl( addr.url() ); + + // X- + QStringList customs = addr.customs(); + QStringList masterCustoms = mMasterAddressee.customs(); + QStringList newCustoms( masterCustoms ); + for ( it = customs.begin(); it != customs.end(); ++it ) + if ( !masterCustoms.contains( *it ) ) + newCustoms.append( *it ); + mMasterAddressee.setCustoms( newCustoms ); +} + +#ifndef KAB_EMBEDDED +#include "mergewidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/features/mergewidget.h b/kaddressbook/features/mergewidget.h new file mode 100644 index 0000000..1063c80 --- a/dev/null +++ b/kaddressbook/features/mergewidget.h @@ -0,0 +1,87 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef MERGEWIDGET_H +#define MERGEWIDGET_H + +#include <kdialogbase.h> +#include <klistview.h> + +#include "extensionwidget.h" + +class QListView; + +class KABCore; + +namespace KABC { +class AddressBook; +} + +class MergeWidget : public ExtensionWidget +{ + Q_OBJECT + + public: + MergeWidget( KABCore*, QWidget *parent, const char *name = 0 ); + virtual ~MergeWidget(); + + void contactsSelectionChanged(); + + QString title() const; + QString identifier() const; + + private slots: + void mergeAndRemove(); + void merge(); + + void selectionContactViewChanged(); + + private: + void updateView(); + void doMerge( const KABC::Addressee &addr ); + + KListView *mContactView; + QPushButton *mMergeAndRemoveButton; + QPushButton *mMergeButton; + + KABC::Addressee mMasterAddressee; + bool mBlockUpdate; +}; + +#ifdef KAB_EMBEDDED +class MergeFactory : public ExtensionFactory +{ + public: + ExtensionWidget *extension( KABCore *core, QWidget *parent, const char *name ) + { + return new MergeWidget( core, parent, name ); + } + + QString identifier() const + { + return "merge"; + } +}; +#endif //KAB_EMBEDDED + +#endif diff --git a/kaddressbook/filter.cpp b/kaddressbook/filter.cpp new file mode 100644 index 0000000..b0d04ca --- a/dev/null +++ b/kaddressbook/filter.cpp @@ -0,0 +1,205 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kconfig.h> +#include <kconfigbase.h> +#include <kdebug.h> + +#include "kabprefs.h" + +#include "filter.h" + +Filter::Filter() + : mName( QString::null ), mMatchRule( Matching ), mEnabled( true ), + mInternal( false ) +{ +} + +Filter::Filter( const QString &name ) + : mName( name ), mMatchRule( Matching ), mEnabled( true ), + mInternal( false ) +{ +} + +Filter::~Filter() +{ +} + +void Filter::setName( const QString &name ) +{ + mName = name; +} + +const QString &Filter::name() const +{ + return mName; +} + +bool Filter::isInternal() const +{ + return mInternal; +} + +void Filter::apply( KABC::Addressee::List &addresseeList ) +{ + KABC::Addressee::List::Iterator iter; + for ( iter = addresseeList.begin(); iter != addresseeList.end(); ) { + if ( filterAddressee( *iter ) ) + ++iter; + else + { +#ifndef KAB_EMBEDDED + iter = addresseeList.erase( iter ); +#else //KAB_EMBEDDED + iter = addresseeList.remove( iter ); +#endif //KAB_EMBEDDED + } + } +} + +bool Filter::filterAddressee( const KABC::Addressee &a ) +{ + QStringList::Iterator iter; + iter = mCategoryList.begin(); + // empty filter always matches + + if ( iter == mCategoryList.end() ) + return true; + + for ( ; iter != mCategoryList.end(); ++iter ) { + if ( a.hasCategory( *iter ) ) + return ( mMatchRule == Matching ); + } + + return !( mMatchRule == Matching ); +} + +void Filter::setEnabled( bool on ) +{ + mEnabled = on; +} + +bool Filter::isEnabled() const +{ + return mEnabled; +} + +void Filter::setCategories( const QStringList &list ) +{ + mCategoryList = list; +} + +const QStringList &Filter::categories() const +{ + return mCategoryList; +} + +void Filter::save( KConfig *config ) +{ + config->writeEntry( "Name", mName ); + config->writeEntry( "Enabled", mEnabled ); + config->writeEntry( "Categories", mCategoryList ); + config->writeEntry( "MatchRule", (int)mMatchRule ); +} + +void Filter::restore( KConfig *config ) +{ + mName = config->readEntry( "Name", "<internal error>" ); + mEnabled = config->readBoolEntry( "Enabled", true ); + mCategoryList = config->readListEntry( "Categories" ); + mMatchRule = (MatchRule)config->readNumEntry( "MatchRule", Matching ); +} + +void Filter::save( KConfig *config, QString baseGroup, Filter::List &list ) +{ + { + KConfigGroupSaver s( config, baseGroup ); + + // remove the old filters + uint count = config->readNumEntry( "Count" ); + /* // memory access violation here + for ( uint i = 0; i < count; ++i ) + config->deleteGroup( QString( "%1_%2" ).arg( baseGroup ).arg( i ) ); + */ + } + + int index = 0; + Filter::List::Iterator iter; + for ( iter = list.begin(); iter != list.end(); ++iter ) { + if ( !(*iter).mInternal ) { + KConfigGroupSaver s( config, QString( "%1_%2" ).arg( baseGroup ).arg( index ) ); + + (*iter).save( config ); + index++; + } + } + + KConfigGroupSaver s( config, baseGroup ); + + config->writeEntry( "Count", index ); + +} + +Filter::List Filter::restore( KConfig *config, QString baseGroup ) +{ + Filter::List list; + int count = 0; + Filter f; + + { + KConfigGroupSaver s( config, baseGroup ); + count = config->readNumEntry( "Count", 0 ); + } + + for ( int i = 0; i < count; i++ ) { + { + KConfigGroupSaver s( config, QString( "%1_%2" ).arg( baseGroup ).arg( i ) ); + f.restore( config ); + } + + list.append( f ); + } + + QStringList cats = KABPrefs::instance()->mCustomCategories; + for ( QStringList::Iterator it = cats.begin(); it != cats.end(); ++it ) { + Filter filter; + filter.mName = *it; + filter.mEnabled = true; + filter.mCategoryList = *it; + filter.mMatchRule = Matching; + filter.mInternal = true; + list.append( filter ); + } + + return list; +} + +void Filter::setMatchRule( MatchRule rule ) +{ + mMatchRule = rule; +} + +Filter::MatchRule Filter::matchRule() const +{ + return mMatchRule; +} diff --git a/kaddressbook/filter.h b/kaddressbook/filter.h new file mode 100644 index 0000000..cf2c0a1 --- a/dev/null +++ b/kaddressbook/filter.h @@ -0,0 +1,153 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef FILTER_H +#define FILTER_H + +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +#include <kabc/addressee.h> +#include <kconfig.h> + +/** + Filter for AddressBook related objects (Addressees) + + @todo This class should be switched to use shared data. + */ +class Filter +{ + public: + typedef QValueList<Filter> List; + + enum MatchRule { Matching = 0, NotMatching = 1 }; + + Filter(); + Filter( const QString& name ); + ~Filter(); + + /** + Set the name of the filter. + */ + void setName( const QString &name ); + + /** + @return The name of the filter. + */ + const QString &name() const; + + /** + @return Whether the filter is an internal one. + */ + bool isInternal() const; + + /** + Apply the filter to the addressee list. All addressees not passing + the filter criterias will be removed from the list. + + If the MatchRule is NotMatch, then all the addressees matching the + filter will be removed from the list. + */ + void apply( KABC::Addressee::List &addresseeList ); + + /** + Apply the filter to the addressee. + + @return True if the addressee passes the criteria, false otherwise. + The return values are opposite if the MatchRule is NotMatch. + */ + bool filterAddressee( const KABC::Addressee &a ); + + /** + Enable or disable the filter + */ + void setEnabled( bool on ); + + /** + @return True if this filter is enabled, false otherwise. + */ + bool isEnabled() const; + + /** + Set the list of categories. This list is used to filter addressees. + */ + void setCategories( const QStringList &list ); + + /** + @return The list of categories. + */ + const QStringList &categories() const; + + /** + Saves the filter to the config file. The group should already be set. + */ + void save( KConfig *config ); + + /** + Loads the filter from the config file. The group should already be set. + */ + void restore( KConfig *config ); + + /** + Saves a list of filters to the config file. + + @param config The config file to use + @param baseGroup The base groupname to use. The number of filters + will be written to this group, then a _1, _2, etc + will be append for each filter saved. + @param list The list of filters to be saved. + */ + static void save( KConfig *config, QString baseGroup, Filter::List &list ); + + /** + Restores a list of filters from a config file. + + @param config The config file to read from. + @param baseGroup The base group name to be used to find the filters + + @return The list of filters. + */ + static Filter::List restore( KConfig *config, QString baseGroup ); + + /** + Sets the filter rule. If the rule is Filter::Matching (default), + then the filter will return true on items that match the filter. + If the rule is Filter::NotMatching, then the filter will return + true on items that do not match the filter. + */ + void setMatchRule( MatchRule rule ); + + /** @return The current match rule. + */ + MatchRule matchRule() const; + + private: + QString mName; + QStringList mCategoryList; + MatchRule mMatchRule; + bool mEnabled; + bool mInternal; +}; + +#endif diff --git a/kaddressbook/filtereditdialog.cpp b/kaddressbook/filtereditdialog.cpp new file mode 100644 index 0000000..063585a --- a/dev/null +++ b/kaddressbook/filtereditdialog.cpp @@ -0,0 +1,302 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qbuttongroup.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qregexp.h> +#include <qstring.h> +#include <qtoolbutton.h> +#include <qtooltip.h> +#include <qwidget.h> + +#include <kapplication.h> +#include <kbuttonbox.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klistbox.h> +#include <klistview.h> +#include <klocale.h> +#include <kglobal.h> + +#include "kabprefs.h" +#include "filtereditdialog.h" + +FilterEditDialog::FilterEditDialog( QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Edit Address Book Filter" ), + Help | Ok | Cancel, Ok, parent, name, /*US false*/ true, true ) +{ + initGUI(); + + QStringList cats = KABPrefs::instance()->mCustomCategories; + + QStringList::Iterator iter; + for ( iter = cats.begin(); iter != cats.end(); ++iter ) + mCategoriesView->insertItem( new QCheckListItem( mCategoriesView, (*iter), QCheckListItem::CheckBox ) ); + filterNameTextChanged( mNameEdit->text() ); +} + +FilterEditDialog::~FilterEditDialog() +{ +} + +void FilterEditDialog::setFilter( const Filter &filter ) +{ + mNameEdit->setText( filter.name() ); + + QStringList categories = filter.categories(); + QListViewItem *item = mCategoriesView->firstChild(); + while ( item != 0 ) { + if ( categories.contains( item->text( 0 ) ) ) { + QCheckListItem *checkItem = static_cast<QCheckListItem*>( item ); + checkItem->setOn( true ); + } + + item = item->nextSibling(); + } + + if ( filter.matchRule() == Filter::Matching ) + mMatchRuleGroup->setButton( 0 ); + else + mMatchRuleGroup->setButton( 1 ); +} + +Filter FilterEditDialog::filter() +{ + Filter filter; + + filter.setName( mNameEdit->text() ); + + QStringList categories; + QListViewItem *item = mCategoriesView->firstChild(); + while ( item != 0 ) { + QCheckListItem *checkItem = static_cast<QCheckListItem*>( item ); + if ( checkItem->isOn() ) + categories.append( item->text( 0 ) ); + + item = item->nextSibling(); + } + filter.setCategories( categories ); + + if ( mMatchRuleGroup->find( 0 )->isOn() ) + filter.setMatchRule( Filter::Matching ); + else + filter.setMatchRule( Filter::NotMatching ); + + return filter; +} + +void FilterEditDialog::initGUI() +{ +#ifndef KAB_EMBEDDED + resize( 490, 300 ); +#else //KAB_EMBEDDED + resize( KMIN(KGlobal::getDesktopWidth()-10, 490), KMIN(KGlobal::getDesktopHeight()-50, 300)); +#endif //KAB_EMBEDDED + + + QWidget *page = plainPage(); + QLabel *label; + + QGridLayout *topLayout = new QGridLayout( page, 3, 2, 0, spacingHint() ); + + label = new QLabel( i18n( "Name" ), page ); + mNameEdit = new KLineEdit( page ); + mNameEdit->setFocus(); + topLayout->addWidget( label, 0, 0 ); + topLayout->addWidget( mNameEdit, 0, 1 ); + connect( mNameEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( filterNameTextChanged( const QString&) ) ); + + mCategoriesView = new KListView( page ); + mCategoriesView->addColumn( i18n( "Categories" ) ); + topLayout->addMultiCellWidget( mCategoriesView, 1, 1, 0, 1 ); + + mMatchRuleGroup = new QButtonGroup( page ); + mMatchRuleGroup->setExclusive( true ); + + QBoxLayout *gbLayout = new QVBoxLayout( mMatchRuleGroup ); + gbLayout->setSpacing( KDialog::spacingHint() ); + gbLayout->setMargin( KDialog::marginHint() ); + + QRadioButton *radio = new QRadioButton( i18n( "Show only contacts matching\n the selected categories" ), mMatchRuleGroup ); + radio->setChecked( true ); + mMatchRuleGroup->insert( radio ); + gbLayout->addWidget( radio ); + + radio = new QRadioButton( i18n( "Show all contacts except those\n matching the selected categories" ), mMatchRuleGroup ); + mMatchRuleGroup->insert( radio ); + gbLayout->addWidget( radio ); + + topLayout->addMultiCellWidget( mMatchRuleGroup, 2, 2, 0, 1 ); +} + +void FilterEditDialog::filterNameTextChanged( const QString &text ) +{ + enableButtonOK( !text.isEmpty() ); +} + +void FilterEditDialog::slotHelp() +{ +#ifndef KAB_EMBEDDED + kapp->invokeHelp( "using-filters" ); +#endif //KAB_EMBEDDED +} + +FilterDialog::FilterDialog( QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Edit Address Book Filters" ), + Ok | Cancel, Ok, parent, name, /*US false*/true, true ) +{ + initGUI(); +} + +FilterDialog::~FilterDialog() +{ +} + +void FilterDialog::setFilters( const Filter::List &list ) +{ + mFilterList.clear(); + mInternalFilterList.clear(); + + Filter::List::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + if ( (*it).isInternal() ) + mInternalFilterList.append( *it ); + else + mFilterList.append( *it ); + } + + refresh(); +} + +Filter::List FilterDialog::filters() const +{ + Filter::List list = mFilterList + mInternalFilterList; + return list; +} + +void FilterDialog::add() +{ +#ifndef KAB_EMBEDDED + FilterEditDialog dlg( this ); +#else //KAB_EMBEDDED + FilterEditDialog dlg( this->parentWidget() ); +#endif //KAB_EMBEDDED + + if ( dlg.exec() ) + mFilterList.append( dlg.filter() ); + + refresh(); + + mFilterListBox->setCurrentItem( mFilterListBox->count() - 1 ); +} + +void FilterDialog::edit() +{ + FilterEditDialog dlg( this ); + + uint pos = mFilterListBox->currentItem(); + + dlg.setFilter( mFilterList[ pos ] ); + + if ( dlg.exec() ) { + mFilterList.remove( mFilterList.at( pos ) ); + mFilterList.insert( mFilterList.at( pos ), dlg.filter() ); + } + + refresh(); + + mFilterListBox->setCurrentItem( pos ); +} + +void FilterDialog::remove() +{ + mFilterList.remove( mFilterList.at( mFilterListBox->currentItem() ) ); + + selectionChanged( 0 ); + + refresh(); +} + +void FilterDialog::refresh() +{ + mFilterListBox->clear(); + + Filter::List::Iterator iter; + for ( iter = mFilterList.begin(); iter != mFilterList.end(); ++iter ) + mFilterListBox->insertItem( (*iter).name() ); +} + +void FilterDialog::selectionChanged( QListBoxItem *item ) +{ + bool state = ( item != 0 ); + + mEditButton->setEnabled( state ); + mRemoveButton->setEnabled( state ); +} + +void FilterDialog::initGUI() +{ +#ifndef KAB_EMBEDDED + resize( 330, 200 ); +#else //KAB_EMBEDDED + resize( KMIN(KGlobal::getDesktopWidth()-10, 330), KMIN(KGlobal::getDesktopHeight()-50, 200)); +#endif //KAB_EMBEDDED + + QWidget *page = plainPage(); + + QGridLayout *topLayout = new QGridLayout( page, 1, 2, 0, spacingHint() ); + + mFilterListBox = new KListBox( page ); + topLayout->addWidget( mFilterListBox, 0, 0 ); + connect( mFilterListBox, SIGNAL( selectionChanged( QListBoxItem * ) ), + SLOT( selectionChanged( QListBoxItem * ) ) ); + connect( mFilterListBox, SIGNAL( doubleClicked ( QListBoxItem * ) ), + SLOT( edit() ) ); + + KButtonBox *buttonBox = new KButtonBox( page, Vertical ); + buttonBox->addButton( i18n( "&Add..." ), this, SLOT( add() ) ); + mEditButton = buttonBox->addButton( i18n( "&Edit..." ), this, SLOT( edit() ) ); + mEditButton->setEnabled( false ); + mRemoveButton = buttonBox->addButton( i18n( "&Remove" ), this, SLOT( remove() ) ); + mRemoveButton->setEnabled( false ); + + buttonBox->layout(); + topLayout->addWidget( buttonBox, 0, 1 ); +} + +#ifndef KAB_EMBEDDED +#include "filtereditdialog.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/filtereditdialog.h b/kaddressbook/filtereditdialog.h new file mode 100644 index 0000000..4dd75e4 --- a/dev/null +++ b/kaddressbook/filtereditdialog.h @@ -0,0 +1,104 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef FILTEREDITDIALOG_H +#define FILTEREDITDIALOG_H + +class QButtonGroup; +class QString; +class QToolButton; +class QWidget; +class QListBoxItem; + +class KLineEdit; +class KListBox; +class KListView; + +#include <kdialogbase.h> + +#include "filter.h" + +class FilterDialog : public KDialogBase +{ + Q_OBJECT + + public: + FilterDialog( QWidget *parent, const char *name = 0 ); + ~FilterDialog(); + + void setFilters( const Filter::List &list ); + Filter::List filters() const; + + protected slots: + void add(); + void edit(); + void remove(); + void selectionChanged( QListBoxItem* ); + + private: + void initGUI(); + void refresh(); + + Filter::List mFilterList; + Filter::List mInternalFilterList; + + KListBox *mFilterListBox; + QPushButton *mAddButton; + QPushButton *mEditButton; + QPushButton *mRemoveButton; +}; + +class FilterEditDialog : public KDialogBase +{ + Q_OBJECT + public: + FilterEditDialog( QWidget *parent, const char *name = 0 ); + ~FilterEditDialog(); + + void setFilter( const Filter &filter ); + Filter filter(); + + protected slots: + void filterNameTextChanged( const QString& ); + void slotHelp(); + + private: + void initGUI(); + + Filter mFilter; + + KLineEdit *mNameEdit; + KListView *mCategoriesView; + QButtonGroup *mMatchRuleGroup; + QPushButton *mEditButton; + QPushButton *mRemoveButton; +}; + +#endif diff --git a/kaddressbook/geowidget.cpp b/kaddressbook/geowidget.cpp new file mode 100644 index 0000000..13cd084 --- a/dev/null +++ b/kaddressbook/geowidget.cpp @@ -0,0 +1,629 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kabc/geo.h> + +#ifndef KAB_EMBEDDED +#include <kaccelmanager.h> +#else //KAB_EMBEDDED + +#include <qtextstream.h> +#include <kglobal.h> +#endif //KAB_EMBEDDED + +#include <knuminput.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kstandarddirs.h> + +#include <qcheckbox.h> +#include <qfile.h> +#include <qapplication.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qstring.h> +#include <stdlib.h> + +#include "geowidget.h" + +GeoWidget::GeoWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QLabel *label = 0; + + QGridLayout *topLayout = new QGridLayout( this, 4, 3 ); + topLayout->setMargin( KDialog::marginHint() ); + topLayout->setSpacing( KDialog::spacingHint() ); + + label = new QLabel( this ); +//US ambiguous call to loadIcon. Add an additional parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "package_network", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "package_network", KIcon::Desktop, 0 ) ); + label->setAlignment( Qt::AlignTop ); + topLayout->addMultiCellWidget( label, 0, 3, 0, 0 ); + label->setAlignment( AlignCenter ); + mGeoIsValid = new QCheckBox( i18n( "Use geo data" ), this ); + topLayout->addMultiCellWidget( mGeoIsValid, 0, 0, 1, 2 ); + + label = new QLabel( i18n( "Latitude:" ), this ); + topLayout->addWidget( label, 1, 1 ); + + mLatitudeBox = new KDoubleSpinBox( -90, 90, 1, 0, 6, this ); + mLatitudeBox->setEnabled( false ); + mLatitudeBox->setSuffix( "" ); + topLayout->addWidget( mLatitudeBox, 1, 2 ); + label->setBuddy( mLatitudeBox ); + + label = new QLabel( i18n( "Longitude:" ), this ); + topLayout->addWidget( label, 2, 1 ); + + mLongitudeBox = new KDoubleSpinBox( -180, 180, 1, 0, 6, this ); + mLongitudeBox->setEnabled( false ); + mLongitudeBox->setSuffix( "" ); + topLayout->addWidget( mLongitudeBox, 2, 2 ); + label->setBuddy( mLongitudeBox ); + + mExtendedButton = new QPushButton( i18n( "Edit Geo Data..." ), this ); + mExtendedButton->setEnabled( false ); + topLayout->addMultiCellWidget( mExtendedButton, 3, 3, 1, 2 ); + + connect( mLatitudeBox, SIGNAL( valueChanged( double ) ), + SIGNAL( changed() ) ); + connect( mLongitudeBox, SIGNAL( valueChanged( double ) ), + SIGNAL( changed() ) ); + connect( mExtendedButton, SIGNAL( clicked() ), + SLOT( editGeoData() ) ); + + connect( mGeoIsValid, SIGNAL( toggled( bool ) ), + mLatitudeBox, SLOT( setEnabled( bool ) ) ); + connect( mGeoIsValid, SIGNAL( toggled( bool ) ), + mLongitudeBox, SLOT( setEnabled( bool ) ) ); + connect( mGeoIsValid, SIGNAL( toggled( bool ) ), + mExtendedButton, SLOT( setEnabled( bool ) ) ); + connect( mGeoIsValid, SIGNAL( toggled( bool ) ), + SIGNAL( changed() ) ); + +#ifndef KAB_EMBEDDED + KAcceleratorManager::manage( this ); +#endif //KAB_EMBEDDED +} + +GeoWidget::~GeoWidget() +{ +} + +void GeoWidget::setGeo( const KABC::Geo &geo ) +{ + if ( geo.isValid() ) { + mGeoIsValid->setChecked( true ); + mLatitudeBox->setValue( geo.latitude() ); + mLongitudeBox->setValue( geo.longitude() ); + } else + mGeoIsValid->setChecked( false ); +} + +KABC::Geo GeoWidget::geo() const +{ + KABC::Geo geo; + + if ( mGeoIsValid->isChecked() ) { + geo.setLatitude( mLatitudeBox->value() ); + geo.setLongitude( mLongitudeBox->value() ); + } else { + geo.setLatitude( 91 ); + geo.setLongitude( 181 ); + } + + return geo; +} + +void GeoWidget::editGeoData() +{ + GeoDialog dlg( this ); + + dlg.setLatitude( mLatitudeBox->value() ); + dlg.setLongitude( mLongitudeBox->value() ); + + if ( dlg.exec() ) { + mLatitudeBox->setValue( dlg.latitude() ); + mLongitudeBox->setValue( dlg.longitude() ); + + emit changed(); + } +} + + + +GeoDialog::GeoDialog( QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Geo Data Input" ), Ok | Cancel, Ok, + parent, name, true, true ), + mUpdateSexagesimalInput( true ) +{ + QFrame *page = plainPage(); + + QGridLayout *topLayout = new QGridLayout( page, 1, 1, marginHintSmall(), + spacingHint() ); + //topLayout->setRowStretch( 1, 1 ); + + mMapWidget = new GeoMapWidget( page ); + mCityCombo = new KComboBox( page ); + QGroupBox *sexagesimalGroup = new QGroupBox( 0, Vertical, i18n( "Sexagesimal" ), page ); + QGridLayout *sexagesimalLayout = new QGridLayout( sexagesimalGroup->layout(), + 2, 5, spacingHint() ); + QLabel *label; + if ( QApplication::desktop()->width() < 320 ) { + label = new QLabel( i18n( "La." ), sexagesimalGroup ); + sexagesimalLayout->setSpacing ( spacingHintSmall() ); + sexagesimalLayout->setMargin ( marginHintSmall() ); + topLayout->setMargin ( 0 ); + mCityCombo->setMaximumWidth( 220 ); + sexagesimalGroup->setMaximumWidth( 220 ); + } + else + label = new QLabel( i18n( "Latitude:" ), sexagesimalGroup ); + sexagesimalLayout->addWidget( label, 0, 0 ); + + int maxWid = 60; + if ( QApplication::desktop()->width() < 320 ) + maxWid = 40; + mLatDegrees = new QSpinBox( 0, 90, 1, sexagesimalGroup ); + mLatDegrees->setSuffix( "" ); + mLatDegrees->setWrapping( false ); + sexagesimalLayout->addWidget( mLatDegrees, 0, 1 ); + mLatDegrees->setMaximumWidth( maxWid ); + + mLatMinutes = new QSpinBox( 0, 59, 1, sexagesimalGroup ); + mLatMinutes->setSuffix( "'" ); + sexagesimalLayout->addWidget( mLatMinutes, 0, 2 ); + mLatMinutes->setMaximumWidth( maxWid ); + + mLatSeconds = new QSpinBox( 0, 59, 1, sexagesimalGroup ); + mLatSeconds->setSuffix( "\"" ); + sexagesimalLayout->addWidget( mLatSeconds, 0, 3 ); + mLatSeconds->setMaximumWidth( maxWid ); + + mLatDirection = new KComboBox( sexagesimalGroup ); + mLatDirection->insertItem( i18n( "North" ) ); + mLatDirection->insertItem( i18n( "South" ) ); + sexagesimalLayout->addWidget( mLatDirection, 0, 4 ); + + + if ( QApplication::desktop()->width() < 320 ) + label = new QLabel( i18n( "Lo." ), sexagesimalGroup ); + else + label = new QLabel( i18n( "Longitude:" ), sexagesimalGroup ); + + + sexagesimalLayout->addWidget( label, 1, 0 ); + + mLongDegrees = new QSpinBox( 0, 180, 1, sexagesimalGroup ); + mLongDegrees->setSuffix( "" ); + sexagesimalLayout->addWidget( mLongDegrees, 1, 1 ); + mLongDegrees->setMaximumWidth( maxWid ); + + mLongMinutes = new QSpinBox( 0, 59, 1, sexagesimalGroup ); + mLongMinutes->setSuffix( "'" ); + sexagesimalLayout->addWidget( mLongMinutes, 1, 2 ); + mLongMinutes->setMaximumWidth( maxWid ); + + mLongSeconds = new QSpinBox( 0, 59, 1, sexagesimalGroup ); + mLongSeconds->setSuffix( "\"" ); + sexagesimalLayout->addWidget( mLongSeconds, 1, 3 ); + mLongSeconds->setMaximumWidth( maxWid ); + + mLongDirection = new KComboBox( sexagesimalGroup ); + mLongDirection->insertItem( i18n( "East" ) ); + mLongDirection->insertItem( i18n( "West" ) ); + sexagesimalLayout->addWidget( mLongDirection, 1, 4 ); + if ( true /*QApplication::desktop()->width() < 640*/ ) { + + topLayout->addWidget( mMapWidget, 0, 0 ); + topLayout->addWidget( mCityCombo, 1, 0 ); + topLayout->addWidget( sexagesimalGroup, 2, 0 ); + + } else { + topLayout->addMultiCellWidget( mMapWidget, 0, 1, 0, 0 ); + topLayout->addWidget( mCityCombo, 0, 1 ); + topLayout->addWidget( sexagesimalGroup, 1, 1 ); + } + + loadCityList(); + + connect( mMapWidget, SIGNAL( changed() ), + SLOT( geoMapChanged() ) ); + connect( mCityCombo, SIGNAL( activated( int ) ), + SLOT( cityInputChanged() ) ); + connect( mLatDegrees, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLatMinutes, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLatSeconds, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLatDirection, SIGNAL( activated( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLongDegrees, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLongMinutes, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLongSeconds, SIGNAL( valueChanged( int ) ), + SLOT( sexagesimalInputChanged() ) ); + connect( mLongDirection, SIGNAL( activated( int ) ), + SLOT( sexagesimalInputChanged() ) ); + mLongitude = 0.0; + mLatitude = 0.0; +#ifndef DESKTOP_VERSION + showMaximized(); +#endif +} + +GeoDialog::~GeoDialog() +{ +} + +void GeoDialog::setLatitude( double latitude ) +{ + mLatitude = latitude; + updateInputs(); +} + +double GeoDialog::latitude() const +{ + return mLatitude; +} + +void GeoDialog::setLongitude( double longitude ) +{ + mLongitude = longitude; + updateInputs(); +} + +double GeoDialog::longitude() const +{ + return mLongitude; +} + +void GeoDialog::sexagesimalInputChanged() +{ + mLatitude = (double)( mLatDegrees->value() + (double)mLatMinutes->value() / + 60 + (double)mLatSeconds->value() / 3600 ); + + mLatitude *= ( mLatDirection->currentItem() == 1 ? -1 : 1 ); + + mLongitude = (double)( mLongDegrees->value() + (double)mLongMinutes->value() / + 60 + (double)mLongSeconds->value() / 3600 ); + + mLongitude *= ( mLongDirection->currentItem() == 1 ? -1 : 1 ); + + mUpdateSexagesimalInput = false; + + updateInputs(); +} + +void GeoDialog::geoMapChanged() +{ + mLatitude = mMapWidget->latitude(); + mLongitude = mMapWidget->longitude(); + + updateInputs(); +} + +void GeoDialog::cityInputChanged() +{ + if ( mCityCombo->currentItem() != 0 ) { + GeoData data = mGeoDataMap[ mCityCombo->currentText() ]; + mLatitude = data.latitude; + mLongitude = data.longitude; + } else + mLatitude = mLongitude = 0; + + updateInputs(); +} + +void GeoDialog::updateInputs() +{ + // hmm, doesn't look nice, but there is no better way AFAIK + mCityCombo->blockSignals( true ); + mLatDegrees->blockSignals( true ); + mLatMinutes->blockSignals( true ); + mLatSeconds->blockSignals( true ); + mLatDirection->blockSignals( true ); + mLongDegrees->blockSignals( true ); + mLongMinutes->blockSignals( true ); + mLongSeconds->blockSignals( true ); + mLongDirection->blockSignals( true ); + + mMapWidget->setLatitude( mLatitude ); + mMapWidget->setLongitude( mLongitude ); + mMapWidget->update(); + + if ( mUpdateSexagesimalInput ) { + int degrees, minutes, seconds; + double latitude = mLatitude; + double longitude = mLongitude; + + latitude *= ( mLatitude < 0 ? -1 : 1 ); + longitude *= ( mLongitude < 0 ? -1 : 1 ); + + degrees = (int)( latitude * 1 ); + minutes = (int)( ( latitude - degrees ) * 60 ); + seconds = (int)( (double)( (double)latitude - (double)degrees - ( (double)minutes / (double)60 ) ) * (double)3600 ); + + mLatDegrees->setValue( degrees ); + mLatMinutes->setValue( minutes ); + mLatSeconds->setValue( seconds ); + + mLatDirection->setCurrentItem( mLatitude < 0 ? 1 : 0 ); + + degrees = (int)( longitude * 1 ); + minutes = (int)( ( longitude - degrees ) * 60 ); + seconds = (int)( (double)( longitude - (double)degrees - ( (double)minutes / 60 ) ) * 3600 ); + + mLongDegrees->setValue( degrees ); + mLongMinutes->setValue( minutes ); + mLongSeconds->setValue( seconds ); + mLongDirection->setCurrentItem( mLongitude < 0 ? 1 : 0 ); + } + mUpdateSexagesimalInput = true; + + int pos = nearestCity( mLongitude, mLatitude ); + if ( pos != -1 ) + mCityCombo->setCurrentItem( pos + 1 ); + else + mCityCombo->setCurrentItem( 0 ); + + mCityCombo->blockSignals( false ); + mLatDegrees->blockSignals( false ); + mLatMinutes->blockSignals( false ); + mLatSeconds->blockSignals( false ); + mLatDirection->blockSignals( false ); + mLongDegrees->blockSignals( false ); + mLongMinutes->blockSignals( false ); + mLongSeconds->blockSignals( false ); + mLongDirection->blockSignals( false ); +} + +void GeoDialog::loadCityList() +{ + mCityCombo->clear(); + mGeoDataMap.clear(); + + QString fileName ; +#ifdef DESKTOP_VERSION +#ifndef _WIN32_ + fileName = qApp->applicationDirPath () + "/kdepim/kaddressbook/zone.tab"; +#else + fileName = qApp->applicationDirPath () + "\\kdepim\\kaddressbook\\zone.tab"; +#endif +#else + fileName = getenv("QPEDIR"); + fileName += "/pics/kdepim/kaddressbook/zone.tab"; +#endif + + QFile file( fileName); + + if ( file.open( IO_ReadOnly ) ) { + QTextStream s( &file ); + + QString line, country; + QRegExp coord( "[+-]\\d+[+-]\\d+" ); + QRegExp name( "[^\\s]+/[^\\s]+" ); + int posc, posn, pos; + + while ( !s.eof() ) { + line = s.readLine().stripWhiteSpace(); + if ( line.isEmpty() || line[ 0 ] == '#' ) + continue; + + country = line.left( 2 ); + QString c, n; +#ifdef DESKTOP_VERSION + posc = coord.search( line, 0 ); +#else + posc = coord.find( line, 0 ); +#endif + // if ( pos >= 0 ) + //c = line.mid( pos, coord.matchedLength() ); + +#ifdef DESKTOP_VERSION + posn = name.search(line, posc); +#else + posn = name.find(line, posc); +#endif + if ( posn > 0 ) { + c = line.mid( posc, posn-posc ).stripWhiteSpace(); + //qDebug("*%s* ", c.latin1()); + int nend = line.find(" ", posn ); + if ( nend < 0 ) + nend = line.length(); + n = line.mid( posn, nend-posn).stripWhiteSpace(); + //n.replace( '_', " " ); + } + + if ( !c.isEmpty() && !n.isEmpty() ) { + pos = c.find( "+", 1 ); + if ( pos < 0 ) + pos = c.find( "-", 1 ); + if ( pos > 0 ) { + GeoData data; + data.latitude = calculateCoordinate( c.left( pos ) ); + data.longitude = calculateCoordinate( c.mid( pos ) ); + data.country = country; + + mGeoDataMap.insert( n, data ); + } + } + } +//US I have no mGeoDataMap.keys(). +//US QStringList items( mGeoDataMap.keys() ); + QStringList items; + + QMap<QString, GeoData>::ConstIterator it; + for( it = mGeoDataMap.begin(); it != mGeoDataMap.end(); ++it ) + items << it.key().latin1(); + + items.prepend( i18n( "Undefined" ) ); + mCityCombo->insertStringList( items ); + + file.close(); + } +} + +double GeoDialog::calculateCoordinate( const QString &coordinate ) +{ + int neg; + int d = 0, m = 0, s = 0; + QString str = coordinate; + + neg = str.left( 1 ) == "-"; + str.remove( 0, 1 ); + + switch ( str.length() ) { + case 4: + d = str.left( 2 ).toInt(); + m = str.mid( 2 ).toInt(); + break; + case 5: + d = str.left( 3 ).toInt(); + m = str.mid( 3 ).toInt(); + break; + case 6: + d = str.left( 2 ).toInt(); + m = str.mid( 2, 2 ).toInt(); + s = str.right( 2 ).toInt(); + break; + case 7: + d = str.left( 3 ).toInt(); + m = str.mid( 3, 2 ).toInt(); + s = str.right( 2 ).toInt(); + break; + default: + break; + } + + if ( neg ) + return - ( d + m / 60.0 + s / 3600.0 ); + else + return d + m / 60.0 + s / 3600.0; +} + +int GeoDialog::nearestCity( double x, double y ) +{ + QMap<QString, GeoData>::Iterator it; + int pos = 0; + for ( it = mGeoDataMap.begin(); it != mGeoDataMap.end(); ++it, pos++ ) { + double dist = ( (*it).longitude - x ) * ( (*it).longitude - x ) + + ( (*it).latitude - y ) * ( (*it).latitude - y ); + if ( dist < 1.5 ) + return pos; + } + + return -1; +} + + +GeoMapWidget::GeoMapWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ), mLatitude( 0 ), mLongitude( 0 ) +{ + setBackgroundMode( NoBackground ); + + setFixedSize( 240, 120 ); + + update(); +} + +GeoMapWidget::~GeoMapWidget() +{ +} + +void GeoMapWidget::setLatitude( double latitude ) +{ + mLatitude = latitude; +} + +double GeoMapWidget::latitude()const +{ + return mLatitude; +} + +void GeoMapWidget::setLongitude( double longitude ) +{ + mLongitude = longitude; +} + +double GeoMapWidget::longitude()const +{ + return mLongitude; +} + +void GeoMapWidget::mousePressEvent( QMouseEvent *event ) +{ + double latMid = height() / 2; + double longMid = width() / 2; + + double latOffset = latMid - event->y(); + double longOffset = event->x() - longMid; + + mLatitude = ( latOffset * 90 ) / latMid; + mLongitude = ( longOffset * 180 ) / longMid; + + emit changed(); +} + +void GeoMapWidget::paintEvent( QPaintEvent* ) +{ + uint w = width(); + uint h = height(); + + QPixmap world = KGlobal::iconLoader()->loadIcon( "world", KIcon::Desktop, 0 ); + + QPainter p; + p.begin( &world, this ); + + p.setPen( QColor( 255, 0, 0 ) ); + p.setBrush( QColor( 255, 0, 0 ) ); + + double latMid = h / 2; + double longMid = w / 2; + + double latOffset = ( mLatitude * latMid ) / 90; + double longOffset = ( mLongitude * longMid ) / 180; + + int x = (int)(longMid + longOffset); + int y = (int)(latMid - latOffset); + p.drawEllipse( x, y, 4, 4 ); + + p.end(); + bitBlt( this, 0, 0, &world ); +} + +#ifndef KAB_EMBEDDED +#include "geowidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/geowidget.h b/kaddressbook/geowidget.h new file mode 100644 index 0000000..3d39691 --- a/dev/null +++ b/kaddressbook/geowidget.h @@ -0,0 +1,155 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef GEOWIDGET_H +#define GEOWIDGET_H + +#include <qmap.h> + +#include <qwidget.h> +#include <kdialogbase.h> + +namespace KABC { +class Geo; +} + +class GeoMapWidget; + +class KComboBox; +class KDoubleSpinBox; + +class QCheckBox; +class QLabel; +class QSpinBox; +class QPushButton; + +typedef struct { + double latitude; + double longitude; + QString country; +} GeoData; + +class GeoWidget : public QWidget +{ + Q_OBJECT + + public: + GeoWidget( QWidget *parent, const char *name = 0 ); + ~GeoWidget(); + + /** + Sets the geo object. + */ + void setGeo( const KABC::Geo &geo ); + + /** + Returns a geo object. + */ + KABC::Geo geo() const; + + signals: + void changed(); + + private slots: + void editGeoData(); + + private: + KDoubleSpinBox *mLatitudeBox; + KDoubleSpinBox *mLongitudeBox; + + QCheckBox *mGeoIsValid; + QPushButton *mExtendedButton; +}; + +class GeoDialog : public KDialogBase +{ + Q_OBJECT + + public: + GeoDialog( QWidget *parent, const char *name = 0 ); + ~GeoDialog(); + + void setLatitude( double latitude ); + double latitude() const; + + void setLongitude( double longitude ); + double longitude() const; + + private slots: + void updateInputs(); + + void sexagesimalInputChanged(); + void geoMapChanged(); + void cityInputChanged(); + + private: + void loadCityList(); + double calculateCoordinate( const QString& ); + int nearestCity( double, double ); + + GeoMapWidget *mMapWidget; + KComboBox *mCityCombo; + + QSpinBox *mLatDegrees; + QSpinBox *mLatMinutes; + QSpinBox *mLatSeconds; + KComboBox *mLatDirection; + + QSpinBox *mLongDegrees; + QSpinBox *mLongMinutes; + QSpinBox *mLongSeconds; + KComboBox *mLongDirection; + + double mLatitude; + double mLongitude; + QMap<QString, GeoData> mGeoDataMap; + bool mUpdateSexagesimalInput; +}; + +class GeoMapWidget : public QWidget +{ + Q_OBJECT + + public: + GeoMapWidget( QWidget *parent, const char *name = 0 ); + ~GeoMapWidget(); + + void setLatitude( double latitude ); + double latitude()const; + + void setLongitude( double longitude ); + double longitude()const; + + signals: + void changed(); + + protected: + virtual void mousePressEvent( QMouseEvent* ); + virtual void paintEvent( QPaintEvent* ); + + private: + double mLatitude; + double mLongitude; +}; + +#endif diff --git a/kaddressbook/imagewidget.cpp b/kaddressbook/imagewidget.cpp new file mode 100644 index 0000000..49d456b --- a/dev/null +++ b/kaddressbook/imagewidget.cpp @@ -0,0 +1,299 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kabc/picture.h> + +#ifndef KAB_EMBEDDED +#include <kaccelmanager.h> +#include <kio/netaccess.h> +#include <kimageio.h> +#endif //KAB_EMBEDDED + +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kurlrequester.h> +#include <kurl.h> + +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpixmap.h> +#include <qapplication.h> + +#include "imagewidget.h" + +ImageWidget::ImageWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QGridLayout *topLayout = new QGridLayout( this, 2, 1, KDialog::marginHint(), + KDialog::spacingHint() ); + + QGroupBox *photoBox = new QGroupBox( 0, Qt::Vertical, i18n( "Photo" ), this ); + QGridLayout *boxLayout = new QGridLayout( photoBox->layout(), 3, 2, + KDialog::spacingHint() ); + boxLayout->setRowStretch( 2, 1 ); + + mPhotoLabel = new QLabel( photoBox ); + int fac = 9; + if ( QApplication::desktop()->width() > 320 ) + fac = 6; + mPhotoLabel->setFixedSize( 50*9/fac, 70*9/fac ); + mPhotoLabel->setScaledContents( true ); + mPhotoLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + boxLayout->addMultiCellWidget( mPhotoLabel, 0, 2, 0, 0 ); + + mPhotoUrl = new KURLRequester( photoBox ); +#ifndef KAB_EMBEDDED + mPhotoUrl->setFilter( KImageIO::pattern() ); +#else //KAB_EMBEDDED +//US qDebug("ImageWidget::ImageWidget KImageIO not defined. Does this harm ???"); +#endif //KAB_EMBEDDED + + + boxLayout->addWidget( mPhotoUrl, 0, 1 ); + + mUsePhotoUrl = new QCheckBox( i18n( "Store as URL" ), photoBox ); + mUsePhotoUrl->setEnabled( false ); + boxLayout->addWidget( mUsePhotoUrl, 1, 1 ); + + topLayout->addWidget( photoBox, 0, 0 ); + + QGroupBox *logoBox = new QGroupBox( 0, Qt::Vertical, i18n( "Logo" ), this ); + boxLayout = new QGridLayout( logoBox->layout(), 3, 2, KDialog::spacingHint() ); + boxLayout->setRowStretch( 2, 1 ); + + mLogoLabel = new QLabel( logoBox ); + mLogoLabel->setFixedSize( 50*9/fac, 70*9/fac ); + mLogoLabel->setScaledContents( true ); + mLogoLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + boxLayout->addMultiCellWidget( mLogoLabel, 0, 2, 0, 0 ); + + mLogoUrl = new KURLRequester( logoBox ); +#ifndef KAB_EMBEDDED + mLogoUrl->setFilter( KImageIO::pattern() ); +#else //KAB_EMBEDDED +//US qDebug("ImageWidget::ImageWidget KImageIO not defined 2"); +#endif //KAB_EMBEDDED + boxLayout->addWidget( mLogoUrl, 0, 1 ); + + mUseLogoUrl = new QCheckBox( i18n( "Store as URL" ), logoBox ); + mUseLogoUrl->setEnabled( false ); + boxLayout->addWidget( mUseLogoUrl, 1, 1 ); + + topLayout->addWidget( logoBox, 1, 0 ); + + connect( mPhotoUrl, SIGNAL( textChanged( const QString& ) ), + SIGNAL( changed() ) ); + connect( mPhotoUrl, SIGNAL( urlSelected( const QString& ) ), + SLOT( loadPhoto() ) ); + connect( mPhotoUrl, SIGNAL( urlSelected( const QString& ) ), + SIGNAL( changed() ) ); + connect( mPhotoUrl, SIGNAL( urlSelected( const QString& ) ), + SLOT( updateGUI() ) ); + connect( mUsePhotoUrl, SIGNAL( toggled( bool ) ), + SIGNAL( changed() ) ); + + connect( mLogoUrl, SIGNAL( textChanged( const QString& ) ), + SIGNAL( changed() ) ); + connect( mLogoUrl, SIGNAL( urlSelected( const QString& ) ), + SLOT( loadLogo() ) ); + connect( mLogoUrl, SIGNAL( urlSelected( const QString& ) ), + SIGNAL( changed() ) ); + connect( mLogoUrl, SIGNAL( urlSelected( const QString& ) ), + SLOT( updateGUI() ) ); + connect( mUseLogoUrl, SIGNAL( toggled( bool ) ), + SIGNAL( changed() ) ); + +#ifndef KAB_EMBEDDED + KAcceleratorManager::manage( this ); +#endif //KAB_EMBEDDED + +#ifndef DESKTOP_VERSION + mUsePhotoUrl->setChecked( true ); + mUseLogoUrl->setChecked( true ); +#endif +} + +ImageWidget::~ImageWidget() +{ +} + +void ImageWidget::setPhoto( const KABC::Picture &photo ) +{ + bool blocked = signalsBlocked(); + blockSignals( true ); + + if ( photo.isIntern() ) { +//US +//US mPhotoLabel->setPixmap( photo.data() ); + if (photo.data().isNull() != true) + { + QPixmap pm; + pm.convertFromImage(photo.data()); + + mPhotoLabel->setPixmap( pm ); + } + + mUsePhotoUrl->setChecked( false ); + } else { + mPhotoUrl->setURL( photo.url() ); + if ( !photo.url().isEmpty() ) + mUsePhotoUrl->setChecked( true ); + loadPhoto(); + } + + blockSignals( blocked ); +} + +KABC::Picture ImageWidget::photo() const +{ + KABC::Picture photo; + + if ( mUsePhotoUrl->isChecked() ) + photo.setUrl( mPhotoUrl->url() ); + else { + QPixmap *px = mPhotoLabel->pixmap(); + if ( px ) { +#ifndef KAB_EMBEDDED + if ( px->height() > px->width() ) + photo.setData( px->convertToImage().scaleHeight( 140 ) ); + else + photo.setData( px->convertToImage().scaleWidth( 100 ) ); +#else //KAB_EMBEDDED +//US add teh nullcheck + if (px->isNull() != true ) + photo.setData( px->convertToImage() ); +#endif //KAB_EMBEDDED + + photo.setType( "PNG" ); + } + } + + return photo; +} + +void ImageWidget::setLogo( const KABC::Picture &logo ) +{ + bool blocked = signalsBlocked(); + blockSignals( true ); + + if ( logo.isIntern() ) { +//US +//US mLogoLabel->setPixmap( logo.data() ); + if (logo.data().isNull() != true) + { + QPixmap pm; + pm.convertFromImage(logo.data()); + mLogoLabel->setPixmap( pm ); + } + mUseLogoUrl->setChecked( false ); + } else { + mLogoUrl->setURL( logo.url() ); + if ( !logo.url().isEmpty() ) + mUseLogoUrl->setChecked( true ); + loadLogo(); + } + + blockSignals( blocked ); +} + +KABC::Picture ImageWidget::logo() const +{ + KABC::Picture logo; + + if ( mUseLogoUrl->isChecked() ) + logo.setUrl( mLogoUrl->url() ); + else { + QPixmap *px = mLogoLabel->pixmap(); + if ( px ) { +#ifndef KAB_EMBEDDED + if ( px->height() > px->width() ) + logo.setData( px->convertToImage().scaleHeight( 140 ) ); + else + logo.setData( px->convertToImage().scaleWidth( 100 ) ); +#else //KAB_EMBEDDED + logo.setData( px->convertToImage() ); +#endif //KAB_EMBEDDED + + logo.setType( "PNG" ); + + } + } + + return logo; +} + +void ImageWidget::loadPhoto() +{ + mPhotoLabel->setPixmap( loadPixmap( mPhotoUrl->url() ) ); +} + +void ImageWidget::loadLogo() +{ + mLogoLabel->setPixmap( loadPixmap( mLogoUrl->url() ) ); +} + +void ImageWidget::updateGUI() +{ + KURLRequester *ptr = (KURLRequester*)sender(); + +#ifdef DESKTOP_VERSION + if ( ptr == mPhotoUrl ) + mUsePhotoUrl->setEnabled( true ); + else if ( ptr == mLogoUrl ) + mUseLogoUrl->setEnabled( true ); +#endif +} + +QPixmap ImageWidget::loadPixmap( const KURL &url ) +{ + QString tempFile; + QPixmap pixmap; + + if ( url.isEmpty() ) + return pixmap; + + if ( url.isLocalFile() ) + pixmap = QPixmap( url.path() ); + else + { +#ifndef KAB_EMBEDDED + if ( KIO::NetAccess::download( url, tempFile ) ) { + pixmap = QPixmap( tempFile ); + KIO::NetAccess::removeTempFile( tempFile ); + } +#else //KAB_EMBEDDED + qDebug("ImageWidget::loadPixmap : only local pixmaps are allowed"); +#endif //KAB_EMBEDDED + + } + + return pixmap; +} + +#ifndef KAB_EMBEDDED +#include "imagewidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/imagewidget.h b/kaddressbook/imagewidget.h new file mode 100644 index 0000000..b3ca0bd --- a/dev/null +++ b/kaddressbook/imagewidget.h @@ -0,0 +1,86 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef IMAGEWIDGET_H +#define IMAGEWIDGET_H + +#include <qwidget.h> + +#include <kabc/picture.h> +#include <kdialogbase.h> + +class KURL; +class KURLRequester; + +class QCheckBox; +class QLabel; + +class ImageWidget : public QWidget +{ + Q_OBJECT + + public: + ImageWidget( QWidget *parent, const char *name = 0 ); + ~ImageWidget(); + + /** + Sets the photo object. + */ + void setPhoto( const KABC::Picture &photo ); + + /** + Returns a photo object. + */ + KABC::Picture photo() const; + + /** + Sets the logo object. + */ + void setLogo( const KABC::Picture &photo ); + + /** + Returns a logo object. + */ + KABC::Picture logo() const; + + signals: + void changed(); + + private slots: + void loadPhoto(); + void loadLogo(); + void updateGUI(); + + private: + QPixmap loadPixmap( const KURL &url ); + + KURLRequester *mPhotoUrl; + KURLRequester *mLogoUrl; + + QCheckBox *mUsePhotoUrl; + QCheckBox *mUseLogoUrl; + QLabel *mPhotoLabel; + QLabel *mLogoLabel; +}; + +#endif diff --git a/kaddressbook/incsearchwidget.cpp b/kaddressbook/incsearchwidget.cpp new file mode 100644 index 0000000..94c37e7 --- a/dev/null +++ b/kaddressbook/incsearchwidget.cpp @@ -0,0 +1,147 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlabel.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qcombobox.h> + +#include <kdialog.h> +#include <klineedit.h> +#include <klocale.h> +#include <kglobal.h> + +#include "incsearchwidget.h" + +IncSearchWidget::IncSearchWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ +#ifndef KAB_EMBEDDED +//US setCaption( i18n( "Incremental Search" ) ); +#endif //KAB_EMBEDDED + + QHBoxLayout *layout = new QHBoxLayout( this, 2, KDialog::spacingHint() ); + +#ifdef DESKTOP_VERSION + QLabel *label = new QLabel( i18n( "Search:" ), this ); + label->setAlignment( QLabel::AlignVCenter | QLabel::AlignRight ); + layout->addWidget( label ); +#endif //KAB_EMBEDDED + + mSearchText = new KLineEdit( this ); + layout->addWidget( mSearchText ); +// #ifdef KAB_EMBEDDED +// if (KGlobal::getOrientation() == KGlobal::Portrait) +// mSearchText->setMaximumWidth(30); +// #endif //KAB_EMBEDDED + + + mFieldCombo = new QComboBox( false, this ); + layout->addWidget( mFieldCombo ); + mFieldCombo->setMaximumHeight( 34 ); + QToolTip::add( mFieldCombo, i18n( "Select Incremental Search Field" ) ); + +// #ifndef KAB_EMBEDDED +// resize( QSize(420, 50).expandedTo( sizeHint() ) ); +// #else //KAB_EMBEDDED +// resize( QSize(30, 10).expandedTo( sizeHint() ) ); +// #endif //KAB_EMBEDDED + + connect( mSearchText, SIGNAL( textChanged( const QString& ) ), + SLOT( announceDoSearch() ) ); + connect( mSearchText, SIGNAL( returnPressed() ), + SLOT( announceDoSearch() ) ); + connect( mFieldCombo, SIGNAL( activated( const QString& ) ), + SLOT( announceDoSearch() ) ); + connect( mFieldCombo, SIGNAL( activated( const QString& ) ), + SLOT( announceFieldChanged() ) ); + + setFocusProxy( mSearchText ); +} + +IncSearchWidget::~IncSearchWidget() +{ + +} + +void IncSearchWidget::announceDoSearch() +{ + emit doSearch( mSearchText->text() ); +} + +void IncSearchWidget::announceFieldChanged() +{ + emit fieldChanged(); +} + +void IncSearchWidget::setFields( const KABC::Field::List &list ) +{ + + mFieldCombo->clear(); + mFieldCombo->insertItem( i18n( "All Fields" ) ); + QFontMetrics fm ( mFieldCombo->font() ); + int wid = fm.width(i18n( "All Fields" ) ); + int max = wid; + + KABC::Field::List::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + mFieldCombo->insertItem( (*it)->label() ); + // wid = fm.width((*it)->label() ); + //if ( wid > max ) + // max = wid; + } + + mFieldList = list; + + announceDoSearch(); + announceFieldChanged(); + mFieldCombo->setMaximumWidth( wid+60 ); +} + +KABC::Field::List IncSearchWidget::fields() const +{ + return mFieldList; +} + +KABC::Field *IncSearchWidget::currentField()const +{ + if ( mFieldCombo->currentItem() == -1 || mFieldCombo->currentItem() == 0 ) + return 0; // for error or 'use all fields' + else + return mFieldList[ mFieldCombo->currentItem() - 1 ]; +} + +void IncSearchWidget::setCurrentItem( int pos ) +{ + mFieldCombo->setCurrentItem( pos ); + announceFieldChanged(); +} + +int IncSearchWidget::currentItem() const +{ + + return mFieldCombo->currentItem(); +} +#ifndef KAB_EMBEDDED +#include "incsearchwidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/incsearchwidget.h b/kaddressbook/incsearchwidget.h new file mode 100644 index 0000000..09fb8ac --- a/dev/null +++ b/kaddressbook/incsearchwidget.h @@ -0,0 +1,73 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef INCSEARCHWIDGET_H +#define INCSEARCHWIDGET_H + +#include <qwidget.h> + +#include <kabc/field.h> + +class QComboBox; +class KLineEdit; + +class IncSearchWidget : public QWidget +{ + Q_OBJECT + + public: + IncSearchWidget( QWidget *parent, const char *name = 0 ); + ~IncSearchWidget(); + + void setFields( const KABC::Field::List &list ); + KABC::Field::List fields() const; + + KABC::Field *currentField() const; + + void setCurrentItem( int pos ); + int currentItem() const; + + signals: + /** + This signal is emmited whenever the text in the input + widget is changed. You can get the sorting field by + @ref currentField. + */ + void doSearch( const QString& text ); + + /** + This signal is emmited whenever the search field changes. + */ + void fieldChanged(); + + private slots: + void announceDoSearch(); + void announceFieldChanged(); + + private: + QComboBox* mFieldCombo; + KLineEdit* mSearchText; + KABC::Field::List mFieldList; +}; + +#endif diff --git a/kaddressbook/jumpbuttonbar.cpp b/kaddressbook/jumpbuttonbar.cpp new file mode 100644 index 0000000..ee5b44e --- a/dev/null +++ b/kaddressbook/jumpbuttonbar.cpp @@ -0,0 +1,232 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qevent.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qtl.h> +#include <qapplication.h> + +#include <kabc/addressbook.h> +#include <kabc/field.h> +#include <kdebug.h> +#include <klocale.h> + +#include "kabcore.h" + +#include "jumpbuttonbar.h" + +class JumpButton : public QPushButton +{ + public: + JumpButton( const QString &text, QWidget *parent, + const QString &character ); + + void setCharacter( const QString &character ); + QString character() const; + + private: + QString mCharacter; +}; + +JumpButton::JumpButton( const QString &text, QWidget *parent, + const QString &character ) + : QPushButton( text, parent ) +{ + mCharacter = character; +} + +void JumpButton::setCharacter( const QString &character ) +{ + mCharacter = character; + setText(mCharacter.upper() ); +} + +QString JumpButton::character() const +{ + return mCharacter; +} + +JumpButtonBar::JumpButtonBar( KABCore *core, QWidget *parent, const char *name ) + : QWidget( parent, name ), mCore( core ) +{ + if ( QApplication::desktop()->width() < 480 ) + + mButtonLayout = new QGridLayout( this, 2, 14 ); + else + mButtonLayout = new QGridLayout( this, 1, 28 ); + mButtonLayout->setAlignment( Qt::AlignTop ); + + recreateButtons(); +} + +JumpButtonBar::~JumpButtonBar() +{ +} + +QSizePolicy JumpButtonBar::sizePolicy() const +{ +#ifndef KAB_EMBEDDED + return QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Minimum, + QSizePolicy::Vertically ); +#else //KAB_EMBEDDED + return QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Minimum); +#endif //KAB_EMBEDDED +} + +void JumpButtonBar::letterClicked() +{ + JumpButton *button = (JumpButton*)sender(); + QString character = button->character(); + if ( !character.isNull() ) + emit jumpToLetter( character ); +} + +void JumpButtonBar::recreateButtons() +{ + // the easiest way to remove all buttons ;) + //mButtons.setAutoDelete( true ); + //mButtons.clear(); + //mButtons.setAutoDelete( false ); + mCharacters.clear(); + + QString character; + + KABC::AddressBook *ab = mCore->addressBook(); + KABC::AddressBook::Iterator it; + KABC::Field *field = mCore->currentSearchField(); + if ( field ) { + setEnabled( true ); + } else { + setEnabled( false ); + return; + } + for ( it = ab->begin(); it != ab->end(); ++it ) { + if ( !field->value( *it ).isEmpty() ) + character = field->value( *it )[ 0 ].lower(); + if ( !character.isEmpty() && !mCharacters.contains( character ) ) + mCharacters.append( character ); + } + if ( mCharacters.count() == 0 ) { + setEnabled( false ); + return; + } + + int maxRows = mCharacters.count() / 2; // we use 2 columns + if ( mCharacters.count() % 2 ) + maxRows++; + int fixwid = 20; + sortListLocaleAware( mCharacters ); + bool skip2 = false; + int skipcount = 0; + int maxHei = 25; + if ( QApplication::desktop()->width() < 480 && mCharacters.count() > 13) { + skipcount = mCharacters.count()-13; + maxHei = (QApplication::desktop()->height()-65)/13; + } + else { + fixwid = 30; + if ( mCharacters.count() > 20 ) + skipcount = mCharacters.count()- 20; + maxHei = (QApplication::desktop()->height()-120)/(mCharacters.count()-skipcount); + + } + maxRows = 28; + bool skipcurrent = false; + bool state = isUpdatesEnabled(); + setUpdatesEnabled( false ); + //qDebug("cc %d ",mCharacters.count() ); + JumpButton *button; + int row = 0, col = 0; + JumpButton* cur = mButtons.first(); + for ( uint i = 0; i < mCharacters.count(); ++i ) { + if ( skipcount > 0 && skipcurrent ) { + --skipcount; + } else { + if ( cur ) { + button = cur ; + cur = mButtons.next(); + button->setCharacter(mCharacters[ i ]); + } else { + button = new JumpButton( mCharacters[ i ].upper(), this, mCharacters[ i ] ); + button->setFixedWidth( fixwid ); + mButtons.append( button ); + connect( button, SIGNAL( clicked() ), this, SLOT( letterClicked() ) ); + mButtonLayout->addWidget( button, row, col ); + } + button->setMaximumHeight( maxHei ); + button->show(); + + if ( col == maxRows ) { + row = 0; + col++; + } else + row++; + } + + skipcurrent = !skipcurrent; + } + while ( cur ) { + cur->hide(); + cur = mButtons.next(); + } + + mButtonLayout->activate(); + setUpdatesEnabled( state ); + update(); +} + +void JumpButtonBar::sortListLocaleAware( QStringList &list ) +{ + QStringList::Iterator beginIt = list.begin(); + QStringList::Iterator endIt = list.end(); + + --endIt; + if ( beginIt == endIt ) // don't need sorting + return; + + QStringList::Iterator walkBackIt = endIt; + while ( beginIt != endIt ) { + QStringList::Iterator j1 = list.begin(); + QStringList::Iterator j2 = j1; + ++j2; + while ( j1 != walkBackIt ) { +#ifndef KAB_EMBEDDED + if ( QString::localeAwareCompare( *j2, *j1 ) < 0 ) +#else //KAB_EMBEDDED + if ( QString::compare( *j2, *j1 ) < 0 ) +#endif //KAB_EMBEDDED + qSwap( *j1, *j2 ); + + ++j1; + ++j2; + } + ++beginIt; + --walkBackIt; + } +} + +#ifndef KAB_EMBEDDED +#include "jumpbuttonbar.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/jumpbuttonbar.h b/kaddressbook/jumpbuttonbar.h new file mode 100644 index 0000000..d534f2b --- a/dev/null +++ b/kaddressbook/jumpbuttonbar.h @@ -0,0 +1,84 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef JUMPBUTTONBAR_H +#define JUMPBUTTONBAR_H + +#include <qsizepolicy.h> +#include <qwidget.h> +#include <qptrlist.h> +#include <qstringlist.h> + +class QChar; +class QGridLayout; +class QResizeEvent; +class QPushButton; +class JumpButton; + +namespace KABC { +class Field; +} + +class KABCore; + +/** + Used to draw the jump button bar on the right of the view. + */ +class JumpButtonBar : public QWidget +{ + Q_OBJECT + + public: + JumpButtonBar( KABCore *core, QWidget *parent, const char *name = 0 ); + ~JumpButtonBar(); + + QSizePolicy sizePolicy() const; + + public slots: + /** + This method removes all buttons from the GUI and recreates them + according to the current global search field and the content of + the address book. + */ + void recreateButtons(); + + signals: + /** + Emitted whenever a letter is selected by the user. + */ + void jumpToLetter( const QString &character ); + + protected slots: + void letterClicked(); + + private: + void sortListLocaleAware( QStringList &list ); + + KABCore *mCore; + + QGridLayout *mButtonLayout; + QStringList mCharacters; + QPtrList<JumpButton> mButtons; +}; + +#endif diff --git a/kaddressbook/kabcore.cpp b/kaddressbook/kabcore.cpp new file mode 100644 index 0000000..3e578bc --- a/dev/null +++ b/kaddressbook/kabcore.cpp @@ -0,0 +1,1571 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "kabcore.h" + +#include <stdaddressbook.h> +#include <klocale.h> + +#ifndef KAB_EMBEDDED +#include <qclipboard.h> +#include <qdir.h> +#include <qfile.h> +#include <qapplicaton.h> +#include <qlayout.h> +#include <qregexp.h> +#include <qvbox.h> +#include <kabc/addresseelist.h> +#include <kabc/errorhandler.h> +#include <kabc/resource.h> +#include <kabc/vcardconverter.h> +#include <kapplication.h> +#include <kactionclasses.h> +#include <kcmultidialog.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <kkeydialog.h> +#include <kmessagebox.h> +#include <kprinter.h> +#include <kprotocolinfo.h> +#include <kresources/selectdialog.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kxmlguiclient.h> +#include <kaboutdata.h> +#include <libkdepim/categoryselectdialog.h> + +#include "addresseeutil.h" +#include "addresseeeditordialog.h" +#include "extensionmanager.h" +#include "kstdaction.h" +#include "kaddressbookservice.h" +#include "ldapsearchdialog.h" +#include "printing/printingwizard.h" +#else // KAB_EMBEDDED + +#include "KDGanttMinimizeSplitter.h" +#include "kaddressbookmain.h" +#include "kactioncollection.h" +#include <qapp.h> +#include <qmenubar.h> +//#include <qtoolbar.h> +#include <qmessagebox.h> +#include <kdebug.h> +#include <kiconloader.h> // needed for SmallIcon +#include <kresources/kcmkresources.h> +#include <ktoolbar.h> + +#include <kcmkabconfig.h> + +//US#include <qpe/resource.h> // needed for Resource::loadPixmap +//#include <qlabel.h> +#endif // KAB_EMBEDDED +#include <kcmkabconfig.h> + + +#include <kresources/selectdialog.h> +#include <kmessagebox.h> + +#include <picture.h> +#include <resource.h> + +//US#include <qsplitter.h> +#include <qvbox.h> +#include <qlayout.h> +#include <qclipboard.h> + +#include <libkdepim/categoryselectdialog.h> + +#include "addresseeutil.h" +#include "undocmds.h" +#include "addresseeeditordialog.h" +#include "viewmanager.h" +#include "details/detailsviewcontainer.h" +#include "kabprefs.h" +#include "xxportmanager.h" +#include "incsearchwidget.h" +#include "jumpbuttonbar.h" +#include "extensionmanager.h" +#include "addresseeconfig.h" +#include <kcmultidialog.h> + + +#ifdef KAB_EMBEDDED +KABCore::KABCore( KAddressBookMain *client, bool readWrite, QWidget *parent, const char *name ) + : QWidget( parent, name ), mGUIClient( client ), mViewManager( 0 ), + mExtensionManager( 0 ),mConfigureDialog( 0 ),/*US mLdapSearchDialog( 0 ),*/ + mReadWrite( readWrite ), mModified( false ), mMainWindow(client) +#else //KAB_EMBEDDED +KABCore::KABCore( KXMLGUIClient *client, bool readWrite, QWidget *parent, const char *name ) + : QWidget( parent, name ), mGUIClient( client ), mViewManager( 0 ), + mExtensionManager( 0 ), mConfigureDialog( 0 ), mLdapSearchDialog( 0 ), + mReadWrite( readWrite ), mModified( false ) +#endif //KAB_EMBEDDED +{ +#ifdef KAB_EMBEDDED + //US we define here our own global actioncollection. + //mActionCollection = new KActionCollection(this); +#endif //KAB_EMBEDDED + + mIsPart = !parent->inherits( "KAddressBookMain" ); + + mAddressBook = KABC::StdAddressBook::self(); + KABC::StdAddressBook::setAutomaticSave( true ); + +#ifndef KAB_EMBEDDED + mAddressBook->setErrorHandler( new KABC::GUIErrorHandler ); +#endif //KAB_EMBEDDED + + connect( mAddressBook, SIGNAL( addressBookChanged( AddressBook * ) ), + SLOT( addressBookChanged() ) ); + + mAddressBook->addCustomField( i18n( "Department" ), KABC::Field::Organization, + "X-Department", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Profession" ), KABC::Field::Organization, + "X-Profession", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Assistant's Name" ), KABC::Field::Organization, + "X-AssistantsName", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Manager's Name" ), KABC::Field::Organization, + "X-ManagersName", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Spouse's Name" ), KABC::Field::Personal, + "X-SpousesName", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Office" ), KABC::Field::Personal, + "X-Office", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "IM Address" ), KABC::Field::Personal, + "X-IMAddress", "KADDRESSBOOK" ); + mAddressBook->addCustomField( i18n( "Anniversary" ), KABC::Field::Personal, + "X-Anniversary", "KADDRESSBOOK" ); + + initGUI(); + + mIncSearchWidget->setFocus(); + + + connect( mViewManager, SIGNAL( selected( const QString& ) ), + SLOT( setContactSelected( const QString& ) ) ); + connect( mViewManager, SIGNAL( executed( const QString& ) ), + SLOT( editContact( const QString& ) ) ); + connect( mViewManager, SIGNAL( deleteRequest( ) ), + SLOT( deleteContacts( ) ) ); + connect( mViewManager, SIGNAL( modified() ), + SLOT( setModified() ) ); + + connect( mExtensionManager, SIGNAL( modified( const KABC::Addressee::List& ) ), this, SLOT( extensionModified( const KABC::Addressee::List& ) ) ); + + connect( mXXPortManager, SIGNAL( modified() ), + SLOT( setModified() ) ); + + connect( mJumpButtonBar, SIGNAL( jumpToLetter( const QString& ) ), + SLOT( incrementalSearch( const QString& ) ) ); + connect( mIncSearchWidget, SIGNAL( fieldChanged() ), + mJumpButtonBar, SLOT( recreateButtons() ) ); + +#ifndef KAB_EMBEDDED + connect( mViewManager, SIGNAL( urlDropped( const KURL& ) ), + mXXPortManager, SLOT( importVCard( const KURL& ) ) ); + + connect( mDetails, SIGNAL( sendEmail( const QString& ) ), + SLOT( sendMail( const QString& ) ) ); + connect( mDetails, SIGNAL( browse( const QString& ) ), + SLOT( browse( const QString& ) ) ); + + mAddressBookService = new KAddressBookService( this ); + +#endif //KAB_EMBEDDED + + setModified( false ); +} + +KABCore::~KABCore() +{ + // save(); + //saveSettings(); + //KABPrefs::instance()->writeConfig(); + delete AddresseeConfig::instance(); + mAddressBook = 0; + KABC::StdAddressBook::close(); + +#ifdef KAB_EMBEDDED + //US we define here our own global actioncollection. + // delete mActionCollection; +#endif //KAB_EMBEDDED + +} + +void KABCore::restoreSettings() +{ + bool state = KABPrefs::instance()->mJumpButtonBarVisible; + + mActionJumpBar->setChecked( state ); + setJumpButtonBarVisible( state ); + + state = KABPrefs::instance()->mDetailsPageVisible; + + mActionDetails->setChecked( state ); + setDetailsVisible( state ); + QValueList<int> splitterSize = KABPrefs::instance()->mExtensionsSplitter; + if ( splitterSize.count() == 0 ) { + splitterSize.append( width() / 2 ); + splitterSize.append( width() / 2 ); + } + mMiniSplitter->setSizes( splitterSize ); +#ifndef KAB_EMBEDDED + QValueList<int> splitterSize = KABPrefs::instance()->mExtensionsSplitter; + if ( splitterSize.count() == 0 ) { + splitterSize.append( width() / 2 ); + splitterSize.append( width() / 2 ); + } + mExtensionBarSplitter->setSizes( splitterSize ); + + splitterSize = KABPrefs::instance()->mDetailsSplitter; + if ( splitterSize.count() == 0 ) { + splitterSize.append( height() / 2 ); + splitterSize.append( height() / 2 ); + } + mDetailsSplitter->setSizes( splitterSize ); + + mExtensionManager->restoreSettings(); + +#endif //KAB_EMBEDDED + + mIncSearchWidget->setCurrentItem( KABPrefs::instance()->mCurrentIncSearchField ); + + mViewManager->restoreSettings(); + mExtensionManager->restoreSettings(); +} + +void KABCore::saveSettings() +{ + KABPrefs::instance()->mJumpButtonBarVisible = mActionJumpBar->isChecked(); + KABPrefs::instance()->mExtensionsSplitter = mMiniSplitter->sizes(); + KABPrefs::instance()->mDetailsPageVisible = mActionDetails->isChecked(); + +#ifndef KAB_EMBEDDED + + KABPrefs::instance()->mExtensionsSplitter = mExtensionBarSplitter->sizes(); + KABPrefs::instance()->mDetailsSplitter = mDetailsSplitter->sizes(); +#endif //KAB_EMBEDDED + mExtensionManager->saveSettings(); + mViewManager->saveSettings(); + + KABPrefs::instance()->mCurrentIncSearchField = mIncSearchWidget->currentItem(); + +} + +KABC::AddressBook *KABCore::addressBook() const +{ + return mAddressBook; +} + +KConfig *KABCore::config() +{ +#ifndef KAB_EMBEDDED + return KABPrefs::instance()->config(); +#else //KAB_EMBEDDED + return KABPrefs::instance()->getConfig(); +#endif //KAB_EMBEDDED +} + +KActionCollection *KABCore::actionCollection() const +{ + return mGUIClient->actionCollection(); +} + +KABC::Field *KABCore::currentSearchField() const +{ + if (mIncSearchWidget) + return mIncSearchWidget->currentField(); + else + return 0; +} + +QStringList KABCore::selectedUIDs() const +{ + return mViewManager->selectedUids(); +} + +KABC::Resource *KABCore::requestResource( QWidget *parent ) +{ + QPtrList<KABC::Resource> kabcResources = addressBook()->resources(); + + QPtrList<KRES::Resource> kresResources; + QPtrListIterator<KABC::Resource> resIt( kabcResources ); + KABC::Resource *resource; + while ( ( resource = resIt.current() ) != 0 ) { + ++resIt; + if ( !resource->readOnly() ) { + KRES::Resource *res = static_cast<KRES::Resource*>( resource ); + if ( res ) + kresResources.append( res ); + } + } + + KRES::Resource *res = KRES::SelectDialog::getResource( kresResources, parent ); + return static_cast<KABC::Resource*>( res ); +} + +#ifndef KAB_EMBEDDED +KAboutData *KABCore::createAboutData() +#else //KAB_EMBEDDED +void KABCore::createAboutData() +#endif //KAB_EMBEDDED +{ +#ifndef KAB_EMBEDDED + KAboutData *about = new KAboutData( "kaddressbook", I18N_NOOP( "KAddressBook" ), + "3.1", I18N_NOOP( "The KDE Address Book" ), + KAboutData::License_GPL_V2, + I18N_NOOP( "(c) 1997-2003, The KDE PIM Team" ) ); + about->addAuthor( "Tobias Koenig", I18N_NOOP( "Current maintainer " ), "tokoe@kde.org" ); + about->addAuthor( "Don Sanders", I18N_NOOP( "Original author " ) ); + about->addAuthor( "Cornelius Schumacher", + I18N_NOOP( "Co-maintainer, libkabc port, CSV import/export " ), + "schumacher@kde.org" ); + about->addAuthor( "Mike Pilone", I18N_NOOP( "GUI and framework redesign " ), + "mpilone@slac.com" ); + about->addAuthor( "Greg Stern", I18N_NOOP( "DCOP interface" ) ); + about->addAuthor( "Mark Westcott", I18N_NOOP( "Contact pinning" ) ); + about->addAuthor( "Michel Boyer de la Giroday", I18N_NOOP( "LDAP Lookup\n" ), + "michel@klaralvdalens-datakonsult.se" ); + about->addAuthor( "Steffen Hansen", I18N_NOOP( "LDAP Lookup " ), + "hansen@kde.org" ); + + return about; +#endif //KAB_EMBEDDED + + QString version; +#include <../version> + QMessageBox::about( this, "About KAddressbook/Pi", + "KAddressbook/Platform-independent\n" + "(KA/Pi) " +version + " - " + +#ifdef DESKTOP_VERSION + "Desktop Edition\n" +#else + "PDA-Edition\n" + "for: Zaurus 5500 / 7x0 / 8x0\n" +#endif + + "(c) 2004 Ulf Schenk\n" + "(c) 1997-2003, The KDE PIM Team\n" + "Tobias Koenig Current maintainer tokoe@kde.org\n" + "Don Sanders Original author\n" + "Cornelius Schumacher Co-maintainer schumacher@kde.org\n" + "Mike Pilone GUI and framework redesign mpilone@slac.com\n" + "Greg Stern DCOP interface\n" + "Mark Westcot Contact pinning\n" + "Michel Boyer de la Giroday LDAP Lookup\n" "michel@klaralvdalens-datakonsult.se\n" + "Steffen Hansen LDAP Lookup hansen@kde.org\n" ); +} + +void KABCore::setContactSelected( const QString &uid ) +{ + KABC::Addressee addr = mAddressBook->findByUid( uid ); + if ( !mDetails->isHidden() ) + mDetails->setAddressee( addr ); + + if ( !addr.isEmpty() ) { + emit contactSelected( addr.formattedName() ); + KABC::Picture pic = addr.photo(); + if ( pic.isIntern() ) { +//US emit contactSelected( pic.data() ); +//US instead use: + QPixmap px; + if (pic.data().isNull() != true) + { + px.convertFromImage(pic.data()); + } + + emit contactSelected( px ); + } + } + + + mExtensionManager->setSelectionChanged(); + + // update the actions + bool selected = !uid.isEmpty(); + + if ( mReadWrite ) { + mActionCut->setEnabled( selected ); + mActionPaste->setEnabled( selected ); + } + + mActionCopy->setEnabled( selected ); + mActionDelete->setEnabled( selected ); + mActionEditAddressee->setEnabled( selected ); + mActionMail->setEnabled( selected ); + mActionMailVCard->setEnabled( selected ); + mActionWhoAmI->setEnabled( selected ); + mActionCategories->setEnabled( selected ); +} + +void KABCore::sendMail() +{ +#ifndef KAB_EMBEDDED + sendMail( mViewManager->selectedEmails().join( ", " ) ); +#else //KAB_EMBEDDED + qDebug("KABCore::sendMail() ust be fixed"); +#endif //KAB_EMBEDDED +} + +void KABCore::sendMail( const QString& email ) +{ +#ifndef KAB_EMBEDDED + kapp->invokeMailer( email, "" ); +#else //KAB_EMBEDDED + qDebug("KABCore::sendMail(const QString& email) ust be fixed"); +#endif //KAB_EMBEDDED +} + +void KABCore::mailVCard() +{ +#ifndef KAB_EMBEDDED + QStringList uids = mViewManager->selectedUids(); + if ( !uids.isEmpty() ) + mailVCard( uids ); +#else //KAB_EMBEDDED + qDebug("KABCore::mailVCard() must be fixed"); +#endif //KAB_EMBEDDED +} + +void KABCore::mailVCard( const QStringList& uids ) +{ +#ifndef KAB_EMBEDDED + QStringList urls; + + // Create a temp dir, so that we can put the files in it with proper names + KTempFile tempDir; + if ( tempDir.status() != 0 ) { + kdWarning() << strerror( tempDir.status() ) << endl; + return; + } + + QString dirName = tempDir.name(); + tempDir.unlink(); + QDir().mkdir( dirName, true ); + + for( QStringList::ConstIterator it = uids.begin(); it != uids.end(); ++it ) { + KABC::Addressee a = mAddressBook->findByUid( *it ); + + if ( a.isEmpty() ) + continue; + + QString name = a.givenName() + "_" + a.familyName() + ".vcf"; + + QString fileName = dirName + "/" + name; + + QFile outFile(fileName); + if ( outFile.open(IO_WriteOnly) ) { // file opened successfully + KABC::VCardConverter converter; + QString vcard; + + converter.addresseeToVCard( a, vcard ); + + QTextStream t( &outFile ); // use a text stream + t.setEncoding( QTextStream::UnicodeUTF8 ); + t << vcard; + + outFile.close(); + + urls.append( fileName ); + } + } + + kapp->invokeMailer( QString::null, QString::null, QString::null, + QString::null, // subject + QString::null, // body + QString::null, + urls ); // attachments +#else //KAB_EMBEDDED + qDebug("KABCore::mailVCard( must be fixed"); +#endif //KAB_EMBEDDED + +} + +void KABCore::browse( const QString& url ) +{ +#ifndef KAB_EMBEDDED + kapp->invokeBrowser( url ); +#else //KAB_EMBEDDED + qDebug("KABCore::browse must be fixed"); +#endif //KAB_EMBEDDED +} + +void KABCore::selectAllContacts() +{ + mViewManager->setSelected( QString::null, true ); +} + +void KABCore::deleteContacts() +{ + QStringList uidList = mViewManager->selectedUids(); + deleteContacts( uidList ); +} + +void KABCore::deleteContacts( const QStringList &uids ) +{ + if ( uids.count() > 0 ) { + PwDeleteCommand *command = new PwDeleteCommand( mAddressBook, uids ); + UndoStack::instance()->push( command ); + RedoStack::instance()->clear(); + + // now if we deleted anything, refresh + setContactSelected( QString::null ); + setModified( true ); + } +} + +void KABCore::copyContacts() +{ + KABC::Addressee::List addrList = mViewManager->selectedAddressees(); + + QString clipText = AddresseeUtil::addresseesToClipboard( addrList ); + + kdDebug(5720) << "KABCore::copyContacts: " << clipText << endl; + + QClipboard *cb = QApplication::clipboard(); + cb->setText( clipText ); +} + +void KABCore::cutContacts() +{ + QStringList uidList = mViewManager->selectedUids(); + +//US if ( uidList.size() > 0 ) { + if ( uidList.count() > 0 ) { + PwCutCommand *command = new PwCutCommand( mAddressBook, uidList ); + UndoStack::instance()->push( command ); + RedoStack::instance()->clear(); + + setModified( true ); + } +} + +void KABCore::pasteContacts() +{ + QClipboard *cb = QApplication::clipboard(); + + KABC::Addressee::List list = AddresseeUtil::clipboardToAddressees( cb->text() ); + + pasteContacts( list ); +} + +void KABCore::pasteContacts( KABC::Addressee::List &list ) +{ + KABC::Resource *resource = requestResource( this ); + KABC::Addressee::List::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) + (*it).setResource( resource ); + + PwPasteCommand *command = new PwPasteCommand( this, list ); + UndoStack::instance()->push( command ); + RedoStack::instance()->clear(); + + setModified( true ); +} + +void KABCore::setWhoAmI() +{ + KABC::Addressee::List addrList = mViewManager->selectedAddressees(); + + if ( addrList.count() > 1 ) { + KMessageBox::sorry( this, i18n( "Please select only one contact." ) ); + return; + } + + QString text( i18n( "<qt>Do you really want to use <b>%1</b> as your new personal contact?</qt>" ) ); + if ( KMessageBox::questionYesNo( this, text.arg( addrList[ 0 ].assembledName() ) ) == KMessageBox::Yes ) + static_cast<KABC::StdAddressBook*>( KABC::StdAddressBook::self() )->setWhoAmI( addrList[ 0 ] ); +} + +void KABCore::setCategories() +{ + KPIM::CategorySelectDialog dlg( KABPrefs::instance(), this, "", true ); + if ( !dlg.exec() ) + return; + + bool merge = false; + QString msg = i18n( "Merge with existing categories?" ); + if ( KMessageBox::questionYesNo( this, msg ) == KMessageBox::Yes ) + merge = true; + + QStringList categories = dlg.selectedCategories(); + + QStringList uids = mViewManager->selectedUids(); + QStringList::Iterator it; + for ( it = uids.begin(); it != uids.end(); ++it ) { + KABC::Addressee addr = mAddressBook->findByUid( *it ); + if ( !addr.isEmpty() ) { + if ( !merge ) + addr.setCategories( categories ); + else { + QStringList addrCategories = addr.categories(); + QStringList::Iterator catIt; + for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) { + if ( !addrCategories.contains( *catIt ) ) + addrCategories.append( *catIt ); + } + addr.setCategories( addrCategories ); + } + + mAddressBook->insertAddressee( addr ); + } + } + + if ( uids.count() > 0 ) + setModified( true ); +} + +void KABCore::setSearchFields( const KABC::Field::List &fields ) +{ + mIncSearchWidget->setFields( fields ); +} + +void KABCore::incrementalSearch( const QString& text ) +{ + mViewManager->setSelected( QString::null, false ); + + if ( !text.isEmpty() ) { + KABC::Field *field = mIncSearchWidget->currentField(); + + QString pattern = text.lower(); + +#if KDE_VERSION >= 319 + KABC::AddresseeList list( mAddressBook->allAddressees() ); + if ( field ) { + list.sortByField( field ); + KABC::AddresseeList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + if ( field->value( *it ).lower().startsWith( pattern ) ) { + mViewManager->setSelected( (*it).uid(), true ); + return; + } + } + } else { + KABC::AddresseeList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + KABC::Field::List fieldList = mIncSearchWidget->fields(); + KABC::Field::List::ConstIterator fieldIt; + for ( fieldIt = fieldList.begin(); fieldIt != fieldList.end(); ++fieldIt ) { + if ( (*fieldIt)->value( *it ).lower().startsWith( pattern ) ) { + mViewManager->setSelected( (*it).uid(), true ); + return; + } + } + } + } +#else + KABC::AddressBook::Iterator it; + for ( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { + if ( field ) { + if ( field->value( *it ).lower().startsWith( pattern ) ) { + mViewManager->setSelected( (*it).uid(), true ); + return; + } + } else { + KABC::Field::List fieldList = mIncSearchWidget->fields(); + KABC::Field::List::ConstIterator fieldIt; + for ( fieldIt = fieldList.begin(); fieldIt != fieldList.end(); ++fieldIt ) { + if ( (*fieldIt)->value( *it ).lower().startsWith( pattern ) ) { + mViewManager->setSelected( (*it).uid(), true ); + return; + } + } + } + } +#endif + } +} + +void KABCore::setModified() +{ + setModified( true ); +} + +void KABCore::setModifiedWOrefresh() +{ + // qDebug("KABCore::setModifiedWOrefresh() "); + mModified = true; + mActionSave->setEnabled( mModified ); +#ifdef DESKTOP_VERSION + mDetails->refreshView(); +#endif + +} +void KABCore::setModified( bool modified ) +{ + mModified = modified; + mActionSave->setEnabled( mModified ); + + if ( modified ) + mJumpButtonBar->recreateButtons(); + + mViewManager->refreshView(); + mDetails->refreshView(); + +} + +bool KABCore::modified() const +{ + return mModified; +} + +void KABCore::contactModified( const KABC::Addressee &addr ) +{ + + Command *command = 0; + QString uid; + + // check if it exists already + KABC::Addressee origAddr = mAddressBook->findByUid( addr.uid() ); + if ( origAddr.isEmpty() ) + command = new PwNewCommand( mAddressBook, addr ); + else { + command = new PwEditCommand( mAddressBook, origAddr, addr ); + uid = addr.uid(); + } + + UndoStack::instance()->push( command ); + RedoStack::instance()->clear(); + + setModified( true ); +} + +void KABCore::newContact() +{ + AddresseeEditorDialog *dialog = 0; + + QPtrList<KABC::Resource> kabcResources = mAddressBook->resources(); + + QPtrList<KRES::Resource> kresResources; + QPtrListIterator<KABC::Resource> it( kabcResources ); + KABC::Resource *resource; + while ( ( resource = it.current() ) != 0 ) { + ++it; + if ( !resource->readOnly() ) { + KRES::Resource *res = static_cast<KRES::Resource*>( resource ); + if ( res ) + kresResources.append( res ); + } + } + + KRES::Resource *res = KRES::SelectDialog::getResource( kresResources, this ); + resource = static_cast<KABC::Resource*>( res ); + + if ( resource ) { + KABC::Addressee addr; + addr.setResource( resource ); + dialog = createAddresseeEditorDialog( this ); + dialog->setAddressee( addr ); + + } else + return; + + mEditorDict.insert( dialog->addressee().uid(), dialog ); + + dialog->show(); + +} + +void KABCore::addEmail( QString aStr ) +{ +#ifndef KAB_EMBEDDED + QString fullName, email; + + KABC::Addressee::parseEmailAddress( aStr, fullName, email ); + + // Try to lookup the addressee matching the email address + bool found = false; + QStringList emailList; + KABC::AddressBook::Iterator it; + for ( it = mAddressBook->begin(); !found && (it != mAddressBook->end()); ++it ) { + emailList = (*it).emails(); + if ( emailList.contains( email ) > 0 ) { + found = true; + (*it).setNameFromString( fullName ); + editContact( (*it).uid() ); + } + } + + if ( !found ) { + KABC::Addressee addr; + addr.setNameFromString( fullName ); + addr.insertEmail( email, true ); + + mAddressBook->insertAddressee( addr ); + mViewManager->refreshView( addr.uid() ); + editContact( addr.uid() ); + } +#else //KAB_EMBEDDED + qDebug("KABCore::addEmail finsih method"); +#endif //KAB_EMBEDDED +} + +void KABCore::importVCard( const KURL &url, bool showPreview ) +{ + mXXPortManager->importVCard( url, showPreview ); +} + +void KABCore::importVCard( const QString &vCard, bool showPreview ) +{ + mXXPortManager->importVCard( vCard, showPreview ); +} + +//US added a second method without defaultparameter +void KABCore::editContact2() { + editContact( QString::null ); +} + +void KABCore::editContact( const QString &uid ) +{ + + if ( mExtensionManager->isQuickEditVisible() ) + return; + + // First, locate the contact entry + QString localUID = uid; + if ( localUID.isNull() ) { + QStringList uidList = mViewManager->selectedUids(); + if ( uidList.count() > 0 ) + localUID = *( uidList.at( 0 ) ); + } + + KABC::Addressee addr = mAddressBook->findByUid( localUID ); + if ( !addr.isEmpty() ) { + AddresseeEditorDialog *dialog = mEditorDict.find( addr.uid() ); + if ( !dialog ) { + dialog = createAddresseeEditorDialog( this ); + + mEditorDict.insert( addr.uid(), dialog ); + + dialog->setAddressee( addr ); + } + + dialog->raise(); + dialog->show(); + } +} + +void KABCore::save() +{ + if ( !mModified ) + return; + QString text = i18n( "There was an error while attempting to save\n the " + "address book. Please check that some \nother application is " + "not using it. " ); + statusMessage(i18n("Saving addressbook ... ")); +#ifndef KAB_EMBEDDED + KABC::StdAddressBook *b = dynamic_cast<KABC::StdAddressBook*>( mAddressBook ); + if ( !b || !b->save() ) { + KMessageBox::error( this, text, i18n( "Unable to Save" ) ); + } +#else //KAB_EMBEDDED + KABC::StdAddressBook *b = (KABC::StdAddressBook*)( mAddressBook ); + if ( !b || !b->save() ) { + QMessageBox::critical( this, i18n( "Unable to Save" ), text, i18n("Ok")); + } +#endif //KAB_EMBEDDED + + statusMessage(i18n("Addressbook saved!")); + setModified( false ); +} + +void KABCore::statusMessage(QString mess , int time ) +{ + //topLevelWidget()->setCaption( mess ); + // pending setting timer to revome message +} +void KABCore::undo() +{ + UndoStack::instance()->undo(); + + // Refresh the view + mViewManager->refreshView(); +} + +void KABCore::redo() +{ + RedoStack::instance()->redo(); + + // Refresh the view + mViewManager->refreshView(); +} + +void KABCore::setJumpButtonBarVisible( bool visible ) +{ + if ( visible ) + mJumpButtonBar->show(); + else + mJumpButtonBar->hide(); +} +void KABCore::setDetailsToState() +{ + setDetailsVisible( mActionDetails->isChecked() ); +} + +void KABCore::setDetailsVisible( bool visible ) +{ + if ( visible ) + mDetails->show(); + else + mDetails->hide(); +} + +void KABCore::extensionModified( const KABC::Addressee::List &list ) +{ + + if ( list.count() != 0 ) { + KABC::Addressee::List::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + mAddressBook->insertAddressee( *it ); + if ( list.count() > 1 ) + setModified(); + else + setModifiedWOrefresh(); + } + if ( list.count() == 0 ) + mViewManager->refreshView(); + else + mViewManager->refreshView( list[ 0 ].uid() ); + + + +} + +QString KABCore::getNameByPhone( const QString &phone ) +{ +#ifndef KAB_EMBEDDED + QRegExp r( "[/*/-/ ]" ); + QString localPhone( phone ); + + bool found = false; + QString ownerName = ""; + KABC::AddressBook::Iterator iter; + KABC::PhoneNumber::List::Iterator phoneIter; + KABC::PhoneNumber::List phoneList; + for ( iter = mAddressBook->begin(); !found && ( iter != mAddressBook->end() ); ++iter ) { + phoneList = (*iter).phoneNumbers(); + for ( phoneIter = phoneList.begin(); !found && ( phoneIter != phoneList.end() ); + ++phoneIter) { + // Get rid of separator chars so just the numbers are compared. + if ( (*phoneIter).number().replace( r, "" ) == localPhone.replace( r, "" ) ) { + ownerName = (*iter).formattedName(); + found = true; + } + } + } + + return ownerName; +#else //KAB_EMBEDDED + qDebug("KABCore::getNameByPhone finsih method"); + return ""; +#endif //KAB_EMBEDDED + +} + +void KABCore::openConfigDialog() +{ + KCMultiDialog* ConfigureDialog = new KCMultiDialog( "PIM", this ,"kabconfigdialog", true ); + KCMKabConfig* kabcfg = new KCMKabConfig( ConfigureDialog->getNewVBoxPage(i18n( "Addressbook")) , "KCMKabConfig" ); + ConfigureDialog->addModule(kabcfg ); + connect( ConfigureDialog, SIGNAL( applyClicked() ), + this, SLOT( configurationChanged() ) ); + connect( ConfigureDialog, SIGNAL( okClicked() ), + this, SLOT( configurationChanged() ) ); + saveSettings(); + ConfigureDialog->exec(); + delete ConfigureDialog; +} + +void KABCore::openLDAPDialog() +{ +#ifndef KAB_EMBEDDED + if ( !mLdapSearchDialog ) { + mLdapSearchDialog = new LDAPSearchDialog( mAddressBook, this ); + connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ), mViewManager, + SLOT( refreshView() ) ); + connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ), this, + SLOT( setModified() ) ); + } else + mLdapSearchDialog->restoreSettings(); + + if ( mLdapSearchDialog->isOK() ) + mLdapSearchDialog->exec(); +#else //KAB_EMBEDDED + qDebug("KABCore::openLDAPDialog() finsih method"); +#endif //KAB_EMBEDDED +} + +void KABCore::print() +{ +#ifndef KAB_EMBEDDED + KPrinter printer; + if ( !printer.setup( this ) ) + return; + + KABPrinting::PrintingWizard wizard( &printer, mAddressBook, + mViewManager->selectedUids(), this ); + + wizard.exec(); +#else //KAB_EMBEDDED + qDebug("KABCore::print() finsih method"); +#endif //KAB_EMBEDDED + +} + + +void KABCore::addGUIClient( KXMLGUIClient *client ) +{ + if ( mGUIClient ) + mGUIClient->insertChildClient( client ); + else + KMessageBox::error( this, "no KXMLGUICLient"); +} + + +void KABCore::configurationChanged() +{ + mExtensionManager->reconfigure(); +} + +void KABCore::addressBookChanged() +{ +#ifndef KAB_EMBEDDED + QDictIterator<AddresseeEditorDialog> it( mEditorDict ); + while ( it.current() ) { + if ( it.current()->dirty() ) { + QString text = i18n( "Data has been changed externally. Unsaved " + "changes will be lost." ); + KMessageBox::information( this, text ); + } + it.current()->setAddressee( mAddressBook->findByUid( it.currentKey() ) ); + ++it; + } + + mViewManager->refreshView(); +#else //KAB_EMBEDDED + qDebug("KABCore::addressBookChanged() finsih method"); +#endif //KAB_EMBEDDED +} + +AddresseeEditorDialog *KABCore::createAddresseeEditorDialog( QWidget *parent, + const char *name ) +{ + AddresseeEditorDialog *dialog = new AddresseeEditorDialog( this, parent, + name ? name : "editorDialog" ); + +//US + dialog->setMaximumSize( 640, 480 ); + dialog->showMaximized(); + + connect( dialog, SIGNAL( contactModified( const KABC::Addressee& ) ), + SLOT( contactModified( const KABC::Addressee& ) ) ); + connect( dialog, SIGNAL( editorDestroyed( const QString& ) ), + SLOT( slotEditorDestroyed( const QString& ) ) ); + + return dialog; +} + +void KABCore::slotEditorDestroyed( const QString &uid ) +{ + mEditorDict.remove( uid ); +} + +void KABCore::initGUI() +{ +#ifndef KAB_EMBEDDED + QHBoxLayout *topLayout = new QHBoxLayout( this ); + topLayout->setSpacing( KDialogBase::spacingHint() ); + + mExtensionBarSplitter = new QSplitter( this ); + mExtensionBarSplitter->setOrientation( Qt::Vertical ); + + mDetailsSplitter = new QSplitter( mExtensionBarSplitter ); + + QVBox *viewSpace = new QVBox( mDetailsSplitter ); + mIncSearchWidget = new IncSearchWidget( viewSpace ); + connect( mIncSearchWidget, SIGNAL( doSearch( const QString& ) ), + SLOT( incrementalSearch( const QString& ) ) ); + + mViewManager = new ViewManager( this, viewSpace ); + viewSpace->setStretchFactor( mViewManager, 1 ); + + mDetails = new ViewContainer( mDetailsSplitter ); + + mJumpButtonBar = new JumpButtonBar( this, this ); + + mExtensionManager = new ExtensionManager( this, mExtensionBarSplitter ); + + topLayout->addWidget( mExtensionBarSplitter ); + topLayout->setStretchFactor( mExtensionBarSplitter, 100 ); + topLayout->addWidget( mJumpButtonBar ); + topLayout->setStretchFactor( mJumpButtonBar, 1 ); + + mXXPortManager = new XXPortManager( this, this ); + +#else //KAB_EMBEDDED + //US initialize viewMenu before settingup viewmanager. + // Viewmanager needs this menu to plugin submenues. + viewMenu = new QPopupMenu( this ); + settingsMenu = new QPopupMenu( this ); + //filterMenu = new QPopupMenu( this ); + ImportMenu = new QPopupMenu( this ); + ExportMenu = new QPopupMenu( this ); + + +//US since we have no splitter for the embedded system, setup +// a layout with two frames. One left and one right. + + QBoxLayout *topLayout; + + // = new QHBoxLayout( this ); +// QBoxLayout *topLayout = (QBoxLayout*)layout(); + +// QWidget *mainBox = new QWidget( this ); +// QBoxLayout * mainBoxLayout = new QHBoxLayout(mainBox); + + + if ( QApplication::desktop()->width() > 480 ) { + topLayout = new QHBoxLayout( this ); + mMiniSplitter = new KDGanttMinimizeSplitter( Qt::Horizontal, this); + mMiniSplitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Right ); + } else { + + topLayout = new QVBoxLayout( this ); + mMiniSplitter = new KDGanttMinimizeSplitter( Qt::Vertical, this); + mMiniSplitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Down ); + } + + topLayout->addWidget(mMiniSplitter ); + mViewManager = new ViewManager( this, mMiniSplitter ); + mDetails = new ViewContainer( mMiniSplitter ); + + + mExtensionManager = new ExtensionManager( this, mMiniSplitter ); + + //eh->hide(); + // topLayout->addWidget(mExtensionManager ); + + +/*US +#ifndef KAB_NOSPLITTER + QHBoxLayout *topLayout = new QHBoxLayout( this ); +//US topLayout->setSpacing( KDialogBase::spacingHint() ); + topLayout->setSpacing( 10 ); + + mDetailsSplitter = new QSplitter( this ); + + QVBox *viewSpace = new QVBox( mDetailsSplitter ); + + mViewManager = new ViewManager( this, viewSpace ); + viewSpace->setStretchFactor( mViewManager, 1 ); + + mDetails = new ViewContainer( mDetailsSplitter ); + + topLayout->addWidget( mDetailsSplitter ); + topLayout->setStretchFactor( mDetailsSplitter, 100 ); +#else //KAB_NOSPLITTER + QHBoxLayout *topLayout = new QHBoxLayout( this ); +//US topLayout->setSpacing( KDialogBase::spacingHint() ); + topLayout->setSpacing( 10 ); + +// mDetailsSplitter = new QSplitter( this ); + + QVBox *viewSpace = new QVBox( this ); + + mViewManager = new ViewManager( this, viewSpace ); + viewSpace->setStretchFactor( mViewManager, 1 ); + + mDetails = new ViewContainer( this ); + + topLayout->addWidget( viewSpace ); +// topLayout->setStretchFactor( mDetailsSplitter, 100 ); + topLayout->addWidget( mDetails ); +#endif //KAB_NOSPLITTER +*/ + + +#endif //KAB_EMBEDDED + initActions(); + +#ifdef KAB_EMBEDDED + addActionsManually(); + //US make sure the export and import menues are initialized before creating the xxPortManager. + mXXPortManager = new XXPortManager( this, this ); + + // LR mIncSearchWidget = new IncSearchWidget( mMainWindow->getIconToolBar() ); + //mMainWindow->toolBar()->insertWidget(-1, 4, mIncSearchWidget); + // mActionQuit->plug ( mMainWindow->toolBar()); + //mIncSearchWidget = new IncSearchWidget( mMainWindow->toolBar() ); + //mMainWindow->toolBar()->insertWidget(-1, 0, mIncSearchWidget); + // mIncSearchWidget->hide(); + connect( mIncSearchWidget, SIGNAL( doSearch( const QString& ) ), + SLOT( incrementalSearch( const QString& ) ) ); + + + mJumpButtonBar = new JumpButtonBar( this, this ); + + topLayout->addWidget( mJumpButtonBar ); +//US topLayout->setStretchFactor( mJumpButtonBar, 10 ); + +// mMainWindow->getIconToolBar()->raise(); + +#endif //KAB_EMBEDDED + +} +void KABCore::initActions() +{ +//US qDebug("KABCore::initActions(): mIsPart %i", mIsPart); + +#ifndef KAB_EMBEDDED + connect( QApplication::clipboard(), SIGNAL( dataChanged() ), + SLOT( clipboardDataChanged() ) ); +#endif //KAB_EMBEDDED + + // file menu + if ( mIsPart ) { + mActionMail = new KAction( i18n( "&Mail" ), "mail_generic", 0, this, + SLOT( sendMail() ), actionCollection(), + "kaddressbook_mail" ); + mActionPrint = new KAction( i18n( "&Print" ), "fileprint", CTRL + Key_P, this, + SLOT( print() ), actionCollection(), "kaddressbook_print" ); + + } else { + mActionMail = KStdAction::mail( this, SLOT( sendMail() ), actionCollection() ); + mActionPrint = KStdAction::print( this, SLOT( print() ), actionCollection() ); + } + + mActionSave = new KAction( i18n( "&Save" ), "filesave", CTRL+Key_S, this, + SLOT( save() ), actionCollection(), "file_sync" ); + + mActionNewContact = new KAction( i18n( "&New Contact..." ), "filenew", CTRL+Key_N, this, + SLOT( newContact() ), actionCollection(), "file_new_contact" ); + + mActionMailVCard = new KAction(i18n("Mail &vCard..."), "mail_post_to", 0, + this, SLOT( mailVCard() ), + actionCollection(), "file_mail_vcard"); + + mActionEditAddressee = new KAction( i18n( "&Edit Contact..." ), "edit", 0, + this, SLOT( editContact2() ), + actionCollection(), "file_properties" ); + +#ifdef KAB_EMBEDDED + // mActionQuit = KStdAction::quit( mMainWindow, SLOT( exit() ), actionCollection() ); + mActionQuit = new KAction( i18n( "&Exit" ), "exit", 0, + mMainWindow, SLOT( exit() ), + actionCollection(), "quit" ); +#endif //KAB_EMBEDDED + + // edit menu + if ( mIsPart ) { + mActionCopy = new KAction( i18n( "&Copy" ), "editcopy", CTRL + Key_C, this, + SLOT( copyContacts() ), actionCollection(), + "kaddressbook_copy" ); + mActionCut = new KAction( i18n( "Cu&t" ), "editcut", CTRL + Key_X, this, + SLOT( cutContacts() ), actionCollection(), + "kaddressbook_cut" ); + mActionPaste = new KAction( i18n( "&Paste" ), "editpaste", CTRL + Key_V, this, + SLOT( pasteContacts() ), actionCollection(), + "kaddressbook_paste" ); + mActionSelectAll = new KAction( i18n( "Select &All" ), CTRL + Key_A, this, + SLOT( selectAllContacts() ), actionCollection(), + "kaddressbook_select_all" ); + mActionUndo = new KAction( i18n( "&Undo" ), "undo", CTRL + Key_Z, this, + SLOT( undo() ), actionCollection(), + "kaddressbook_undo" ); + mActionRedo = new KAction( i18n( "Re&do" ), "redo", CTRL + SHIFT + Key_Z, + this, SLOT( redo() ), actionCollection(), + "kaddressbook_redo" ); + } else { + mActionCopy = KStdAction::copy( this, SLOT( copyContacts() ), actionCollection() ); + mActionCut = KStdAction::cut( this, SLOT( cutContacts() ), actionCollection() ); + mActionPaste = KStdAction::paste( this, SLOT( pasteContacts() ), actionCollection() ); + mActionSelectAll = KStdAction::selectAll( this, SLOT( selectAllContacts() ), actionCollection() ); + mActionUndo = KStdAction::undo( this, SLOT( undo() ), actionCollection() ); + mActionRedo = KStdAction::redo( this, SLOT( redo() ), actionCollection() ); + } + + mActionDelete = new KAction( i18n( "&Delete Contact" ), "editdelete", + Key_Delete, this, SLOT( deleteContacts() ), + actionCollection(), "edit_delete" ); + + mActionUndo->setEnabled( false ); + mActionRedo->setEnabled( false ); + + // settings menu +#ifdef KAB_EMBEDDED +//US special menuentry to configure the addressbook resources. On KDE +// you do that through the control center !!! + mActionConfigResources = new KAction( i18n( "Configure &Resources..." ), "configure_resources", 0, this, + SLOT( configureResources() ), actionCollection(), + "kaddressbook_configure_resources" ); +#endif //KAB_EMBEDDED + + if ( mIsPart ) { + mActionConfigKAddressbook = new KAction( i18n( "&Configure KAddressBook..." ), "configure", 0, this, + SLOT( openConfigDialog() ), actionCollection(), + "kaddressbook_configure" ); + + mActionConfigShortcuts = new KAction( i18n( "Configure S&hortcuts..." ), "configure_shortcuts", 0, + this, SLOT( configureKeyBindings() ), actionCollection(), + "kaddressbook_configure_shortcuts" ); +#ifdef KAB_EMBEDDED + mActionConfigureToolbars = KStdAction::configureToolbars( this, SLOT( mMainWindow->configureToolbars() ), actionCollection() ); +#endif //KAB_EMBEDDED + + } else { + mActionConfigKAddressbook = KStdAction::preferences( this, SLOT( openConfigDialog() ), actionCollection() ); + + mActionKeyBindings = KStdAction::keyBindings( this, SLOT( configureKeyBindings() ), actionCollection() ); + } + + mActionJumpBar = new KToggleAction( i18n( "Show Jump Bar" ), 0, 0, + actionCollection(), "options_show_jump_bar" ); + connect( mActionJumpBar, SIGNAL( toggled( bool ) ), SLOT( setJumpButtonBarVisible( bool ) ) ); + + mActionDetails = new KToggleAction( i18n( "Show Details" ), 0, 0, + actionCollection(), "options_show_details" ); + connect( mActionDetails, SIGNAL( toggled( bool ) ), SLOT( setDetailsVisible( bool ) ) ); + + // misc + // only enable LDAP lookup if we can handle the protocol +#ifndef KAB_EMBEDDED + if ( KProtocolInfo::isKnownProtocol( KURL( "ldap://localhost" ) ) ) { + new KAction( i18n( "&Lookup Addresses in Directory" ), "find", 0, + this, SLOT( openLDAPDialog() ), actionCollection(), + "ldap_lookup" ); + } +#else //KAB_EMBEDDED + //qDebug("KABCore::initActions() LDAP has to be implemented"); +#endif //KAB_EMBEDDED + + + mActionWhoAmI = new KAction( i18n( "Set Who Am I" ), "personal", 0, this, + SLOT( setWhoAmI() ), actionCollection(), + "set_personal" ); + + mActionCategories = new KAction( i18n( "Set Categories" ), 0, this, + SLOT( setCategories() ), actionCollection(), + "edit_set_categories" ); + +#ifdef KAB_EMBEDDED + + mActionAboutKAddressbook = new KAction( i18n( "&About KAddressBook" ), "kaddressbook2", 0, + this, SLOT( createAboutData() ), actionCollection(), + "kaddressbook_about_data" ); +#endif //KAB_EMBEDDED + + clipboardDataChanged(); + connect( UndoStack::instance(), SIGNAL( changed() ), SLOT( updateActionMenu() ) ); + connect( RedoStack::instance(), SIGNAL( changed() ), SLOT( updateActionMenu() ) ); +} + +//US we need this function, to plug all actions into the correct menues. +// KDE uses a XML format to plug the actions, but we work her without this overhead. +void KABCore::addActionsManually() +{ +//US qDebug("KABCore::initActions(): mIsPart %i", mIsPart); + +#ifdef KAB_EMBEDDED + QPopupMenu *fileMenu = new QPopupMenu( this ); + QPopupMenu *editMenu = new QPopupMenu( this ); + QPopupMenu *helpMenu = new QPopupMenu( this ); + + KToolBar* tb = mMainWindow->toolBar(); + +#ifdef DESKTOP_VERSION + QMenuBar* mb = mMainWindow->menuBar(); + + //US setup menubar. + //Disable the following block if you do not want to have a menubar. + mb->insertItem( "&File", fileMenu ); + mb->insertItem( "&Edit", editMenu ); + mb->insertItem( "&View", viewMenu ); + mb->insertItem( "&Settings", settingsMenu ); + mb->insertItem( "&Help", helpMenu ); + mIncSearchWidget = new IncSearchWidget( tb ); + // tb->insertWidget(-1, 0, mIncSearchWidget); + +#else + //US setup toolbar + QMenuBar *menuBarTB = new QMenuBar( tb ); + QPopupMenu *popupBarTB = new QPopupMenu( this ); + menuBarTB->insertItem( "ME", popupBarTB); + tb->insertWidget(-1, 0, menuBarTB); + mIncSearchWidget = new IncSearchWidget( tb ); + + tb->enableMoving(false); + popupBarTB->insertItem( "&File", fileMenu ); + popupBarTB->insertItem( "&Edit", editMenu ); + popupBarTB->insertItem( "&View", viewMenu ); + popupBarTB->insertItem( "&Settings", settingsMenu ); + mViewManager->getFilterAction()->plug ( popupBarTB); + popupBarTB->insertItem( "&Help", helpMenu ); + if (QApplication::desktop()->width() > 320 ) { + // mViewManager->getFilterAction()->plug ( tb); + } +#endif + // mActionQuit->plug ( mMainWindow->toolBar()); + + + + //US Now connect the actions with the menue entries. + mActionPrint->plug( fileMenu ); + mActionMail->plug( fileMenu ); + fileMenu->insertSeparator(); + + mActionNewContact->plug( fileMenu ); + mActionNewContact->plug( tb ); + + mActionEditAddressee->plug( fileMenu ); + fileMenu->insertSeparator(); + mActionSave->plug( fileMenu ); + fileMenu->insertItem( "&Import", ImportMenu ); + fileMenu->insertItem( "&Emport", ExportMenu ); + fileMenu->insertSeparator(); + mActionMailVCard->plug( fileMenu ); + fileMenu->insertSeparator(); + mActionQuit->plug( fileMenu ); + + + // edit menu + mActionUndo->plug( editMenu ); + mActionRedo->plug( editMenu ); + editMenu->insertSeparator(); + mActionCut->plug( editMenu ); + mActionCopy->plug( editMenu ); + mActionPaste->plug( editMenu ); + mActionDelete->plug( editMenu ); + editMenu->insertSeparator(); + mActionSelectAll->plug( editMenu ); + + + // settings menu +//US special menuentry to configure the addressbook resources. On KDE +// you do that through the control center !!! + mActionConfigResources->plug( settingsMenu ); + settingsMenu->insertSeparator(); + + mActionConfigKAddressbook->plug( settingsMenu ); + + if ( mIsPart ) { + mActionConfigShortcuts->plug( settingsMenu ); + mActionConfigureToolbars->plug( settingsMenu ); + + } else { + mActionKeyBindings->plug( settingsMenu ); + } + + settingsMenu->insertSeparator(); + + mActionJumpBar->plug( settingsMenu ); + mActionDetails->plug( settingsMenu ); + settingsMenu->insertSeparator(); + + mActionWhoAmI->plug( settingsMenu ); + mActionCategories->plug( settingsMenu ); + + mActionAboutKAddressbook->plug( helpMenu ); + + if (QApplication::desktop()->width() > 320 ) { + + mActionEditAddressee->plug( tb ); + mActionSave->plug( tb ); + mViewManager->getFilterAction()->plug ( tb); + if (QApplication::desktop()->width() > 480 ) + mActionDelete->plug( tb ); + } + mActionQuit->plug ( tb ); + // tb->insertWidget(-1, 0, mIncSearchWidget, 6); + + //US link the searchwidget first to this. + // The real linkage to the toolbar happens later. +//US mIncSearchWidget->reparent(tb, 0, QPoint(50,0), TRUE); +//US tb->insertItem( mIncSearchWidget ); +/*US + mIncSearchWidget = new IncSearchWidget( tb ); + connect( mIncSearchWidget, SIGNAL( doSearch( const QString& ) ), + SLOT( incrementalSearch( const QString& ) ) ); + + mJumpButtonBar = new JumpButtonBar( this, this ); + +//US topLayout->addWidget( mJumpButtonBar ); + this->layout()->add( mJumpButtonBar ); +*/ + +#endif //KAB_EMBEDDED +} + + + +void KABCore::clipboardDataChanged() +{ + + if ( mReadWrite ) + mActionPaste->setEnabled( !QApplication::clipboard()->text().isEmpty() ); + +} + +void KABCore::updateActionMenu() +{ + UndoStack *undo = UndoStack::instance(); + RedoStack *redo = RedoStack::instance(); + + if ( undo->isEmpty() ) + mActionUndo->setText( i18n( "Undo" ) ); + else + mActionUndo->setText( i18n( "Undo %1" ).arg( undo->top()->name() ) ); + + mActionUndo->setEnabled( !undo->isEmpty() ); + + if ( !redo->top() ) + mActionRedo->setText( i18n( "Redo" ) ); + else + mActionRedo->setText( i18n( "Redo %1" ).arg( redo->top()->name() ) ); + + mActionRedo->setEnabled( !redo->isEmpty() ); +} + +void KABCore::configureKeyBindings() +{ +#ifndef KAB_EMBEDDED + KKeyDialog::configure( actionCollection(), true ); +#else //KAB_EMBEDDED + qDebug("KABCore::configureKeyBindings() not implemented"); +#endif //KAB_EMBEDDED +} + +#ifdef KAB_EMBEDDED +void KABCore::configureResources() +{ + KRES::KCMKResources dlg( this, "" , 0 ); + + if ( !dlg.exec() ) + return; +} +#endif //KAB_EMBEDDED + + + +#ifndef KAB_EMBEDDED +#include "kabcore.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/kabcore.h b/kaddressbook/kabcore.h new file mode 100644 index 0000000..edf98c2 --- a/dev/null +++ b/kaddressbook/kabcore.h @@ -0,0 +1,421 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KABCORE_H +#define KABCORE_H + +#include <kabc/field.h> + +#ifndef KAB_EMBEDDED +#endif //KAB_EMBEDDED +#include <qdict.h> + +#include <qwidget.h> +#include <qpopupmenu.h> + +namespace KABC { +class AddressBook; +} + +#ifndef KAB_EMBEDDED +class KAboutData; +class KConfig; + +class KAddressBookService; +class LDAPSearchDialog; +#else //KAB_EMBEDDED +class KAddressBookMain; +//US class QAction; +#endif //KAB_EMBEDDED +class KCMultiDialog; +class KXMLGUIClient; +class ExtensionManager; +class XXPortManager; +class JumpButtonBar; +class IncSearchWidget; +class KDGanttMinimizeSplitter; +class KAction; +class KActionCollection; +class KToggleAction; + +class QAction; +class QMenuBar; +class QSplitter; +class ViewContainer; +class ViewManager; +class AddresseeEditorDialog; + +class KABCore : public QWidget +{ + Q_OBJECT + + public: + KABCore( KAddressBookMain *client, bool readWrite, QWidget *parent, const char *name = 0 ); + + + ~KABCore(); + + +#ifdef KAB_EMBEDDED + //US added functionality + QPopupMenu* getViewMenu() {return viewMenu;} + QPopupMenu* getFilterMenu() {return filterMenu;} + QPopupMenu* getSettingsMenu() {return settingsMenu;} + void addActionsManually(); +#endif //KAB_EMBEDDED + /** + Restores the global settings. + */ + void restoreSettings(); + + /** + Saves the global settings. + */ + void saveSettings(); + + /** + Returns a pointer to the StdAddressBook of the application. + */ + KABC::AddressBook *addressBook() const; + + /** + Returns a pointer to the KConfig object of the application. + */ + static KConfig *config(); + + /** + Returns a pointer to the global KActionCollection object. So + other classes can register their actions easily. + */ + KActionCollection *actionCollection() const; + + /** + Returns the current search field of the Incremental Search Widget. + */ + KABC::Field *currentSearchField() const; + + /** + Returns the uid list of the currently selected contacts. + */ + QStringList selectedUIDs() const; + + /** + Displays the ResourceSelectDialog and returns the selected + resource or a null pointer if no resource was selected by + the user. + */ + KABC::Resource *requestResource( QWidget *parent ); + +#ifndef KAB_EMBEDDED + static KAboutData *createAboutData(); +#endif //KAB_EMBEDDED + +#ifdef KAB_EMBEDDED + inline QPopupMenu* getImportMenu() { return ImportMenu;} + inline QPopupMenu* getExportMenu() { return ExportMenu;} +#endif //KAB_EMBEDDED + + public slots: +#ifdef KAB_EMBEDDED + void createAboutData(); +#endif //KAB_EMBEDDED + + void statusMessage(QString, int time = 0 ); + /** + Is called whenever a contact is selected in the view. + */ + void setContactSelected( const QString &uid ); + + /** + Opens the preferred mail composer with all selected contacts as + arguments. + */ + void sendMail(); + + /** + Opens the preferred mail composer with the given contacts as + arguments. + */ + void sendMail( const QString& email ); + + + void mailVCard(); + void mailVCard(const QStringList& uids); + + /** + Starts the preferred web browser with the given URL as argument. + */ + void browse( const QString& url ); + + /** + Select all contacts in the view. + */ + void selectAllContacts(); + + /** + Deletes all selected contacts from the address book. + */ + void deleteContacts(); + + /** + Deletes given contacts from the address book. + + @param uids The uids of the contacts, which shall be deleted. + */ + void deleteContacts( const QStringList &uids ); + + /** + Copys the selected contacts into clipboard for later pasting. + */ + void copyContacts(); + + /** + Cuts the selected contacts and stores them for later pasting. + */ + void cutContacts(); + + /** + Paste contacts from clipboard into the address book. + */ + void pasteContacts(); + + /** + Paste given contacts into the address book. + + @param list The list of addressee, which shall be pasted. + */ + void pasteContacts( KABC::Addressee::List &list ); + + /** + Sets the whoAmI contact, that is used by many other programs to + get personal information about the current user. + */ + void setWhoAmI(); + + /** + Displays the category dialog and applies the result to all + selected contacts. + */ + void setCategories(); + + /** + Sets the field list of the Incremental Search Widget. + */ + void setSearchFields( const KABC::Field::List &fields ); + + /** + Search with the current search field for a contact, that matches + the given text, and selects it in the view. + */ + void incrementalSearch( const QString& text ); + + /** + Marks the address book as modified. + */ + void setModified(); + /** + Marks the address book as modified without refreshing the view. + */ + void setModifiedWOrefresh(); + + /** + Marks the address book as modified concerning the argument. + */ + void setModified( bool modified ); + + /** + Returns whether the address book is modified. + */ + bool modified() const; + + /** + Called whenever an contact is modified in the contact editor + dialog or the quick edit. + */ + void contactModified( const KABC::Addressee &addr ); + + /** + DCOP METHODS. + */ + void addEmail( QString addr ); + void importVCard( const KURL& url, bool showPreview ); + void importVCard( const QString& vCard, bool showPreview ); + void newContact(); + QString getNameByPhone( const QString& phone ); + /** + END DCOP METHODS + */ + + /** + Saves the contents of the AddressBook back to disk. + */ + void save(); + + /** + Undos the last command using the undo stack. + */ + void undo(); + + /** + Redos the last command that was undone, using the redo stack. + */ + void redo(); + + /** + Shows the edit dialog for the given uid. If the uid is QString::null, + the method will try to find a selected addressee in the view. + */ + void editContact( const QString &uid /*US = QString::null*/ ); +//US added a second method without defaultparameter + void editContact2(); + + /** + Launches the configuration dialog. + */ + void openConfigDialog(); + + /** + Launches the ldap search dialog. + */ + void openLDAPDialog(); + + /** + Creates a KAddressBookPrinter, which will display the print + dialog and do the printing. + */ + void print(); + + /** + Registers a new GUI client, so plugins can register its actions. + */ + void addGUIClient( KXMLGUIClient *client ); + + signals: + void contactSelected( const QString &name ); + void contactSelected( const QPixmap &pixmap ); + public slots: + void setDetailsVisible( bool visible ); + void setDetailsToState(); + private slots: + void setJumpButtonBarVisible( bool visible ); + + void extensionModified( const KABC::Addressee::List &list ); + void clipboardDataChanged(); + void updateActionMenu(); + void configureKeyBindings(); +#ifdef KAB_EMBEDDED + void configureResources(); +#endif //KAB_EMBEDDED + + void slotEditorDestroyed( const QString &uid ); + void configurationChanged(); + void addressBookChanged(); + + private: + void initGUI(); + void initActions(); + + AddresseeEditorDialog *createAddresseeEditorDialog( QWidget *parent, + const char *name = 0 ); + + KXMLGUIClient *mGUIClient; + + KABC::AddressBook *mAddressBook; + + ViewManager *mViewManager; + // QSplitter *mDetailsSplitter; + //QSplitter *mExtensionBarSplitter; + ViewContainer *mDetails; + KDGanttMinimizeSplitter* mMiniSplitter; + XXPortManager *mXXPortManager; + JumpButtonBar *mJumpButtonBar; + IncSearchWidget *mIncSearchWidget; + ExtensionManager *mExtensionManager; + + KCMultiDialog *mConfigureDialog; + +#ifndef KAB_EMBEDDED + + KCMultiDialog *mConfigureDialog; + LDAPSearchDialog *mLdapSearchDialog; +#endif //KAB_EMBEDDED + QDict<AddresseeEditorDialog> mEditorDict; + + bool mReadWrite; + bool mModified; + bool mIsPart; + + //US file menu + KAction *mActionMail; + KAction* mActionPrint; + KAction* mActionNewContact; + KAction *mActionSave; + KAction *mActionEditAddressee; + KAction *mActionMailVCard; + KAction *mActionQuit; + + //US edit menu + KAction *mActionCopy; + KAction *mActionCut; + KAction *mActionPaste; + KAction *mActionSelectAll; + KAction *mActionUndo; + KAction *mActionRedo; + KAction *mActionDelete; + + //US settings menu + KAction *mActionConfigResources; + KAction *mActionConfigKAddressbook; + KAction *mActionConfigShortcuts; + KAction *mActionConfigureToolbars; + KAction *mActionKeyBindings; + KToggleAction *mActionJumpBar; + KToggleAction *mActionDetails; + KAction *mActionWhoAmI; + KAction *mActionCategories; + KAction *mActionAboutKAddressbook; + + KAction *mActionDeleteView; + + QPopupMenu *viewMenu; + QPopupMenu *filterMenu; + QPopupMenu *settingsMenu; + +//US QAction *mActionSave; + QPopupMenu *ImportMenu; + QPopupMenu *ExportMenu; + +#ifndef KAB_EMBEDDED + KAddressBookService *mAddressBookService; +#endif //KAB_EMBEDDED + + class KABCorePrivate; + KABCorePrivate *d; + +#ifdef KAB_EMBEDDED + KAddressBookMain *mMainWindow; // should be the same like mGUIClient +#endif //KAB_EMBEDDED + +}; + +#endif diff --git a/kaddressbook/kabprefs.cpp b/kaddressbook/kabprefs.cpp new file mode 100644 index 0000000..5b3b1ab --- a/dev/null +++ b/kaddressbook/kabprefs.cpp @@ -0,0 +1,127 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +//US#ifdef KAB_EMBEDDED +//#include <qstring.h> +//#endif //KAB_EMBEDDED + + +#include <kconfig.h> +#include <klocale.h> +#include <kstaticdeleter.h> +//US#include <kdebug.h> // defines kdDebug() + +#include "kabprefs.h" + +KABPrefs *KABPrefs::sInstance = 0; +static KStaticDeleter<KABPrefs> staticDeleter; + +KABPrefs::KABPrefs() + : KPimPrefs("kaddressbookrc") +{ + KPrefs::setCurrentGroup( "Views" ); + addItemBool( "HonorSingleClick", &mHonorSingleClick, false ); + + KPrefs::setCurrentGroup( "General" ); + addItemBool( "AutomaticNameParsing", &mAutomaticNameParsing, true ); + addItemInt( "CurrentIncSearchField", &mCurrentIncSearchField, 0 ); + +#ifdef KAB_EMBEDDED + addItemBool("AskForQuit",&mAskForQuit,false); + addItemBool("ToolBarHor",&mToolBarHor, true ); + addItemBool("ToolBarUp",&mToolBarUp, false ); +#endif //KAB_EMBEDDED + + KPrefs::setCurrentGroup( "MainWindow" ); + addItemBool( "JumpButtonBarVisible", &mJumpButtonBarVisible, false ); + addItemBool( "DetailsPageVisible", &mDetailsPageVisible, true ); + addItemIntList( "ExtensionsSplitter", &mExtensionsSplitter ); + addItemIntList( "DetailsSplitter", &mDetailsSplitter ); + + KPrefs::setCurrentGroup( "Extensions_General" ); + QStringList defaultExtensions; + defaultExtensions << "merge"; + defaultExtensions << "distribution_list_editor"; + addItemInt( "CurrentExtension", &mCurrentExtension, 0 ); + addItemStringList( "ActiveExtensions", &mActiveExtensions, defaultExtensions ); + + KPrefs::setCurrentGroup( "Views" ); + QString defaultView = i18n( "Default Table View" ); + addItemString( "CurrentView", &mCurrentView, defaultView ); + addItemStringList( "ViewNames", &mViewNames, defaultView ); + + KPrefs::setCurrentGroup( "Filters" ); + addItemInt( "CurrentFilter", &mCurrentFilter, 0 ); + +} + +KABPrefs::~KABPrefs() +{ +} + +KABPrefs *KABPrefs::instance() +{ + if ( !sInstance ) { +#ifdef KAB_EMBEDDED + sInstance = staticDeleter.setObject( new KABPrefs() ); +#else //KAB_EMBEDDED + //US the following line has changed ???. Why + staticDeleter.setObject( sInstance, new KABPrefs() ); +#endif //KAB_EMBEDDED + sInstance->readConfig(); + } + + return sInstance; +} + +void KABPrefs::setCategoryDefaults() +{ + mCustomCategories.clear(); + + mCustomCategories << i18n( "Business" ) << i18n( "Family" ) << i18n( "School" ) + << i18n( "Customer" ) << i18n( "Friend" ); +} + + // US introduce a nonconst way to return the config object. +KConfig* KABPrefs::getConfig() +{ + return config(); +} + + +/*US +void KABPrefs::usrSetDefaults() +{ + KPimPrefs::usrSetDefaults(); +} + +void KABPrefs::usrReadConfig() +{ + KPimPrefs::usrReadConfig(); +} + +void KABPrefs::usrWriteConfig() +{ + KPimPrefs::usrWriteConfig(); +} +*/ diff --git a/kaddressbook/kabprefs.h b/kaddressbook/kabprefs.h new file mode 100644 index 0000000..370fc5b --- a/dev/null +++ b/kaddressbook/kabprefs.h @@ -0,0 +1,88 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KABPREFS_H +#define KABPREFS_H + +#include <qstringlist.h> + +#include <libkdepim/kpimprefs.h> + +class KConfig; + +class KABPrefs : public KPimPrefs +{ + public: + virtual ~KABPrefs(); + + static KABPrefs *instance(); + + // General + bool mHonorSingleClick; + bool mAutomaticNameParsing; + int mCurrentIncSearchField; + +#ifdef KAB_EMBEDDED + // US introduce a nonconst way to return the config object. + KConfig* getConfig(); + + bool mToolBarHor; + bool mToolBarUp; + bool mAskForQuit; + /** Set preferences to default values */ +// void usrSetDefaults(); + + /** Read preferences from config file */ +// void usrReadConfig(); + + /** Write preferences to config file */ +// void usrWriteConfig(); +#endif //KAB_EMBEDDED + + + // GUI + bool mJumpButtonBarVisible; + bool mDetailsPageVisible; + QValueList<int> mExtensionsSplitter; + QValueList<int> mDetailsSplitter; + + // Extensions stuff + int mCurrentExtension; + QStringList mActiveExtensions; + + // Views stuff + QString mCurrentView; + QStringList mViewNames; + + // Filter + int mCurrentFilter; + + void setCategoryDefaults(); + + private: + KABPrefs(); + + static KABPrefs *sInstance; +}; + +#endif diff --git a/kaddressbook/kaddressbook.desktop b/kaddressbook/kaddressbook.desktop new file mode 100644 index 0000000..9cee2aa --- a/dev/null +++ b/kaddressbook/kaddressbook.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment = KAddressbook +Display = 640x480/144dpi,480x640/144dpi +Exec = kapi +Icon = kdepim/kaddressbook/kaddressbook +Name = KA/Pi +Type = Application +CanFastload = 1 diff --git a/kaddressbook/kaddressbook.pro b/kaddressbook/kaddressbook.pro new file mode 100644 index 0000000..761c3e7 --- a/dev/null +++ b/kaddressbook/kaddressbook.pro @@ -0,0 +1,166 @@ +TEMPLATE = app +CONFIG = qt warn_on +TARGET = kapi +DESTDIR= ../bin + +include( ../variables.pri ) + + +INCLUDEPATH += . ./details ./features ./kcmconfigs ./xxport ../microkde ../microkde/kdecore ../microkde/kutils ../microkde/kio/kfile ../microkde/kdeui ../kabc ../ interfaces +DEFINES += KAB_EMBEDDED KAB_NOSPLITTER DESKTOP_VERSION + +unix : { +LIBS += ../bin/libmicrokdepim.so +LIBS += ../bin/libmicrokde.so +LIBS += ../bin/libmicrokabc.so +LIBS += ../bin/libmicrokcal.so +LIBS += -lldap +OBJECTS_DIR = obj/unix +MOC_DIR = moc/unix +} +win32: { +DEFINES += _WIN32_ +LIBS += ../bin/microkdepim.lib +LIBS += ../bin/microkcal.lib +LIBS += ../bin/microkde.lib +LIBS += ../bin/microkabc.lib +QMAKE_LINK += /NODEFAULTLIB:LIBC +OBJECTS_DIR = obj/win +MOC_DIR = moc/win +} + + + + + + + + +INTERFACES = \ +# filteredit_base.ui \ +# kofilterview_base.ui \ + +HEADERS = \ +features/mergewidget.h \ +features/distributionlistwidget.h \ +kcmconfigs/addresseewidget.h \ +kcmconfigs/extensionconfigdialog.h \ +kcmconfigs/kcmkabconfig.h \ +kcmconfigs/kabconfigwidget.h \ +addresseeeditordialog.h \ +addresseeeditorwidget.h \ +addresseditwidget.h \ +addresseeconfig.h \ +addresseeutil.h \ +emaileditwidget.h \ +filtereditdialog.h \ +kaddressbookmain.h \ +kabprefs.h \ +kabcore.h \ +viewmanager.h \ +extensionmanager.h \ +extensionwidget.h \ +kaddressbookview.h \ +geowidget.h \ +imagewidget.h \ +incsearchwidget.h \ +jumpbuttonbar.h \ +phoneeditwidget.h \ +secrecywidget.h \ +keywidget.h \ +nameeditdialog.h \ +filter.h \ +addviewdialog.h \ +configurewidget.h \ +viewconfigurewidget.h \ +viewconfigurefieldspage.h \ +viewconfigurefilterpage.h \ +typecombo.h \ +undo.h \ +undocmds.h \ +xxportmanager.h \ +xxportobject.h \ +xxportselectdialog.h \ +details/detailsviewcontainer.h \ +details/look_basic.h \ +details/look_html.h \ +views/kaddressbookiconview.h \ +views/kaddressbooktableview.h \ +views/kaddressbookcardview.h \ +views/configuretableviewdialog.h \ +views/configurecardviewdialog.h \ +views/cardview.h \ +views/colorlistbox.h \ +views/contactlistview.h \ +xxport/vcard_xxport.h \ +xxport/kde2_xxport.h \ +xxport/csv_xxport.h \ +xxport/csvimportdialog.h \ +#details/look_details.h \ +#mainwindoiw.h \ +# alarmclient.h \ +# calendarview.h \ +# customlistviewitem.h \ +# datenavigator.h + +SOURCES = \ +addresseeeditordialog.cpp \ +addresseeeditorwidget.cpp \ +addresseditwidget.cpp \ +addresseeconfig.cpp \ +addresseeutil.cpp \ +extensionmanager.cpp \ +features/mergewidget.cpp \ +features/distributionlistwidget.cpp \ +kcmconfigs/addresseewidget.cpp \ +kcmconfigs/extensionconfigdialog.cpp \ +kcmconfigs/kcmkabconfig.cpp \ +kcmconfigs/kabconfigwidget.cpp \ +emaileditwidget.cpp \ +filtereditdialog.cpp \ +mainembedded.cpp \ +kaddressbookmain.cpp \ +kabcore.cpp \ +kabprefs.cpp \ +viewmanager.cpp \ +kaddressbookview.cpp \ +extensionwidget.cpp \ +geowidget.cpp \ +imagewidget.cpp \ +incsearchwidget.cpp \ +jumpbuttonbar.cpp \ +phoneeditwidget.cpp \ +secrecywidget.cpp \ +keywidget.cpp \ +nameeditdialog.cpp \ +filter.cpp \ +addviewdialog.cpp \ +configurewidget.cpp \ +viewconfigurewidget.cpp \ +viewconfigurefieldspage.cpp \ +viewconfigurefilterpage.cpp \ +undo.cpp \ +undocmds.cpp \ +xxportmanager.cpp \ +xxportobject.cpp \ +xxportselectdialog.cpp \ +details/detailsviewcontainer.cpp \ +details/look_basic.cpp \ +details/look_html.cpp \ +views/kaddressbookiconview.cpp \ +views/kaddressbooktableview.cpp \ +views/kaddressbookcardview.cpp \ +views/configuretableviewdialog.cpp \ +views/configurecardviewdialog.cpp \ +views/cardview.cpp \ +views/contactlistview.cpp \ +views/colorlistbox.cpp \ +xxport/vcard_xxport.cpp \ +xxport/kde2_xxport.cpp \ +xxport/csv_xxport.cpp \ +xxport/csvimportdialog.cpp \ +#details/look_details.cpp \ +#mainwindow.cpp \ +# calendarview.cpp \ +# timespanview.cpp + diff --git a/kaddressbook/kaddressbookE.pro b/kaddressbook/kaddressbookE.pro new file mode 100644 index 0000000..577dbf9 --- a/dev/null +++ b/kaddressbook/kaddressbookE.pro @@ -0,0 +1,154 @@ +TEMPLATE = app +CONFIG += qt warn_on + + +TARGET = kapi +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR=$(QPEDIR)/bin + + +INCLUDEPATH += . ./details ./features ./kcmconfigs ./xxport ../microkde ../microkde/kdecore ../microkde/kutils ../microkde/kio/kfile ../microkde/kdeui ../kabc ../qtcompat ../ interfaces $(QPEDIR)/include +DEFINES += KAB_EMBEDDED KAB_NOSPLITTER +#DEFINES += KORG_NODND KORG_NOPLUGINS KORG_NOKABC KORG_NOARCHIVE KORG_NOMAIL +#DEFINES += KORG_NOPRINTER KORG_NODCOP KORG_NOKALARMD KORG_NORESOURCEVIEW KORG_NOSPLITTER +#DEFINES += KORG_NOLVALTERNATION +LIBS += -lmicrokdepim +#LIBS += -lmicrokcal +LIBS += -lmicrokde +LIBS += -lmicrokcal +LIBS += -lmicroqtcompat +LIBS += -lmicrokabc +LIBS += -lqpe +LIBS += -ljpeg +LIBS += $(QTOPIALIB) +LIBS += -L$(QPEDIR)/lib + +INTERFACES = \ +# filteredit_base.ui \ +# kofilterview_base.ui \ + +HEADERS = \ +features/mergewidget.h \ +features/distributionlistwidget.h \ +kcmconfigs/addresseewidget.h \ +kcmconfigs/extensionconfigdialog.h \ +kcmconfigs/kcmkabconfig.h \ +kcmconfigs/kabconfigwidget.h \ +addresseeeditordialog.h \ +addresseeeditorwidget.h \ +addresseditwidget.h \ +addresseeconfig.h \ +addresseeutil.h \ +emaileditwidget.h \ +filtereditdialog.h \ +kaddressbookmain.h \ +kabprefs.h \ +kabcore.h \ +viewmanager.h \ +extensionmanager.h \ +extensionwidget.h \ +kaddressbookview.h \ +geowidget.h \ +imagewidget.h \ +incsearchwidget.h \ +jumpbuttonbar.h \ +phoneeditwidget.h \ +secrecywidget.h \ +keywidget.h \ +nameeditdialog.h \ +filter.h \ +addviewdialog.h \ +configurewidget.h \ +viewconfigurewidget.h \ +viewconfigurefieldspage.h \ +viewconfigurefilterpage.h \ +typecombo.h \ +undo.h \ +undocmds.h \ +xxportmanager.h \ +xxportobject.h \ +xxportselectdialog.h \ +details/detailsviewcontainer.h \ +details/look_basic.h \ +details/look_html.h \ +views/kaddressbookiconview.h \ +views/kaddressbooktableview.h \ +views/kaddressbookcardview.h \ +views/configuretableviewdialog.h \ +views/configurecardviewdialog.h \ +views/cardview.h \ +views/colorlistbox.h \ +views/contactlistview.h \ +xxport/vcard_xxport.h \ +xxport/kde2_xxport.h \ +xxport/csv_xxport.h \ +xxport/csvimportdialog.h \ +#details/look_details.h \ +#mainwindoiw.h \ +# alarmclient.h \ +# calendarview.h \ +# customlistviewitem.h \ +# datenavigator.h + +SOURCES = \ +addresseeeditordialog.cpp \ +addresseeeditorwidget.cpp \ +addresseditwidget.cpp \ +addresseeconfig.cpp \ +addresseeutil.cpp \ +extensionmanager.cpp \ +features/mergewidget.cpp \ +features/distributionlistwidget.cpp \ +kcmconfigs/addresseewidget.cpp \ +kcmconfigs/extensionconfigdialog.cpp \ +kcmconfigs/kcmkabconfig.cpp \ +kcmconfigs/kabconfigwidget.cpp \ +emaileditwidget.cpp \ +filtereditdialog.cpp \ +mainembedded.cpp \ +kaddressbookmain.cpp \ +kabcore.cpp \ +kabprefs.cpp \ +viewmanager.cpp \ +kaddressbookview.cpp \ +extensionwidget.cpp \ +geowidget.cpp \ +imagewidget.cpp \ +incsearchwidget.cpp \ +jumpbuttonbar.cpp \ +phoneeditwidget.cpp \ +secrecywidget.cpp \ +keywidget.cpp \ +nameeditdialog.cpp \ +filter.cpp \ +addviewdialog.cpp \ +configurewidget.cpp \ +viewconfigurewidget.cpp \ +viewconfigurefieldspage.cpp \ +viewconfigurefilterpage.cpp \ +undo.cpp \ +undocmds.cpp \ +xxportmanager.cpp \ +xxportobject.cpp \ +xxportselectdialog.cpp \ +details/detailsviewcontainer.cpp \ +details/look_basic.cpp \ +details/look_html.cpp \ +views/kaddressbookiconview.cpp \ +views/kaddressbooktableview.cpp \ +views/kaddressbookcardview.cpp \ +views/configuretableviewdialog.cpp \ +views/configurecardviewdialog.cpp \ +views/cardview.cpp \ +views/contactlistview.cpp \ +views/colorlistbox.cpp \ +xxport/vcard_xxport.cpp \ +xxport/kde2_xxport.cpp \ +xxport/csv_xxport.cpp \ +xxport/csvimportdialog.cpp \ +#details/look_details.cpp \ +#mainwindow.cpp \ +# calendarview.cpp \ +# timespanview.cpp + diff --git a/kaddressbook/kaddressbookmain.cpp b/kaddressbook/kaddressbookmain.cpp new file mode 100644 index 0000000..92c32ca --- a/dev/null +++ b/kaddressbook/kaddressbookmain.cpp @@ -0,0 +1,293 @@ +/* + This file is part of KAddressbook. + Copyright (c) 1999 Don Sanders <dsanders@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifdef KAB_EMBEDDED +#include "kabprefs.h" +#include <kglobal.h> +#include <qmessagebox.h> +#include <qtoolbar.h> +#include <qapplication.h> +#else //KAB_EMBEDDED +#include <kedittoolbar.h> +#include <kkeydialog.h> +#include <kmessagebox.h> +#include <kstatusbar.h> +#endif //KAB_EMBEDDED +#include <klocale.h> + +#include "kabcore.h" +#include "kaddressbookmain.h" +#include "kactioncollection.h" + +#ifdef KAB_EMBEDDED +KAddressBookMain::KAddressBookMain() : KMainWindow( 0, "adrressbook" ) +#else //KAB_EMBEDDED +//MOC_SKIP_BEGIN +KAddressBookMain::KAddressBookMain() : DCOPObject( "KAddressBookIface" ), KMainWindow( 0 ) +//MOC_SKIP_END +#endif //KAB_EMBEDDED +{ + + setIcon(SmallIcon( "ka24" ) ); +#if 0 + //US for embedded systems, create the toolbar before we initiate KABCore. + // KABCore will fill the toolbar with menues and icons + QMainWindow::ToolBarDock tbd; + tbd = Top; + iconToolBar = new QToolBar( this ); + addToolBar (iconToolBar , tbd ); + iconToolBar->setHorizontalStretchable(true); +//US iconToolBar->setWidth(300); +#endif // 0 + + mCore = new KABCore( this, true, this ); + +#ifdef KAB_EMBEDDED + setCaption( i18n( "KAddressbook/Pi" ) ); +#else //KAB_EMBEDDED + setCaption( i18n( "Address Book Browser" ) ); +#endif //KAB_EMBEDDED + + //mCore->restoreSettings(); + + initActions(); + + setCentralWidget( mCore ); + +//US statusBar()->show(); + +#ifndef KAB_EMBEDDED + setStandardToolBarMenuEnabled(true); + + createGUI( "kaddressbookui.rc", false ); + + +#endif //KAB_EMBEDDED + setAutoSaveSettings(); + qApp->processEvents(); + mCore->restoreSettings(); +} + +KAddressBookMain::~KAddressBookMain() +{ + // mCore->saveSettings(); +} +#ifndef DESKTOP_VERSION +void KAddressBookMain::show () +{ + static bool block = false; + if( block ) { + QWidget::show(); + return; + } else { + block = true ; + QWidget::showFullScreen(); + } + int min = 20; + if ( QApplication::desktop()->width() > 320 ) + min += 20; + setGeometry( 0,0,QApplication::desktop()->width(), QApplication::desktop()->height() - min ); + block = false; +} +#endif +void KAddressBookMain::showMinimized () +{ + QWidget::showMinimized () ; +} +void KAddressBookMain::addEmail( QString addr ) +{ + mCore->addEmail( addr ); +} + +#ifndef KAB_EMBEDDED +ASYNC KAddressBookMain::showContactEditor( QString uid ) +{ + mCore->editContact( uid ); +} +#endif //KAB_EMBEDDED +void KAddressBookMain::newContact() +{ + mCore->newContact(); +} + +QString KAddressBookMain::getNameByPhone( QString phone ) +{ + return mCore->getNameByPhone( phone ); +} + +void KAddressBookMain::save() +{ + mCore->save(); +} + +void KAddressBookMain::exit() +{ + close( ); +} + +void KAddressBookMain::saveProperties( KConfig* ) +{ +} + +void KAddressBookMain::readProperties( KConfig* ) +{ +} + +void KAddressBookMain::initActions() +{ +#ifndef KAB_EMBEDDED + KStdAction::quit( this, SLOT( close() ), actionCollection() ); + KStdAction::configureToolbars( this, SLOT( configureToolbars() ), actionCollection() ); +#else //KAB_EMBEDDED + //US: transfered the setup of the actions into KABCore +#endif //KAB_EMBEDDED + + +} + +//US new method to setup menues and toolbars on embedded systems +#ifdef KAB_EMBEDDED +/* +QToolBar * KAddressBookMain::getIconToolBar() +{ + return iconToolBar; +} +*/ + +void KAddressBookMain::createGUI() +{ + + + +} +#endif //KAB_EMBEDDED + +void KAddressBookMain::configureToolbars() +{ +#ifndef KAB_EMBEDDED + saveMainWindowSettings( KGlobal::config(), "MainWindow" ); + + KEditToolbar dlg( factory() ); + connect( &dlg, SIGNAL( newToolbarConfig() ), SLOT( slotNewToolbarConfig() ) ); + + dlg.exec(); +#else //KAB_EMBEDDED + qDebug("KAddressBookMain::configureToolbars() not implemented by ulf" ); +#endif //KAB_EMBEDDED +} + +void KAddressBookMain::slotNewToolbarConfig() +{ +#ifndef KAB_EMBEDDED + applyMainWindowSettings( KGlobal::config(), "MainWindow" ); +#else //KAB_EMBEDDED + qDebug("KAddressBookMain::slotNewToolbarConfig() not implemented by ulf" ); +#endif //KAB_EMBEDDED +} + +void KAddressBookMain::configureKeys() +{ +#ifndef KAB_EMBEDDED + KKeyDialog::configureKeys( actionCollection(), xmlFile(), true, this ); +#else //KAB_EMBEDDED + qDebug("KAddressBookMain::configureKeys() not implemented by ulf" ); +#endif //KAB_EMBEDDED +} + +void KAddressBookMain::closeEvent( QCloseEvent* ce ) +{ + QString mess = i18n( "Close KA/Pi?"); + if ( mCore->modified() ) + mess += i18n( "\n\nChanges will be saved!"); + else + mess += i18n( "\n\nNo unsaved changes detected!\nNothing will be saved!"); + + switch( QMessageBox::information( this, "KA/Pi", mess , + i18n("Yes!"), i18n("No"), 0, 0 ) ) { + case 0: + + break; + case 1: + return; + break; + case 2: + return; + break; + + default: + return; + break; + } + +#if 0 + + if ( mCore->modified() ) { + QString text = i18n( "The address book has been modified.\nDo you want to save your changes?" ); + +#ifndef KAB_EMBEDDED + int ret = KMessageBox::warningYesNoCancel( this, text, "", + KStdGuiItem::yes(), + KStdGuiItem::no(), "AskForSave" ); + switch ( ret ) { + case KMessageBox::Yes: + save(); + break; + case KMessageBox::No: + return true; + break; + default: //cancel + return ; + break; + } + +#else //KAB_EMBEDDED + switch( QMessageBox::information( this, "KA/Pi", + text, + i18n("Yes!"), i18n("No"), 0, 0 ) ) { + case 0: + save(); + break; + case 1: + break; + case 2: + return; + default: + return; + break; + } +#endif //KAB_EMBEDDED + } + +#endif + + save(); + mCore->saveSettings(); + KABPrefs::instance()->writeConfig(); + ce->accept(); + +} + +#ifndef KAB_EMBEDDED +#include "kaddressbookmain.moc" +#endif //KAB_EMBEDDED + diff --git a/kaddressbook/kaddressbookmain.h b/kaddressbook/kaddressbookmain.h new file mode 100644 index 0000000..81ae09c --- a/dev/null +++ b/kaddressbook/kaddressbookmain.h @@ -0,0 +1,126 @@ +/* + This file is part of KAddressbook. + Copyright (c) 1999 Don Sanders <dsanders@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KADDRESSBOOKMAIN_H +#define KADDRESSBOOKMAIN_H + +#include <qptrlist.h> + +#ifdef KAB_EMBEDDED +class QToolBar; +#include <qaction.h> +//#include <qmainwindow.h> +#include <kmainwindow.h> +#else //KAB_EMBEDDED +#include <kaction.h> +#include <kapplication.h> +#include <kmainwindow.h> +#include "kaddressbookiface.h" +#endif //KAB_EMBEDDED + +class KABCore; +class KConfig; + +/** + This class serves as the main window for KAddressBook. It handles the + menus, toolbars, and status bars. + + @short Main window class + @author Don Sanders <dsanders@kde.org> + @version 0.1 + */ +#ifdef KAB_EMBEDDED +class KAddressBookMain : public KMainWindow +#else //KAB_EMBEDDED +//MOC_SKIP_BEGIN +class KAddressBookMain : public KMainWindow, virtual public KAddressBookIface +//MOC_SKIP_END +#endif //KAB_EMBEDDED +{ + Q_OBJECT + + public: + KAddressBookMain(); + virtual ~KAddressBookMain(); + +#ifdef KAB_EMBEDDED +// QPEToolBar * getIconToolBar(); + // QToolBar * getIconToolBar(); +#endif //KAB_EMBEDDED + + + public slots: +#ifndef DESKTOP_VERSION + void show(); +#endif + + void showMinimized () ; + virtual void addEmail( QString addr ); +#ifndef KAB_EMBEDDED +//MOC_SKIP_BEGIN + virtual ASYNC showContactEditor( QString uid ); +//MOC_SKIP_END +#endif //KAB_EMBEDDED + virtual void newContact(); + virtual QString getNameByPhone( QString phone ); + virtual void save(); + virtual void exit(); + + protected: + void initActions(); +#ifdef KAB_EMBEDDED + //US new method to setup menues and toolbars on embedded systems + void createGUI(); +#endif //KAB_EMBEDDED + + /** + This function is called when it is time for the app to save its + properties for session management purposes. + */ + void saveProperties( KConfig* ); + + /** + This function is called when this app is restored. The KConfig + object points to the session management config file that was saved + with @ref saveProperties + */ + void readProperties( KConfig* ); + + void closeEvent( QCloseEvent* ce ); + + protected slots: + void configureToolbars(); + void configureKeys(); + + void slotNewToolbarConfig(); + + private: + KABCore *mCore; + +#ifdef KAB_EMBEDDED + // QToolBar *iconToolBar; +#endif //KAB_EMBEDDED + +}; + +#endif diff --git a/kaddressbook/kaddressbookview.cpp b/kaddressbook/kaddressbookview.cpp new file mode 100644 index 0000000..a44fd82 --- a/dev/null +++ b/kaddressbook/kaddressbookview.cpp @@ -0,0 +1,171 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KAB_EMBEDDED +#include <qapplication.h> + +#include <kabc/distributionlistdialog.h> +#include <kconfig.h> +#include <klocale.h> + +#include "viewmanager.h" + +#endif //KAB_EMBEDDED +#include <qlayout.h> + +#include <kabc/addressbook.h> +#include <kdebug.h> + +#include "kaddressbookview.h" + +KAddressBookView::KAddressBookView( KABC::AddressBook *ab, QWidget *parent, + const char *name ) + : QWidget( parent, name ), mAddressBook( ab ), mFieldList() +{ + initGUI(); +} + +KAddressBookView::~KAddressBookView() +{ + kdDebug(5720) << "KAddressBookView::~KAddressBookView: destroying - " + << name() << endl; +} + +void KAddressBookView::readConfig( KConfig *config ) +{ + mFieldList = KABC::Field::restoreFields( config, "KABCFields" ); + + if ( mFieldList.isEmpty() ) + mFieldList = KABC::Field::defaultFields(); + + mDefaultFilterType = (DefaultFilterType)config->readNumEntry( "DefaultFilterType", 1 ); + mDefaultFilterName = config->readEntry( "DefaultFilterName", QString::null ); +} + +void KAddressBookView::writeConfig( KConfig* ) +{ + // Most of writing the config is handled by the ConfigureViewDialog +} + +QString KAddressBookView::selectedEmails() +{ +#ifndef KAB_EMBEDDED + + bool first = true; + QString emailAddrs; + QStringList uidList = selectedUids(); + KABC::Addressee addr; + QString email; + + QStringList::Iterator it; + for ( it = uidList.begin(); it != uidList.end(); ++it ) { + addr = mAddressBook->findByUid( *it ); + + if ( !addr.isEmpty() ) { + QString m = QString::null; + + if ( addr.emails().count() > 1 ) + m = KABC::EmailSelector::getEmail( addr.emails(), addr.preferredEmail(), this ); + + email = addr.fullEmail( m ); + + if ( !first ) + emailAddrs += ", "; + else + first = false; + + emailAddrs += email; + } + } + + return emailAddrs; +#else //KAB_EMBEDDED +qDebug("KAddressBookView::selectedEmails() update method"); +return 0; +#endif //KAB_EMBEDDED + +} + +KABC::Addressee::List KAddressBookView::addressees() +{ + KABC::Addressee::List addresseeList; + + KABC::AddressBook::Iterator it; + for (it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { + if ( mFilter.filterAddressee( *it ) ) + addresseeList.append( *it ); + } + + return addresseeList; +} + +void KAddressBookView::initGUI() +{ + // Create the layout + QVBoxLayout *layout = new QVBoxLayout( this ); + + // Add the view widget + mViewWidget = new QWidget( this ); + layout->addWidget( mViewWidget ); +} + +KABC::Field::List KAddressBookView::fields() const +{ + return mFieldList; +} + +void KAddressBookView::setFilter( const Filter &filter ) +{ + mFilter = filter; +} + +KAddressBookView::DefaultFilterType KAddressBookView::defaultFilterType() const +{ + return mDefaultFilterType; +} + +const QString &KAddressBookView::defaultFilterName() const +{ + return mDefaultFilterName; +} + +KABC::AddressBook *KAddressBookView::addressBook() const +{ + return mAddressBook; +} + +QWidget *KAddressBookView::viewWidget() +{ + return mViewWidget; +} + +ViewConfigureWidget *ViewFactory::configureWidget( KABC::AddressBook *ab, + QWidget *parent, + const char *name ) +{ + return new ViewConfigureWidget( ab, parent, name ); +} + +#ifndef KAB_EMBEDDED +#include "kaddressbookview.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/kaddressbookview.h b/kaddressbook/kaddressbookview.h new file mode 100644 index 0000000..7457080 --- a/dev/null +++ b/kaddressbook/kaddressbookview.h @@ -0,0 +1,295 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KADDRESSBOOKVIEW_H +#define KADDRESSBOOKVIEW_H + +#ifndef KAB_EMBEDDED +#include <klibloader.h> +#endif //KAB_EMBEDDED + +class KConfig; +class QDropEvent; + +#include <qstringlist.h> +#include <kabc/field.h> +#include <qwidget.h> + +#include "viewconfigurewidget.h" +#include "filter.h" + +namespace KABC { class AddressBook; } + +/** + Base class for all views in kaddressbook. This class implements + all the common methods needed to provide a view to the user. + + To implement a specific view (table, card, etc), just inherit from + this class and implement all the pure virtuals. + + @author Mike Pilone <mpilone@slac.com> + */ +class KAddressBookView : public QWidget +{ + Q_OBJECT + + public: + enum DefaultFilterType { None = 0, Active = 1, Specific = 2 }; + + KAddressBookView( KABC::AddressBook *ab, QWidget *parent, const char *name ); + virtual ~KAddressBookView(); + + /** + Must be overloaded in subclasses. Should return a list of + all the uids of selected contacts. + */ + virtual QStringList selectedUids() = 0; + + /** + Called whenever this view should read the config. This can be used + as a sign that the config has changed, therefore the view should + assume the worst and rebuild itself if necessary. For example, + in a table view this method may be called when the user adds or + removes columns from the view. + + If overloaded in the subclass, do not forget to call super class's + method. + + @param config The KConfig object to read from. The group will already + be set, so do not change the group. + */ + virtual void readConfig( KConfig *config ); + + /** + Called whenever this view should write the config. The view should not + write out information handled by the application, such as which fields + are visible. The view should only write out information specific + to itself (i.e.: All information in the ViewConfigWidget) + + If overloaded in the subclass, do not forget to call the super class's + method. + + @param config The KConfig object to read from. The group will already + be set, so do not change the group. + */ + virtual void writeConfig( KConfig *config ); + + /** + Returns a QString with all the selected email addresses concatenated + together with a ',' seperator. + */ + virtual QString selectedEmails(); + + /** + Return the type of the view: Icon, Table, etc. Please make sure that + this is the same value that ViewWrapper::type() will return for your + view. + */ + virtual QString type() const = 0; + + /** + Returns a list of the fields that should be displayed. The list + is composed of the fields proper names (ie: Home Address), so + the view may need to translate them in order to get the + value from the addressee. + + This list is generated from the config file, so it is advisable to call + this method whenever a readConfig() is called in order to get the newest + list of fields. + */ + KABC::Field::List fields() const; + + /** + Sets the active filter. This filter will be used for filtering + the list of addressees to display. The view will <b>not</b> + automatically refresh itself, so in most cases you will want to call + KAddressBookView::refresh() after this method. + */ + void setFilter( const Filter& ); + + /** + @return The default filter type selection. If the selection + is SpecificFilter, the name of the filter can be retrieved with + defaultFilterName() + */ + DefaultFilterType defaultFilterType() const; + + /** + @return The name of the default filter. This string is + only valid if defaultFilterType() is returning SpecificFilter. + */ + const QString &defaultFilterName() const; + + /** + @return The address book. + */ + KABC::AddressBook *addressBook() const; + + public slots: + /** + Must be overloaded in subclasses to refresh the view. + Refreshing includes updating the view to ensure that only items + in the document are visible. If <i>uid</i> is valid, only the + addressee with uid needs to be refreshed. This is an optimization + only. + */ + virtual void refresh( QString uid = QString::null ) = 0; + + /** + This method must be overloaded in subclasses. Select (highlight) + the addressee matching <i>uid</i>. If uid + is equal to QString::null, then all addressees should be selected. + */ +#ifndef KAB_EMBEDDED +//MOC_SKIP_BEGIN + virtual void setSelected( QString uid = QString::null, bool selected = true ) = 0; +//MOC_SKIP_END +#else //KAB_EMBEDDED + //US my moc can not handle the default parameters. Is this a problem ??? + virtual void setSelected( QString uid, bool selected) = 0; +#endif //KAB_EMBEDDED + + signals: + /** + This signal should be emitted by a subclass whenever an addressee + is modified. + */ + void modified(); + + /** + This signal should be emitted by a subclass whenever an addressee + is selected. Selected means that the addressee was given the focus. + Some widgets may call this 'highlighted'. The view is responsible for + emitting this signal multiple times if multiple items are selected, + with the last item selected being the last emit. + + @param uid The uid of the selected addressee. + + @see KListView + */ + void selected( const QString &uid ); + void deleteRequest(); + /** + This signal should be emitted by a subclass whenever an addressee + is executed. This is defined by the KDE system wide config, but it + either means single or doubleclicked. + + @param ui The uid of the selected addressee + + @see KListView + */ + void executed( const QString &uid ); + + /** + This signal is emitted whenever a user attempts to start a drag + in the view. The slot connected to this signal would usually want + to create a QDragObject. + */ + void startDrag(); + + /** + This signal is emitted whenever the user drops something on the + view. The individual view should handle checking if the item is + droppable (ie: if it is a vcard). + */ + void dropped( QDropEvent* ); + + protected: + /** + Returns a list of the addressees that should be displayed. This method + should always be used by the subclass to get a list of addressees. This + method internally takes many factors into account, including the current + filter. + */ + KABC::Addressee::List addressees(); + + /** + This method returns the widget that should be used as the parent for + all view components. By using this widget as the parent and not + 'this', the view subclass has the option of placing other widgets + around the view (ie: search fields, etc). Do not delete this widget! + */ + QWidget *viewWidget(); + + private: + void initGUI(); + + DefaultFilterType mDefaultFilterType; + Filter mFilter; + QString mDefaultFilterName; + KABC::AddressBook *mAddressBook; + KABC::Field::List mFieldList; + + QWidget *mViewWidget; +}; + +#ifndef KAB_EMBEDDED +//MOC_SKIP_BEGIN +class ViewFactory : public KLibFactory +//MOC_SKIP_END +#else //KAB_EMBEDDED +class ViewFactory +#endif //KAB_EMBEDDED +{ + + public: + virtual KAddressBookView *view( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ) = 0; + + /** + @return The type of the view. This is normally a small one word + string (ie: Table, Icon, Tree, etc). + */ + virtual QString type() const = 0; + + /** + @return The description of the view. This should be a 3 to + 4 line string (don't actually use return characters in the string) + describing the features offered by the view. + */ + virtual QString description() const = 0; + + /** + Creates a config dialog for the view type. The default + implementation will return a ViewConfigDialog. This default + dialog will allow the user to set the visible fields only. If + you need more config options (as most views will), this method + can be overloaded to return your sublcass of ViewConfigDialog. + If this method is over loaded the base classes method should + <B>not</B> be called. + */ + virtual ViewConfigureWidget *configureWidget( KABC::AddressBook *ab, + QWidget *parent, + const char *name = 0 ); + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } + +}; + + +#endif diff --git a/kaddressbook/kcmconfigs/addresseewidget.cpp b/kaddressbook/kcmconfigs/addresseewidget.cpp new file mode 100644 index 0000000..0f3c353 --- a/dev/null +++ b/kaddressbook/kcmconfigs/addresseewidget.cpp @@ -0,0 +1,236 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qpushbutton.h> + +#include <kbuttonbox.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <kdialog.h> +#include <klocale.h> +#include <kglobal.h> +#include <klineedit.h> +#include <kstandarddirs.h> + +#include "addresseewidget.h" + +NamePartWidget::NamePartWidget( const QString &title, QWidget *parent, + const char *name ) + : QWidget( parent, name ) +{ + if (KGlobal::getOrientation() == KGlobal::Portrait) + { + QGridLayout* layout = new QGridLayout( this, 1, 1, KDialog::marginHintSmall(), + KDialog::spacingHintSmall() ); + + QLabel *label = new QLabel( i18n( title ), this ); + layout->addWidget( label, 0, 1 ); + + mBox = new QListBox( this ); + mBox->setMaximumSize(70, 70); + layout->addMultiCellWidget( mBox, 0, 1, 0, 0 ); + + KButtonBox *bbox = new KButtonBox( this, Qt::Vertical ); + mAddButton = bbox->addButton( i18n( "Add" ), this, SLOT( add() ) ); + mRemoveButton = bbox->addButton( i18n( "Rem" ), this, SLOT( remove() ) ); + bbox->layout(); + layout->addMultiCellWidget( bbox, 0, 2, 2,2); + + mEdit = new KLineEdit( this ); + layout->addWidget( mEdit, 1, 1 ); + //mEdit->setMinimumWidth(50); + +// layout->addWidget( group ); + + } + else + { + QHBoxLayout *layout = new QHBoxLayout( this ); + + QGroupBox *group = new QGroupBox( 0, Qt::Vertical, title, this ); + QGridLayout *groupLayout = new QGridLayout( group->layout(), 2, 2, + KDialog::spacingHint() ); + + mBox = new QListBox( group ); + + groupLayout->addWidget( mBox, 0, 0 ); + + KButtonBox *bbox = new KButtonBox( group, Qt::Vertical ); + mAddButton = bbox->addButton( i18n( "Add" ), this, SLOT( add() ) ); + mRemoveButton = bbox->addButton( i18n( "Remove" ), this, SLOT( remove() ) ); + bbox->layout(); + groupLayout->addWidget( bbox, 0, 1 ); + + mEdit = new KLineEdit( group ); + groupLayout->addMultiCellWidget( mEdit, 1, 1, 0, 1 ); + + layout->addWidget( group ); + + } + + mAddButton->setEnabled( false ); + mRemoveButton->setEnabled( false ); + + + connect( mBox, SIGNAL( selectionChanged( QListBoxItem* ) ), + SLOT( selectionChanged( QListBoxItem* ) ) ); + connect( mEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( textChanged( const QString& ) ) ); + connect( mEdit, SIGNAL( returnPressed() ), SLOT( add() ) ); + +} + +NamePartWidget::~NamePartWidget() +{ +} + +void NamePartWidget::setNameParts( const QStringList &list ) +{ + mBox->clear(); + mBox->insertStringList( list ); +} + +QStringList NamePartWidget::nameParts() const +{ + QStringList parts; + for ( uint i = 0; i < mBox->count(); ++i ) + parts.append( mBox->text( i ) ); + + return parts; +} + +void NamePartWidget::add() +{ + if ( !mEdit->text().isEmpty() ) { + mBox->insertItem( mEdit->text() ); + emit modified(); + } + + mEdit->setText( "" ); +} + +void NamePartWidget::remove() +{ + mBox->removeItem( mBox->currentItem() ); + if ( mBox->count() == 0 ) + selectionChanged( 0 ); + + emit modified(); +} + +void NamePartWidget::selectionChanged( QListBoxItem *item ) +{ + mRemoveButton->setEnabled( item != 0 ); +} + +void NamePartWidget::textChanged( const QString& text ) +{ + mAddButton->setEnabled( !text.isEmpty() ); +} + + +AddresseeWidget::AddresseeWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QGridLayout *layout; + + mPrefix = new NamePartWidget( i18n( "Prefixes" ), this ); + mInclusion = new NamePartWidget( i18n( "Inclusions" ), this ); + mSuffix = new NamePartWidget( i18n( "Suffixes" ), this ); + QLabel *label = new QLabel( i18n( "Default formatted name:" ), this ); + + mFormattedNameCombo = new KComboBox( this ); + mFormattedNameCombo->insertItem( i18n( "Empty" ) ); + mFormattedNameCombo->insertItem( i18n( "Simple Name" ) ); + mFormattedNameCombo->insertItem( i18n( "Full Name" ) ); + mFormattedNameCombo->insertItem( i18n( "Reverse Name" ) ); + + if (KGlobal::getOrientation() == KGlobal::Portrait) + { + layout = new QGridLayout( this, 4, 2, KDialog::marginHint(), + KDialog::spacingHint() ); + + layout->addMultiCellWidget( mPrefix, 0, 0, 0, 1 ); + layout->addMultiCellWidget( mInclusion, 1, 1, 0, 1 ); + layout->addMultiCellWidget( mSuffix, 2, 2, 0, 1 ); + layout->addWidget( label, 3, 0 ); + layout->addWidget( mFormattedNameCombo, 3, 1 ); + + } + else + { + layout = new QGridLayout( this, 2, 3, KDialog::marginHint(), + KDialog::spacingHint() ); + + layout->addWidget( mPrefix, 0, 0 ); + layout->addWidget( mInclusion, 0, 1 ); + layout->addWidget( mSuffix, 0, 2 ); + layout->addWidget( label, 1, 0 ); + layout->addMultiCellWidget( mFormattedNameCombo, 1, 1, 1, 2 ); + } + + connect( mPrefix, SIGNAL( modified() ), SIGNAL( modified() ) ); + connect( mInclusion, SIGNAL( modified() ), SIGNAL( modified() ) ); + connect( mSuffix, SIGNAL( modified() ), SIGNAL( modified() ) ); + connect( mFormattedNameCombo, SIGNAL( activated( int ) ), SIGNAL( modified() ) ); +} + +AddresseeWidget::~AddresseeWidget() +{ +} + +void AddresseeWidget::restoreSettings() +{ + KConfig config( locateLocal("config", "kabcrc") ); + config.setGroup( "General" ); + + mPrefix->setNameParts( config.readListEntry( "Prefixes" ) ); + mInclusion->setNameParts( config.readListEntry( "Inclusions" ) ); + mSuffix->setNameParts( config.readListEntry( "Suffixes" ) ); + + KConfig cfg( locateLocal("config","kaddressbookrc") ); + cfg.setGroup( "General" ); + mFormattedNameCombo->setCurrentItem( cfg.readNumEntry( "FormattedNameType", 1 ) ); +} + +void AddresseeWidget::saveSettings() +{ + KConfig config( locateLocal("config","kabcrc") ); + config.setGroup( "General" ); + + config.writeEntry( "Prefixes", mPrefix->nameParts() ); + config.writeEntry( "Inclusions", mInclusion->nameParts() ); + config.writeEntry( "Suffixes", mSuffix->nameParts() ); + + KConfig cfg( locateLocal("config","kaddressbookrc") ); + cfg.setGroup( "General" ); + cfg.writeEntry( "FormattedNameType", mFormattedNameCombo->currentItem() ); +} + +#ifndef KAB_EMBEDDED +#include "addresseewidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/kcmconfigs/addresseewidget.h b/kaddressbook/kcmconfigs/addresseewidget.h new file mode 100644 index 0000000..09330c8 --- a/dev/null +++ b/kaddressbook/kcmconfigs/addresseewidget.h @@ -0,0 +1,87 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef ADDRESSEEWIDGET_H +#define ADDRESSEEWIDGET_H + +#include <qwidget.h> + +class KComboBox; +class KLineEdit; + +class QListBox; +class QListBoxItem; +class QPushButton; + +class NamePartWidget : public QWidget +{ + Q_OBJECT + + public: + NamePartWidget( const QString &title, QWidget *parent, + const char *name = 0 ); + ~NamePartWidget(); + + void setNameParts( const QStringList &list ); + QStringList nameParts() const; + + signals: + void modified(); + + private slots: + void add(); + void remove(); + + void selectionChanged( QListBoxItem* ); + void textChanged( const QString& ); + + private: + KLineEdit *mEdit; + + QListBox *mBox; + QPushButton *mAddButton; + QPushButton *mRemoveButton; +}; + +class AddresseeWidget : public QWidget +{ + Q_OBJECT + + public: + AddresseeWidget( QWidget *parent, const char *name = 0 ); + ~AddresseeWidget(); + + void restoreSettings(); + void saveSettings(); + + signals: + void modified(); + + private: + KComboBox *mFormattedNameCombo; + NamePartWidget *mPrefix; + NamePartWidget *mInclusion; + NamePartWidget *mSuffix; +}; + +#endif diff --git a/kaddressbook/kcmconfigs/extensionconfigdialog.cpp b/kaddressbook/kcmconfigs/extensionconfigdialog.cpp new file mode 100644 index 0000000..e87b000 --- a/dev/null +++ b/kaddressbook/kcmconfigs/extensionconfigdialog.cpp @@ -0,0 +1,59 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> + +#include <klocale.h> + +#include "configurewidget.h" + +#include "extensionconfigdialog.h" + +ExtensionConfigDialog::ExtensionConfigDialog( ExtensionFactory *factory, KConfig *config, + QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Extension Settings" ), Ok | Cancel, Ok, parent, + name, true, true ), mWidget( 0 ), mConfig( config ) +{ + QFrame *page = plainPage(); + QGridLayout *layout = new QGridLayout( page, 1, 1, marginHint(), spacingHint() ); + + mWidget = factory->configureWidget( page, "ExtensionConfigWidget" ); + layout->addWidget( mWidget, 0, 0 ); + + mWidget->restoreSettings( mConfig ); +} + +ExtensionConfigDialog::~ExtensionConfigDialog() +{ +} + +void ExtensionConfigDialog::slotOk() +{ + mWidget->saveSettings( mConfig ); + + KDialogBase::slotOk(); +} + +#ifndef KAB_EMBEDDED +#include "extensionconfigdialog.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/kcmconfigs/extensionconfigdialog.h b/kaddressbook/kcmconfigs/extensionconfigdialog.h new file mode 100644 index 0000000..5a92034 --- a/dev/null +++ b/kaddressbook/kcmconfigs/extensionconfigdialog.h @@ -0,0 +1,48 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef EXTENSIONCONFIGDIALOG_H +#define EXTENSIONCONFIGDIALOG_H + +#include <kdialogbase.h> + +#include "extensionwidget.h" + +class ExtensionConfigDialog : public KDialogBase +{ + Q_OBJECT + + public: + ExtensionConfigDialog( ExtensionFactory *factory, KConfig *config, + QWidget *parent, const char *name = 0 ); + ~ExtensionConfigDialog(); + + protected slots: + void slotOk(); + + private: + ConfigureWidget *mWidget; + KConfig *mConfig; +}; + +#endif diff --git a/kaddressbook/kcmconfigs/kabconfigwidget.cpp b/kaddressbook/kcmconfigs/kabconfigwidget.cpp new file mode 100644 index 0000000..7b3e5c6 --- a/dev/null +++ b/kaddressbook/kcmconfigs/kabconfigwidget.cpp @@ -0,0 +1,357 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qcheckbox.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qtabwidget.h> + +#include <kconfig.h> +#include <kdebug.h> +#include <kdialog.h> +#include <klistview.h> +#include <klocale.h> +#include <kglobal.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> + +#ifndef KAB_EMBEDDED +#include <ktrader.h> +#else // KAB_EMBEDDED +#include <mergewidget.h> +#include <distributionlistwidget.h> +#endif // KAB_EMBEDDED + +#include "addresseewidget.h" +#include "extensionconfigdialog.h" +#include "extensionwidget.h" +#include "kabprefs.h" + +#include "kabconfigwidget.h" + +class ExtensionItem : public QCheckListItem +{ + public: + +#ifndef KAB_EMBEDDED + ExtensionItem( QListView *parent, const QString &text ); + void setService( const KService::Ptr &ptr ); +#else //KAB_EMBEDDED + ExtensionItem( QListView *parent, const QString &text, const QString &name, const QString &comment ); + void setFactory( ExtensionFactory* fac ); +#endif //KAB_EMBEDDED + + bool configWidgetAvailable() const; + ExtensionFactory *factory() const; + + virtual QString text( int column ) const; + + private: +#ifndef KAB_EMBEDDED + KService::Ptr mPtr; +#else //KAB_EMBEDDED + ExtensionFactory* mFactory; + QString mName; + QString mComment; + +#endif //KAB_EMBEDDED + +}; + +KABConfigWidget::KABConfigWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QVBoxLayout *topLayout = new QVBoxLayout( this, 0, + KDialog::spacingHint() ); + + QTabWidget *tabWidget = new QTabWidget( this ); + topLayout->addWidget( tabWidget ); + + // General page + QWidget *generalPage = new QWidget( this ); + QVBoxLayout *layout = new QVBoxLayout( generalPage, KDialog::marginHint(), + KDialog::spacingHint() ); + + QGroupBox *groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "General" ), generalPage ); + QVBoxLayout *boxLayout = new QVBoxLayout( groupBox->layout() ); + boxLayout->setAlignment( Qt::AlignTop ); + + mViewsSingleClickBox = new QCheckBox( i18n( "Honor KDE single click" ), groupBox, "msingle" ); + boxLayout->addWidget( mViewsSingleClickBox ); + + mNameParsing = new QCheckBox( i18n( "Automatic name parsing for new addressees" ), groupBox, "mparse" ); + boxLayout->addWidget( mNameParsing ); + + layout->addWidget( groupBox ); + + groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Extensions" ), generalPage ); + boxLayout = new QVBoxLayout( groupBox->layout() ); + boxLayout->setAlignment( Qt::AlignTop ); + + mExtensionView = new KListView( groupBox ); + mExtensionView->setAllColumnsShowFocus( true ); + mExtensionView->addColumn( i18n( "Name" ) ); + mExtensionView->addColumn( i18n( "Description" ) ); + mExtensionView->setMaximumHeight(80); + + boxLayout->addWidget( mExtensionView ); + + mConfigureButton = new QPushButton( i18n( "Configure..." ), groupBox ); + mConfigureButton->setEnabled( false ); + boxLayout->addWidget( mConfigureButton ); + + layout->addWidget( groupBox ); + + connect( mNameParsing, SIGNAL( toggled( bool ) ), this, SLOT( modified() ) ); + connect( mViewsSingleClickBox, SIGNAL( toggled( bool ) ), this, SLOT( modified() ) ); + connect( mExtensionView, SIGNAL( selectionChanged( QListViewItem* ) ), + SLOT( selectionChanged( QListViewItem* ) ) ); + connect( mExtensionView, SIGNAL( clicked( QListViewItem* ) ), + SLOT( itemClicked( QListViewItem* ) ) ); + connect( mConfigureButton, SIGNAL( clicked() ), + SLOT( configureExtension() ) ); + + tabWidget->addTab( generalPage, i18n( "General" ) ); + + // Addressee page + mAddresseeWidget = new AddresseeWidget( this ); + tabWidget->addTab( mAddresseeWidget, i18n( "Contact" ) ); + connect( mAddresseeWidget, SIGNAL( modified() ), SLOT( modified() ) ); +} + +void KABConfigWidget::restoreSettings() +{ + bool blocked = signalsBlocked(); + blockSignals( true ); + + mNameParsing->setChecked( KABPrefs::instance()->mAutomaticNameParsing ); + mViewsSingleClickBox->setChecked( KABPrefs::instance()->mHonorSingleClick ); + mAddresseeWidget->restoreSettings(); + + restoreExtensionSettings(); + + blockSignals( blocked ); + + emit changed( false ); +} + +void KABConfigWidget::saveSettings() +{ + KABPrefs::instance()->mAutomaticNameParsing = mNameParsing->isChecked(); + KABPrefs::instance()->mHonorSingleClick = mViewsSingleClickBox->isChecked(); + mAddresseeWidget->saveSettings(); + + saveExtensionSettings(); + KABPrefs::instance()->writeConfig(); + + emit changed( false ); +} + +void KABConfigWidget::defaults() +{ + mNameParsing->setChecked( true ); + mViewsSingleClickBox->setChecked( false ); + + emit changed( true ); +} + +void KABConfigWidget::modified() +{ + emit changed( true ); +} + +void KABConfigWidget::restoreExtensionSettings() +{ + QStringList activeExtensions = KABPrefs::instance()->mActiveExtensions; + + mExtensionView->clear(); + +#ifndef KAB_EMBEDDED + KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/Extension" ); + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + if ( !(*it)->hasServiceType( "KAddressBook/Extension" ) ) + continue; + + ExtensionItem *item = new ExtensionItem( mExtensionView, (*it)->name() ); + item->setService( *it ); + if ( activeExtensions.contains( item->factory()->identifier() ) ) + item->setOn( true ); + } +#else //KAB_EMBEDDED + ExtensionFactory *extensionFactory = new MergeFactory(); + + ExtensionItem *item = new ExtensionItem( mExtensionView, "Merge", "Merge", "Merge contacts"); + + item->setFactory( extensionFactory ); + if ( activeExtensions.contains( extensionFactory->identifier() ) ) + item->setOn( true ); + + + + extensionFactory = new DistributionListFactory(); + + item = new ExtensionItem( mExtensionView, "Distribution List", "Distribution List", "Manage Distribution Lists"); + + item->setFactory( extensionFactory ); + if ( activeExtensions.contains( extensionFactory->identifier() ) ) + item->setOn( true ); + + +#endif //KAB_EMBEDDED + +} + +void KABConfigWidget::saveExtensionSettings() +{ + QStringList activeExtensions; + + QPtrList<QListViewItem> list; + QListViewItemIterator it( mExtensionView ); + while ( it.current() ) { + ExtensionItem *item = static_cast<ExtensionItem*>( it.current() ); + if ( item ) { + if ( item->isOn() ) + activeExtensions.append( item->factory()->identifier() ); + } + ++it; + } + + KABPrefs::instance()->mActiveExtensions = activeExtensions; +} + +void KABConfigWidget::configureExtension() +{ + ExtensionItem *item = static_cast<ExtensionItem*>( mExtensionView->currentItem() ); + if ( !item ) + return; + +#ifndef KAB_EMBEDDED + KConfig config( "kaddressbookrc" ); +#else //KAB_EMBEDDED + KConfig config( locateLocal("config", "kaddressbookrc") ); +#endif //KAB_EMBEDDED + config.setGroup( QString( "Extensions_%1" ).arg( item->factory()->identifier() ) ); + + ExtensionConfigDialog dlg( item->factory(), &config, this ); + dlg.exec(); + + config.sync(); +} + +void KABConfigWidget::selectionChanged( QListViewItem *i ) +{ + ExtensionItem *item = static_cast<ExtensionItem*>( i ); + if ( !item ) + return; + + mConfigureButton->setEnabled( item->configWidgetAvailable() ); +} + +void KABConfigWidget::itemClicked( QListViewItem *item ) +{ + if ( item != 0 ) + modified(); +} + +#ifndef KAB_EMBEDDED +ExtensionItem::ExtensionItem( QListView *parent, const QString &text ) + : QCheckListItem( parent, text, CheckBox ) +{ +} + +void ExtensionItem::setService( const KService::Ptr &ptr ) +{ + mPtr = ptr; +} +#else //KAB_EMBEDDED +ExtensionItem::ExtensionItem( QListView *parent, const QString &text, const QString &name, const QString &comment ) + : QCheckListItem( parent, text, CheckBox ) +{ + mName = name; + mComment = comment; +} + + +void ExtensionItem::setFactory( ExtensionFactory* fac ) +{ + mFactory = fac; +} +#endif //KAB_EMBEDDED + +bool ExtensionItem::configWidgetAvailable() const +{ +#ifndef KAB_EMBEDDED + KLibFactory *factory = KLibLoader::self()->factory( mPtr->library().latin1() ); + if ( !factory ) + return false; + + ExtensionFactory *extensionFactory = static_cast<ExtensionFactory*>( factory ); + if ( !extensionFactory ) + return false; + + return extensionFactory->configureWidgetAvailable(); +#else //KAB_EMBEDDED + return mFactory->configureWidgetAvailable(); +#endif //KAB_EMBEDDED + +} + +ExtensionFactory *ExtensionItem::factory() const +{ +#ifndef KAB_EMBEDDED + KLibFactory *factory = KLibLoader::self()->factory( mPtr->library().latin1() ); + if ( !factory ) + return 0; + + return static_cast<ExtensionFactory*>( factory ); +#else //KAB_EMBEDDED + return mFactory; +#endif //KAB_EMBEDDED +} + +QString ExtensionItem::text( int column ) const +{ +#ifndef KAB_EMBEDDED + if ( column == 0 ) + return mPtr->name(); + else if ( column == 1 ) + return mPtr->comment(); + else + return QString::null; +#else //KAB_EMBEDDED + if ( column == 0 ) + return mName; + else if ( column == 1 ) + return mComment; + else + return QString::null; +#endif //KAB_EMBEDDED +} + +#ifndef KAB_EMBEDDED +#include "kabconfigwidget.moc" +#endif //KAB_EMBEDDED + diff --git a/kaddressbook/kcmconfigs/kabconfigwidget.h b/kaddressbook/kcmconfigs/kabconfigwidget.h new file mode 100644 index 0000000..0f36d9e --- a/dev/null +++ b/kaddressbook/kcmconfigs/kabconfigwidget.h @@ -0,0 +1,72 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KABCONFIGWIDGET_H +#define KABCONFIGWIDGET_H + +#include <qwidget.h> + +class QCheckBox; +class QListViewItem; +class QPushButton; + +class KListView; + +class AddresseeWidget; + +class KABConfigWidget : public QWidget +{ + Q_OBJECT + + public: + KABConfigWidget( QWidget *parent, const char *name = 0 ); + + void restoreSettings(); + void saveSettings(); + void defaults(); + + signals: + void changed( bool ); + + public slots: + void modified(); + + private slots: + void configureExtension(); + void selectionChanged( QListViewItem* ); + void itemClicked( QListViewItem* ); + + private: + void restoreExtensionSettings(); + void saveExtensionSettings(); + + KListView *mExtensionView; + + QCheckBox *mNameParsing; + QCheckBox *mViewsSingleClickBox; + QPushButton *mConfigureButton; + + AddresseeWidget *mAddresseeWidget; +}; + +#endif diff --git a/kaddressbook/kcmconfigs/kcmkabconfig.cpp b/kaddressbook/kcmconfigs/kcmkabconfig.cpp new file mode 100644 index 0000000..791a940 --- a/dev/null +++ b/kaddressbook/kcmconfigs/kcmkabconfig.cpp @@ -0,0 +1,86 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> + +#ifndef KAB_EMBEDDED +#include <kaboutdata.h> +#endif //KAB_EMBEDDED +#include <kdebug.h> +#include <klocale.h> + +#include "kabconfigwidget.h" + +#include "kcmkabconfig.h" + +extern "C" +{ + KCModule *create_kabconfig( QWidget *parent, const char * ) { + return new KCMKabConfig( parent, "kcmkabconfig" ); + } +} + +KCMKabConfig::KCMKabConfig( QWidget *parent, const char *name ) + : KCModule( parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + mConfigWidget = new KABConfigWidget( this, "mConfigWidget" ); + layout->addWidget( mConfigWidget ); + + connect( mConfigWidget, SIGNAL( changed( bool ) ), SIGNAL( changed( bool ) ) ); + load(); +} + +void KCMKabConfig::load() +{ + mConfigWidget->restoreSettings(); +} + +void KCMKabConfig::save() +{ + mConfigWidget->saveSettings(); +} + +void KCMKabConfig::defaults() +{ + mConfigWidget->defaults(); +} + +#ifndef KAB_EMBEDDED +const KAboutData* KCMKabConfig::aboutData() const +{ + KAboutData *about = new KAboutData( I18N_NOOP( "kcmkabconfig" ), + I18N_NOOP( "KAddressBook Configure Dialog" ), + 0, 0, KAboutData::License_GPL, + I18N_NOOP( "(c), 2003 Tobias Koenig" ) ); + + about->addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" ); + + return about; + +} +#endif //KAB_EMBEDDED + +#ifndef KAB_EMBEDDED +#include "kcmkabconfig.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/kcmconfigs/kcmkabconfig.h b/kaddressbook/kcmconfigs/kcmkabconfig.h new file mode 100644 index 0000000..be345b8 --- a/dev/null +++ b/kaddressbook/kcmconfigs/kcmkabconfig.h @@ -0,0 +1,53 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KCMKABCONFIG_H +#define KCMKABCONFIG_H + +#include <kcmodule.h> + +class KABConfigWidget; + +#ifndef KAB_EMBEDDED +class KAboutData; +#endif //KAB_EMBEDDED + +class KCMKabConfig : public KCModule +{ + Q_OBJECT + + public: + KCMKabConfig( QWidget *parent = 0, const char *name = 0 ); + + virtual void load(); + virtual void save(); + virtual void defaults(); +#ifndef KAB_EMBEDDED + virtual const KAboutData* aboutData() const; +#endif //KAB_EMBEDDED + + private: + KABConfigWidget *mConfigWidget; +}; + +#endif diff --git a/kaddressbook/keywidget.cpp b/kaddressbook/keywidget.cpp new file mode 100644 index 0000000..c117d34 --- a/dev/null +++ b/kaddressbook/keywidget.cpp @@ -0,0 +1,277 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qfile.h> + +#include <qinputdialog.h> + +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> + +#ifndef KAB_EMBEDDED +#include <kaccelmanager.h> +#include <kio/netaccess.h> +#include <kmessagebox.h> +#else //KAB_EMBEDDED +#include <qmap.h> +#include <qmessagebox.h> +#include <qtextstream.h> +#include <kurl.h> +#endif //KAB_EMBEDDED + +#include <kapplication.h> +#include <kcombobox.h> +#include <kdialog.h> +#include <kfiledialog.h> +#include <klocale.h> +#include <ktempfile.h> + +#include "keywidget.h" + +KeyWidget::KeyWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QGridLayout *layout = new QGridLayout( this, 2, 2, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Keys:" ), this ); + layout->addWidget( label, 0, 0 ); + + mKeyCombo = new KComboBox( this ); + layout->addWidget( mKeyCombo, 0, 1 ); + + mAddButton = new QPushButton( i18n( "Add" ), this ); + layout->addWidget( mAddButton, 1, 0 ); + + mRemoveButton = new QPushButton( i18n( "Remove" ), this ); + mRemoveButton->setEnabled( false ); + layout->addWidget( mRemoveButton, 1, 1 ); + + mExportButton = new QPushButton( i18n( "Export" ), this ); + mExportButton->setEnabled( false ); + layout->addMultiCellWidget( mExportButton, 2, 2, 0, 1 ); + + connect( mAddButton, SIGNAL( clicked() ), SLOT( addKey() ) ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeKey() ) ); + connect( mExportButton, SIGNAL( clicked() ), SLOT( exportKey() ) ); +} + +KeyWidget::~KeyWidget() +{ +} + +void KeyWidget::setKeys( const KABC::Key::List &list ) +{ + mKeyList = list; + + updateKeyCombo(); +} + +KABC::Key::List KeyWidget::keys() const +{ + return mKeyList; +} + +void KeyWidget::addKey() +{ + QMap<QString, int> keyMap; + QStringList keyTypeNames; + QStringList existingKeyTypes; + + KABC::Key::List::Iterator listIt; + for ( listIt = mKeyList.begin(); listIt != mKeyList.end(); ++listIt ) { + if ( (*listIt).type() != KABC::Key::Custom ) + existingKeyTypes.append( KABC::Key::typeLabel( (*listIt).type() ) ); + } + + KABC::Key::TypeList typeList = KABC::Key::typeList(); + KABC::Key::TypeList::Iterator it; + for ( it = typeList.begin(); it != typeList.end(); ++it ) { + if ( (*it) != KABC::Key::Custom && + !existingKeyTypes.contains( KABC::Key::typeLabel( *it ) ) ) { + keyMap.insert( KABC::Key::typeLabel( *it ), *it ); + keyTypeNames.append( KABC::Key::typeLabel( *it ) ); + } + } + + bool ok; + QString name = QInputDialog::getItem( i18n( "Key type" ), i18n( "Select the key type." ), keyTypeNames, 0, true, &ok ); + + + + if ( !ok || name.isEmpty() ) + return; + + int type = keyMap[ name ]; + if ( !keyTypeNames.contains( name ) ) + type = KABC::Key::Custom; + +#ifndef KAB_EMBEDDED + KURL url = KFileDialog::getOpenURL(); + + if ( url.isEmpty() ) + return; + + QString tmpFile; + if ( KIO::NetAccess::download( url, tmpFile ) ) { + QFile file( tmpFile ); + if ( !file.open( IO_ReadOnly ) ) { + QString text( i18n( "<qt>Unable to open file <b>%1</b>.</qt>" ) ); + KMessageBox::error( this, text.arg( url.url() ) ); + return; + } + + +#else //KAB_EMBEDDED + QString keyfile = KFileDialog::getOpenFileName( "huhu", + "Select Key", this ); + + if ( keyfile.isEmpty() ) + return; + + { + QFile file( keyfile ); + if ( !file.open( IO_ReadOnly ) ) { + QString text( i18n( "<qt>Unable to open file <b>%1</b>.</qt>" ) ); + QString caption( i18n( "Error" ) ); + QMessageBox::critical( this, caption, text.arg( keyfile ) ); + return; + } + +#endif //KAB_EMBEDDED + + + + QTextStream s( &file ); + QString data; + + s.setEncoding( QTextStream::UnicodeUTF8 ); + s >> data; + file.close(); + + KABC::Key key( data, type ); + if ( type == KABC::Key::Custom ) + key.setCustomTypeString( name ); + mKeyList.append( key ); + + emit changed(); + +#ifndef KAB_EMBEDDED + KIO::NetAccess::removeTempFile( tmpFile ); +#endif //KAB_EMBEDDED + + } + + updateKeyCombo(); +} + +void KeyWidget::removeKey() +{ + int pos = mKeyCombo->currentItem(); + if ( pos == -1 ) + return; + + QString type = mKeyCombo->currentText(); + QString text = i18n( "<qt>Do you really want to remove the key <b>%1</b>?</qt>" ); + + +#ifndef KAB_EMBEDDED + if ( KMessageBox::questionYesNo( this, text.arg( type ) ) == KMessageBox::No ) + return; +#else //KAB_EMBEDDED + QString caption = i18n( "Confirm Delete" ); + if (QMessageBox::information( this, caption, + text.arg( type ), + i18n("Yes!"), i18n("No"), 0, 0 ) == 1) + return; +#endif //KAB_EMBEDDED + + mKeyList.remove( mKeyList.at( pos ) ); + emit changed(); + + updateKeyCombo(); +} + +void KeyWidget::exportKey() +{ + KABC::Key key = (*mKeyList.at( mKeyCombo->currentItem() ) ); + +#ifndef KAB_EMBEDDED + KURL url = KFileDialog::getSaveURL(); + + KTempFile tempFile; + QTextStream *s = tempFile.textStream(); + s->setEncoding( QTextStream::UnicodeUTF8 ); + (*s) << key.textData(); + tempFile.close(); + + KIO::NetAccess::upload( tempFile.name(), url, kapp->mainWidget() ); +#else //KAB_EMBEDDED + QString keyfile = KFileDialog::getSaveFileName( "huhu", + "Save Key", this ); + + if ( keyfile.isEmpty() ) + return; + + QFile file( keyfile ); + if ( !file.open( IO_ReadWrite ) ) { + QString text( i18n( "<qt>Unable to open file <b>%1</b>.</qt>" ) ); + QString caption( i18n( "Error" ) ); + QMessageBox::critical( this, caption, text.arg( keyfile ) ); + return; + } + + QTextStream s( &file ); + s.setEncoding( QTextStream::UnicodeUTF8 ); + s << key.textData(); + file.close(); + + +#endif //KAB_EMBEDDED + +} + +void KeyWidget::updateKeyCombo() +{ + int pos = mKeyCombo->currentItem(); + mKeyCombo->clear(); + + KABC::Key::List::Iterator it; + for ( it = mKeyList.begin(); it != mKeyList.end(); ++it ) { + if ( (*it).type() == KABC::Key::Custom ) + mKeyCombo->insertItem( (*it).customTypeString() ); + else + mKeyCombo->insertItem( KABC::Key::typeLabel( (*it).type() ) ); + } + + mKeyCombo->setCurrentItem( pos ); + + bool state = ( mKeyList.count() != 0 ); + mRemoveButton->setEnabled( state ); + mExportButton->setEnabled( state ); +} + +#ifndef KAB_EMBEDDED +#include "keywidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/keywidget.h b/kaddressbook/keywidget.h new file mode 100644 index 0000000..50bac53 --- a/dev/null +++ b/kaddressbook/keywidget.h @@ -0,0 +1,65 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KEYWIDGET_H +#define KEYWIDGET_H + +#include <qwidget.h> +#include <kabc/key.h> + +class KComboBox; + +class QPushButton; + +class KeyWidget : public QWidget +{ + Q_OBJECT + + public: + KeyWidget( QWidget *parent, const char *name = 0 ); + ~KeyWidget(); + + void setKeys( const KABC::Key::List &list ); + KABC::Key::List keys() const; + + signals: + void changed(); + + private slots: + void addKey(); + void removeKey(); + void exportKey(); + + private: + void updateKeyCombo(); + + KComboBox *mKeyCombo; + + QPushButton *mAddButton; + QPushButton *mRemoveButton; + QPushButton *mExportButton; + + KABC::Key::List mKeyList; +}; + +#endif diff --git a/kaddressbook/mainembedded.cpp b/kaddressbook/mainembedded.cpp new file mode 100644 index 0000000..ffa37a5 --- a/dev/null +++ b/kaddressbook/mainembedded.cpp @@ -0,0 +1,208 @@ +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#include <qpe/global.h> +#include <stdlib.h> +#else +#include <qapplication.h> +#include <qwindowsstyle.h> +#include <qplatinumstyle.h> +#include <qmainwindow.h> +#endif + +#include <kstandarddirs.h> +#include <kglobal.h> +#include <stdio.h> +#include <qdir.h> +#include "kaddressbookmain.h" + +int main( int argc, char **argv ) +{ +#ifndef DESKTOP_VERSION + QPEApplication a( argc, argv ); + a.setKeepRunning (); +#else + QApplication a( argc, argv ); + QApplication::setStyle( new QPlatinumStyle ()); +#endif + + bool exitHelp = false; + if ( argc > 1 ) { + QString command = argv[1]; + if ( command == "-help" ){ + printf("KA/E command line commands:\n"); + printf(" no command: Start KA/E in usual way\n"); + printf(" -help: This output\n"); + printf(" KA/E is exiting now. Bye!\n"); + exitHelp = true; + } + } + if ( ! exitHelp ) { + + KGlobal::setAppName( "kaddressbook" ); +#ifndef DESKTOP_VERSION + KStandardDirs::setAppDir( Global::applicationFileName( "kaddressbook", "" ) ); + KGlobal::iconLoader()->setIconPath(QString(getenv("QPEDIR"))+"/pics/kdepim/kaddressbook/icons16/"); +#else + QString fileName ; +#ifndef _WIN32_ + fileName = qApp->applicationDirPath () + "/kdepim/kaddressbook/icons16/"; +#else + fileName = qApp->applicationDirPath () + "\\kdepim\\kaddressbook\\icons16\\"; +#endif + KGlobal::iconLoader()->setIconPath(fileName); + QString appdir = QDir::homeDirPath(); + if ( appdir.right(1) == "\\" || appdir.right(1) == "/" ) + appdir += "kaddressbook"; + else + appdir += "/kaddressbook"; + KStandardDirs::setAppDir( QDir::convertSeparators( appdir )); + // qDebug(" %s ",KStandardDirs::appDir().latin1() ); +#endif // desktop + QDir app_dir; + if ( !app_dir.exists(KStandardDirs::appDir()) ) + app_dir.mkdir (KStandardDirs::appDir()); + + KAddressBookMain* m = new KAddressBookMain(); +//US MainWindow m; +//US QObject::connect( &a, SIGNAL (appMessage ( const QCString &, const QByteArray & )),&m, SLOT(recieve( const QCString&, const QByteArray& ))); + +#ifndef DESKTOP_VERSION + a.showMainWidget(m ); + m->showFullScreen(); + int min = 20; + if ( QApplication::desktop()->width() > 320 ) + min += 20; + m->setGeometry( 0,0,QApplication::desktop()->width(), QApplication::desktop()->height() - min ); + +#else + a.setMainWidget(m ); + m->show(); + //m->resize( 640, 480 ); +#endif + a.exec(); + + } + qDebug("KA: Bye! "); +} + +/* +#include <stdlib.h> + +#include <qstring.h> + +#include <kabc/stdaddressbook.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kcrash.h> +#include <kdebug.h> +#include <klocale.h> +#include <kstartupinfo.h> +#include <kuniqueapplication.h> +#include <kwin.h> + +#include "kaddressbookmain.h" +#include "kabcore.h" + +extern "C" { + +void crashHandler( int ) +{ + KABC::StdAddressBook::handleCrash(); + ::exit( 0 ); +} + +} + +class KAddressBookApp : public KUniqueApplication { + public: + KAddressBookApp() : mMainWin( 0 ) {} + ~KAddressBookApp() {} + + int newInstance(); + + private: + KAddressBookMain *mMainWin; +}; + +int KAddressBookApp::newInstance() +{ + if ( isRestored() ) { + // There can only be one main window + if ( KMainWindow::canBeRestored( 1 ) ) { + mMainWin = new KAddressBookMain; + mMainWin->show(); + mMainWin->restore( 1 ); + } + } else { + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + QCString addrStr = args->getOption( "addr" ); + QCString uidStr = args->getOption( "uid" ); + QString addr; + QString uid; + if ( !addrStr.isEmpty() ) + addr = QString::fromLocal8Bit( addrStr ); + if ( !uidStr.isEmpty() ) + uid = QString::fromLocal8Bit( uidStr ); + + + if ( args->isSet( "editor-only" ) ) { + if ( !mMainWin ) + mMainWin = new KAddressBookMain; + KStartupInfo::appStarted(); + mMainWin->hide(); + } else { + if ( mMainWin ) { + mMainWin->show(); + KWin::setActiveWindow( mMainWin->winId() ); + } else { + mMainWin = new KAddressBookMain; + mMainWin->show(); + } + } + // Can not see why anyone would pass both a uid and an email address, so I'll leave it that two contact editors will show if they do + if ( !addr.isEmpty() ) + mMainWin->addEmail( addr ); + + if ( !uid.isEmpty() ) + mMainWin->showContactEditor( uid ); + if ( args->isSet( "new-contact" ) ) { + mMainWin->newContact(); + } + } + + KCrash::setEmergencySaveFunction( crashHandler ); + + return 0; +} + +// the dummy argument is required, because KMail apparently sends an empty +// argument. +static KCmdLineOptions kmoptions[] = +{ + { "a", 0 , 0 }, + { "addr <email>", I18N_NOOP( "Shows contact editor with given email address" ), 0 }, + { "uid <uid>", I18N_NOOP( "Shows contact editor with given uid" ), 0 }, + { "editor-only", I18N_NOOP( "Launches in editor only mode" ), 0 }, + { "new-contact", I18N_NOOP( "Launches editor for the new contact" ), 0 }, + { "+[argument]", I18N_NOOP( "dummy argument" ), 0}, + { 0, 0, 0} +}; + +int main( int argc, char *argv[] ) +{ + KLocale::setMainCatalogue( "kaddressbook" ); + + KCmdLineArgs::init( argc, argv, KABCore::createAboutData() ); + KCmdLineArgs::addCmdLineOptions( kmoptions ); + KUniqueApplication::addCmdLineOptions(); + + if ( !KAddressBookApp::start() ) + exit( 0 ); + + KAddressBookApp app; + KGlobal::locale()->insertCatalogue( "libkdepim" ); + + return app.exec(); +} +*/ diff --git a/kaddressbook/nameeditdialog.cpp b/kaddressbook/nameeditdialog.cpp new file mode 100644 index 0000000..fb7eb22 --- a/dev/null +++ b/kaddressbook/nameeditdialog.cpp @@ -0,0 +1,296 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> +#include <qlabel.h> +#include <qlistbox.h> +#include <qlistview.h> +#include <qtooltip.h> +#include <qpushbutton.h> +#include <qcheckbox.h> +#include <qstring.h> + +#ifndef KAB_EMBEDDED +#include <kaccelmanager.h> +#else //KAB_EMBEDDED +#include <kstandarddirs.h> +#endif //KAB_EMBEDDED + +#include <kapplication.h> +#include <kbuttonbox.h> +#include <kconfig.h> +#include <klineedit.h> +#include <klistview.h> +#include <kcombobox.h> +#include <klocale.h> +#include <kglobal.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kmessagebox.h> + +#include "nameeditdialog.h" + +NameEditDialog::NameEditDialog( const KABC::Addressee &addr, int type, + QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Edit Contact Name" ), Help | Ok | Cancel, + Ok, parent, name, true ) +{ + + QWidget *page = plainPage(); + QGridLayout *layout = new QGridLayout( page, 5, 3 ); + layout->setSpacing( spacingHint() ); + layout->addColSpacing( 2, 100 ); + QLabel *label; + + label = new QLabel( i18n( "Honorific prefixes:" ), page ); + layout->addWidget( label, 0, 0 ); + mPrefixCombo = new KComboBox( page ); + mPrefixCombo->setDuplicatesEnabled( false ); + mPrefixCombo->setEditable( true ); + label->setBuddy( mPrefixCombo ); + layout->addMultiCellWidget( mPrefixCombo, 0, 0, 1, 2 ); + + label = new QLabel( i18n( "Given name:" ), page ); + layout->addWidget( label, 1, 0 ); + mGivenNameEdit = new KLineEdit( page ); + label->setBuddy( mGivenNameEdit ); + layout->addMultiCellWidget( mGivenNameEdit, 1, 1, 1, 2 ); + + label = new QLabel( i18n( "Additional names:" ), page ); + layout->addWidget( label, 2, 0 ); + mAdditionalNameEdit = new KLineEdit( page ); + label->setBuddy( mAdditionalNameEdit ); + layout->addMultiCellWidget( mAdditionalNameEdit, 2, 2, 1, 2 ); + + label = new QLabel( i18n( "Family names:" ), page ); + layout->addWidget( label, 3, 0 ); + mFamilyNameEdit = new KLineEdit( page ); + label->setBuddy( mFamilyNameEdit ); + layout->addMultiCellWidget( mFamilyNameEdit, 3, 3, 1, 2 ); + + label = new QLabel( i18n( "Honorific suffixes:" ), page ); + layout->addWidget( label, 4, 0 ); + mSuffixCombo = new KComboBox( page ); + mSuffixCombo->setDuplicatesEnabled( false ); + mSuffixCombo->setEditable( true ); + label->setBuddy( mSuffixCombo ); + layout->addMultiCellWidget( mSuffixCombo, 4, 4, 1, 2 ); + + mFormattedNameCombo = new KComboBox( page ); + mFormattedNameCombo->setMaximumWidth(100); + + layout->addMultiCellWidget( mFormattedNameCombo, 5, 5, 0, 0 ); + connect( mFormattedNameCombo, SIGNAL( activated( int ) ), SLOT( typeChanged( int ) ) ); + + mFormattedNameEdit = new KLineEdit( page ); + mFormattedNameEdit->setEnabled( type == CustomName ); + layout->addMultiCellWidget( mFormattedNameEdit, 5, 5, 1, 2 ); + + mParseBox = new QCheckBox( i18n( "Parse name automatically" ), page ); + connect( mParseBox, SIGNAL( toggled(bool) ), SLOT( parseBoxChanged(bool) ) ); + connect( mParseBox, SIGNAL( toggled(bool) ), SLOT( modified() ) ); + layout->addMultiCellWidget( mParseBox, 6, 6, 0, 1 ); + + // Fill in the values + mFamilyNameEdit->setText( addr.familyName() ); + mGivenNameEdit->setText( addr.givenName() ); + mAdditionalNameEdit->setText( addr.additionalName() ); + mFormattedNameEdit->setText( addr.formattedName() ); + + // Prefix and suffix combos +//US KConfig config( "kabcrc" ); + KConfig config( locateLocal("config", "kabcrc") ); + config.setGroup( "General" ); + + QStringList sTitle; + sTitle += i18n( "Dr." ); + sTitle += i18n( "Miss" ); + sTitle += i18n( "Mr." ); + sTitle += i18n( "Mrs." ); + sTitle += i18n( "Ms." ); + sTitle += i18n( "Prof." ); + sTitle += config.readListEntry( "Prefixes" ); + sTitle.sort(); + + QStringList sSuffix; + sSuffix += i18n( "I" ); + sSuffix += i18n( "II" ); + sSuffix += i18n( "III" ); + sSuffix += i18n( "Jr." ); + sSuffix += i18n( "Sr." ); + sSuffix += config.readListEntry( "Suffixes" ); + sSuffix.sort(); + + mPrefixCombo->insertStringList( sTitle ); + mSuffixCombo->insertStringList( sSuffix ); + +#ifndef KAB_EMBEDDED + mPrefixCombo->setCurrentText( addr.prefix() ); + mSuffixCombo->setCurrentText( addr.suffix() ); +#else //KAB_EMBEDDED + mPrefixCombo->setEditText( addr.prefix() ); + mSuffixCombo->setEditText( addr.suffix() ); +#endif //KAB_EMBEDDED + + AddresseeConfig::instance()->setUid( addr.uid() ); + mParseBox->setChecked( AddresseeConfig::instance()->automaticNameParsing() ); + +#ifndef KAB_EMBEDDED + KAcceleratorManager::manage( this ); +#endif //KAB_EMBEDDED + + connect( mPrefixCombo, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mPrefixCombo, SIGNAL( textChanged( const QString& ) ), SLOT( updateTypeCombo() ) ); + connect( mGivenNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mGivenNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( updateTypeCombo() ) ); + connect( mAdditionalNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mAdditionalNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( updateTypeCombo() ) ); + connect( mFamilyNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mFamilyNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( updateTypeCombo() ) ); + connect( mSuffixCombo, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + connect( mSuffixCombo, SIGNAL( textChanged( const QString& ) ), SLOT( updateTypeCombo() ) ); + connect( mFormattedNameCombo, SIGNAL( activated( int ) ), SLOT( modified() ) ); + connect( mFormattedNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( modified() ) ); + + updateTypeCombo(); + mFormattedNameCombo->setCurrentItem( type ); + +#ifdef KAB_EMBEDDED + resize( KMIN(KGlobal::getDesktopWidth()-10, 490), KMIN(KGlobal::getDesktopHeight()-50, 300)); +#endif //KAB_EMBEDDED + + mChanged = false; +} + +NameEditDialog::~NameEditDialog() +{ +} + +QString NameEditDialog::familyName() const +{ + return mFamilyNameEdit->text(); +} + +QString NameEditDialog::givenName() const +{ + return mGivenNameEdit->text(); +} + +QString NameEditDialog::prefix() const +{ + return mPrefixCombo->currentText(); +} + +QString NameEditDialog::suffix() const +{ + return mSuffixCombo->currentText(); +} + +QString NameEditDialog::additionalName() const +{ + return mAdditionalNameEdit->text(); +} + +QString NameEditDialog::customFormattedName() const +{ + return mFormattedNameEdit->text(); +} + +int NameEditDialog::formattedNameType() const +{ + return mFormattedNameCombo->currentItem(); +} + +bool NameEditDialog::changed() const +{ + return mChanged; +} + +QString NameEditDialog::formattedName( const KABC::Addressee &addr, int type ) +{ + switch ( type ) { + case SimpleName: + return addr.givenName() + " " + addr.familyName(); + break; + case FullName: + return addr.prefix() + " " + addr.givenName() + " " + + addr.additionalName() + " " + addr.familyName() + " " + + addr.suffix(); + break; + case ReverseName: + return addr.familyName() + ", " + addr.givenName(); + break; + default: + return ""; + break; + } +} + +void NameEditDialog::parseBoxChanged( bool value ) +{ + //AddresseeConfig::instance()->setUid( addr.uid() ); + AddresseeConfig::instance()->setAutomaticNameParsing( value ); +} + +void NameEditDialog::typeChanged( int pos ) +{ + mFormattedNameEdit->setEnabled( pos == 0 ); +} + +void NameEditDialog::modified() +{ + mChanged = true; +} + +void NameEditDialog::updateTypeCombo() +{ + KABC::Addressee addr; + addr.setPrefix( mPrefixCombo->currentText() ); + addr.setGivenName( mGivenNameEdit->text() ); + addr.setAdditionalName( mAdditionalNameEdit->text() ); + addr.setFamilyName( mFamilyNameEdit->text() ); + addr.setSuffix( mSuffixCombo->currentText() ); + + int pos = mFormattedNameCombo->currentItem(); + + mFormattedNameCombo->clear(); + mFormattedNameCombo->insertItem( i18n( "Custom" ) ); + mFormattedNameCombo->insertItem( formattedName( addr, SimpleName ) ); + mFormattedNameCombo->insertItem( formattedName( addr, FullName ) ); + mFormattedNameCombo->insertItem( formattedName( addr, ReverseName ) ); + + mFormattedNameCombo->setCurrentItem( pos ); +} + +void NameEditDialog::slotHelp() +{ +#ifndef KAB_EMBEDDED + kapp->invokeHelp( "managing-contacts-automatic-nameparsing" ); +#else //KAB_EMBEDDED +qDebug("NameEditDialog::slotHelp Help is not supported yet"); +#endif //KAB_EMBEDDED +} + +#ifndef KAB_EMBEDDED +#include "nameeditdialog.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/nameeditdialog.h b/kaddressbook/nameeditdialog.h new file mode 100644 index 0000000..1d756c1 --- a/dev/null +++ b/kaddressbook/nameeditdialog.h @@ -0,0 +1,90 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef NAMEEDITDIALOG_H +#define NAMEEDITDIALOG_H + +#include <kdialogbase.h> +#include <kabc/addressee.h> + +#include "addresseeconfig.h" + +class QCheckBox; + +class KLineEdit; +class KComboBox; + +/** + Editor dialog for name details, like given name, family name etc. +*/ +class NameEditDialog : public KDialogBase +{ + Q_OBJECT + + public: + enum FormattedNameType + { + CustomName, // returned by @ref customFormattedName() + SimpleName, // form: givenName familyName + FullName, // form: prefix givenName additionalName familyName suffix + ReverseName // form: familyName, givenName + }; + + NameEditDialog( const KABC::Addressee &addr, int type, + QWidget *parent, const char *name = 0 ); + ~NameEditDialog(); + + QString familyName() const; + QString givenName() const; + QString prefix() const; + QString suffix() const; + QString additionalName() const; + QString customFormattedName() const; + int formattedNameType() const; + + bool changed() const; + + static QString formattedName( const KABC::Addressee &addr, int type ); + + protected slots: + void slotHelp(); + + private slots: + void parseBoxChanged( bool ); + void typeChanged( int ); + void updateTypeCombo(); + void modified(); + + private: + KComboBox *mSuffixCombo; + KComboBox *mPrefixCombo; + KComboBox *mFormattedNameCombo; + KLineEdit *mFamilyNameEdit; + KLineEdit *mGivenNameEdit; + KLineEdit *mAdditionalNameEdit; + KLineEdit *mFormattedNameEdit; + QCheckBox *mParseBox; + bool mChanged; +}; + +#endif diff --git a/kaddressbook/old_mainwindow.cpp b/kaddressbook/old_mainwindow.cpp new file mode 100644 index 0000000..0e886d9 --- a/dev/null +++ b/kaddressbook/old_mainwindow.cpp @@ -0,0 +1,1561 @@ +#include <qlabel.h> +#include <qapp.h> +#include <qmessagebox.h> +#include <qaction.h> + +#include <kdebug.h> // defined kdDebug() +#include <klocale.h> // defines i18n (microkde) + +#include "kabprefs.h" + +#ifndef DESKTOP_VERSION +#include <qpe/qpetoolbar.h> +#include <qpe/qpemenubar.h> +#include <qpe/resource.h> +#else +#include <qtoolbar.h> +#include <qmenubar.h> +#include <resource.h> +#endif + +/* +#include <stdlib.h> + +#include <qaction.h> +#include <qpainter.h> +#include <qwhatsthis.h> +#include <qpopupmenu.h> +#include <qmessagebox.h> +#include <qlineedit.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qwmatrix.h> +#ifndef DESKTOP_VERSION +#include <qpe/global.h> +#include <qpe/qpemenubar.h> +#include <qpe/qpetoolbar.h> +#include <qpe/resource.h> +#include <qpe/qpeapplication.h> +#include <qtopia/alarmserver.h> +#include <qtopia/qcopenvelope_qws.h> +#else +#include <qtoolbar.h> +#include <qdir.h> +#include <qapplication.h> +//#include <resource.h> +#endif + +#include <libkcal/calendarlocal.h> +#include <libkcal/todo.h> + +//#include "calendarview.h" +//#include "koviewmanager.h" +//#include "koagendaview.h" +//#include "kodialogmanager.h" +//#include "kdialogbase.h" +//#include "koprefs.h" +//#include "kfiledialog.h" +//#include "koglobals.h" + +//#include "kconfig.h" +//#include "simplealarmclient.h" +*/ +//US using namespace KACore; + + +#include "mainwindow.h" + +MainWindow::MainWindow( QWidget *parent, const char *name, QString msg) : + QMainWindow( parent, name ) +{ + +#ifdef DESKTOP_VERSION + setFont( QFont("Arial"), 14 ); +#endif +// mBlockAtStartup = true; + kdDebug() << "MainWindow()::MainWindow()" << endl; +// mFlagKeyPressed = false; + setCaption("KAddressbook/Pi"); + + KABPrefs *p = KABPrefs::instance(); + if ( QApplication::desktop()->height() > 480 ) { +//US if ( p->mHourSize == 4 ) +//US p->mHourSize = 6; + } + + QMainWindow::ToolBarDock tbd; + if ( p->mToolBarHor ) { + if ( p->mToolBarUp ) + tbd = Bottom; + else + tbd = Top; + } + else { + if ( p->mToolBarUp ) + tbd = Right; + else + tbd = Left; + } + + iconToolBar = new QPEToolBar( this ); + addToolBar (iconToolBar , tbd ); + +/*US + mBlockSaveFlag = false; + mCalendarModifiedFlag = false; +*/ + QLabel* splash = new QLabel(i18n("KA/Pi is starting ... "), this ); + splash->setAlignment ( AlignCenter ); + setCentralWidget( splash ); +#ifndef DESKTOP_VERSION + showMaximized(); +#endif + qDebug("Mainwidget x %d y %d w %d h %d", x(), y(), width(), height ()); +// setDefaultPreferences(); +/* mCalendar = new CalendarLocal(); + mView = new CalendarView( mCalendar, this,"mCalendar " ); + mView->hide(); + //mView->resize(splash->size() ); +*/ + initActions(); + +#ifndef DESKTOP_VERSION +//US iconToolBar->show(); + qApp->processEvents(); +#endif + qDebug("Splashwidget x %d y %d w %d h %d", splash-> x(), splash->y(), splash->width(),splash-> height ()); + + int vh = height() ; + int vw = width(); + qDebug("Toolbar hei %d ",iconToolBar->height() ); +/*US if ( iconToolBar->orientation () == Qt:: Horizontal ) { + vh -= iconToolBar->height(); + } else { + vw -= iconToolBar->height(); + } +*/ + //mView->setMaximumSize( splash->size() ); + //mView->resize( splash->size() ); + //qDebug("MainView x %d y %d w %d h %d", mView->x(),mView-> y(), mView->width(), mView->height ()); +/* mView->readSettings(); + if( !QFile::exists( defaultFileName() ) ) { + mView->saveCalendar( defaultFileName() ); + } + mView->openCalendar( defaultFileName() ); + processIncidenceSelection( 0 ); + connect( mView, SIGNAL( incidenceSelected( Incidence * ) ), + SLOT( processIncidenceSelection( Incidence * ) ) ); + connect( mView, SIGNAL( modifiedChanged( bool ) ), + SLOT( slotModifiedChanged( bool ) ) ); + connect( mView, SIGNAL( signalmodified() ), + SLOT( checkAlarms( ) ) ); + + connect( &mSaveTimer, SIGNAL( timeout() ), SLOT( save() ) ); + connect( &alarmTimer, SIGNAL( timeout() ), SLOT( writeAlarm() ) ); + mView->setModified( false ); + mBlockAtStartup = false; + mView->setModified( false ); + setCentralWidget( mView ); + mView->show(); +*/ + delete splash; + + qApp->processEvents(); +//US qDebug("MainView x %d y %d w %d h %d", mView->x(),mView-> y(), mView->width(), mView->height ()); + +} +MainWindow::~MainWindow() +{ + qDebug("MainWindow::~MainWindow() "); + kdDebug() << "MainWindow()::~MainWindow()" << endl; + //save toolbar location +/* + KOPrefs *p = KOPrefs::instance(); + p->mToolBarHor = ( iconToolBar->orientation () == Qt:: Horizontal ); + p->mToolBarUp = iconToolBar->x() > width()/2 || + iconToolBar->y() > height()/2; + alarmTimer.stop(); + mView->writeSettings(); + writeAlarm(); + if ( mCalendarModifiedFlag ) + save(); + delete mCalendar; +*/ +} + + +void MainWindow::closeEvent( QCloseEvent* ce ) +{ + + if ( ! KABPrefs::instance()->mAskForQuit ) { + + ce->accept(); + return; + + } + + switch( QMessageBox::information( this, "KA/Pi", + i18n("Do you really want\nto close KA/Pi?"), + i18n("Close!"), i18n("No"), + 0, 0 ) ) { + case 0: + ce->accept(); + break; + case 1: + ce->ignore(); + break; + case 2: + + default: + break; + } + + +} + + +void MainWindow::recieve( const QCString& cmsg, const QByteArray& data ) +{ +/* + QDataStream stream( data, IO_ReadOnly ); + // QMessageBox::about( this, "About KOrganizer/Pi", "*" +msg +"*" ); + + + if ( cmsg == "-writeFile" ) { + mView->viewManager()->showWhatsNextView(); + save(); + setCaption( i18n("File written on AD request")); + showMaximized(); + raise(); +#ifndef DESKTOP_VERSION + QCopEnvelope e3("kosaved", "blabla"); +#endif + return; + + } + if ( cmsg == "-newCountdown" ) { + qDebug("newCountdown "); + + } + QString msg ;; + QString allmsg = cmsg; + while ( allmsg.length() > 0 ) { + int nextC = allmsg.find( "-", 1 ); + if ( nextC == -1 ) { + msg = allmsg; + allmsg = ""; + } else{ + msg = allmsg.left( nextC ); + allmsg = allmsg.mid( nextC, allmsg.length()-nextC ); + } + //qDebug("msg: %s all: %s ", msg.latin1(), allmsg.latin1() ); + if ( msg == "-newEvent" ) { + mView->newEvent(); + } + if ( msg == "-newTodo" ) { + mView->newTodo(); + + } + if ( msg == "-showWN" ) { + mView->viewManager()->showWhatsNextView(); + } + if ( msg == "-showTodo" ) { + mView->viewManager()->showTodoView(); + } + if ( msg == "-showList" ) { + mView->viewManager()->showListView(); + } + else if ( msg == "-showDay" ) { + mView->viewManager()->showDayView(); + } + else if ( msg == "-showWWeek" ) { + mView->viewManager()->showWorkWeekView(); + } + else if ( msg == "-showWeek" ) { + mView->viewManager()->showWeekView(); + } + else if ( msg == "-showTodo" ) { + mView->viewManager()->showTodoView(); + } + else if ( msg == "-showJournal" ) { + mView->viewManager()->showJournalView(); + } + else if ( msg == "-showKO" ) { + mView->viewManager()->showNextXView(); + } + else if ( msg == "-showWNext" ) { + mView->viewManager()->showWhatsNextView(); + } + } + + showMaximized(); + raise(); +*/ +} + + +QPixmap MainWindow::loadPixmap( QString name ) +{ + return KGlobal::iconLoader().loadPixmap( name ); +/*US use the advanced version of the iconloader +#ifdef DESKTOP_VERSION + QPixmap pixmapLoader; + QString file; + file = QDir::homeDirPath()+"/kaddressbook/pics/" + name+".png"; + //qDebug("pixmap name %s ", file.latin1()); + pixmapLoader.load( file ); + return pixmapLoader; +#else + return Resource::loadPixmap( name ); +#endif +*/ +} + +void MainWindow::initActions() +{ + iconToolBar->clear(); + KABPrefs *p = KABPrefs::instance(); + QPEMenuBar *menuBar1 = new QPEMenuBar( iconToolBar ); + QPopupMenu *menuBar = new QPopupMenu( this ); + menuBar1->insertItem( "ME", menuBar); + QPopupMenu *fileMenu = new QPopupMenu( this ); + QPopupMenu *editMenu = new QPopupMenu( this ); + QPopupMenu *viewMenu = new QPopupMenu( this ); + QPopupMenu *settingsMenu = new QPopupMenu( this ); + QPopupMenu *importMenu = new QPopupMenu( this ); + + menuBar1->setMaximumWidth( menuBar1->sizeHint().width() ); + + QIconSet icon; + + + icon = loadPixmap( pathString + "newtodo" ); + configureToolBarMenu->insertItem(icon, "New todo", 20 ); + QAction* nt_action = new QAction( "New Todo", icon, "New Todo...", 0, this ); + nt_action->addTo( actionMenu ); + connect( nt_action, SIGNAL( activated() ), + mView, SLOT( newTodo() ) ); + +/* + QAction *action; + QIconSet icon; + // QPopupMenu *configureMenu= new QPopupMenu( menuBar ); + configureToolBarMenu = new QPopupMenu( this ); + configureToolBarMenu->setCheckable( true ); +#ifdef DESKTOP_VERSION + QString pathString = ""; +#else + QString pathString = "kaddressbook/"; +#endif + if ( QApplication::desktop()->width() < 480 ) + pathString += "icons16/"; + configureAgendaMenu = new QPopupMenu( menuBar ); + configureAgendaMenu->setCheckable( true ); + configureAgendaMenu->insertItem("Toggle Allday", 1 ); + configureAgendaMenu->insertSeparator(); + configureAgendaMenu->insertItem("Tiny", 4 ); + configureAgendaMenu->insertItem("Small", 6 ); + configureAgendaMenu->insertItem("Medium", 8 ); + configureAgendaMenu->insertItem("Normal", 10 ); + configureAgendaMenu->insertItem("Large", 12 ); + configureAgendaMenu->insertItem("Big", 14 ); + configureAgendaMenu->insertItem("Bigger", 16 ); + configureAgendaMenu->insertItem("Biggest", 18 ); + //configureMenu->insertItem( "AgendaSize",configureAgendaMenu ); + icon = loadPixmap( pathString + "newevent" ); + icon = loadPixmap( pathString + "newevent" ); + configureToolBarMenu->insertItem("Stretched TB", 5 ); + configureToolBarMenu->insertSeparator(); + configureToolBarMenu->insertItem(icon, "New event", 10 ); + QAction* ne_action = new QAction( "New Event", icon, "New Event...", 0, this ); + ne_action->addTo( actionMenu ); +*/ +/* + connect( ne_action, SIGNAL( activated() ), + mView, SLOT( newEvent() ) ); + icon = loadPixmap( pathString + "newtodo" ); + configureToolBarMenu->insertItem(icon, "New todo", 20 ); + QAction* nt_action = new QAction( "New Todo", icon, "New Todo...", 0, this ); + nt_action->addTo( actionMenu ); + connect( nt_action, SIGNAL( activated() ), + mView, SLOT( newTodo() ) ); + + action = new QAction( "Toggle FilterView", QPixmap(), "Toggle FilterView", 0, this ); + action->addTo( viewMenu ); + connect( action, SIGNAL( activated() ), + mView, SLOT( toggleFilter() ) ); + + viewMenu->insertSeparator(); + icon = loadPixmap( pathString + "picker" ); + action = new QAction( "Date Picker", icon, "Date Picker", 0, this ); + action->addTo( viewMenu ); + connect( action, SIGNAL( activated() ), + mView, SLOT( showDatePicker() ) ); + action->addTo( iconToolBar ); + viewMenu->insertSeparator(); + icon = loadPixmap( pathString + "list" ); + configureToolBarMenu->insertItem(icon, "Event list", 30 ); + QAction* showlist_action = new QAction( "List", icon, "List", 0, this ); + showlist_action->addTo( viewMenu ); + connect( showlist_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showListView() ) ); + + + icon = loadPixmap( pathString + "day" ); + configureToolBarMenu->insertItem(icon, "One day", 40 ); + QAction* day1_action = new QAction( "Day", icon, "Day", 0, this ); + day1_action->addTo( viewMenu ); + // action->addTo( toolBar ); + connect( day1_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showDayView() ) ); + + icon = loadPixmap( pathString + "workweek" ); + configureToolBarMenu->insertItem(icon, "Work week", 50 ); + QAction* day5_action = new QAction( "Work Week", icon, "Work Week", 0, this ); + day5_action->addTo( viewMenu ); + connect( day5_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showWorkWeekView() ) ); + + icon = loadPixmap( pathString + "week" ); + configureToolBarMenu->insertItem(icon, "Week", 60 ); + QAction* day7_action = new QAction( "Week", icon, "Week", 0, this ); + day7_action->addTo( viewMenu ); + connect( day7_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showWeekView() ) ); + + icon = loadPixmap( pathString + "month" ); + configureToolBarMenu->insertItem(icon, "Month", 70 ); + QAction* month_action = new QAction( "Month", icon, "Month", 0, this ); + month_action->addTo( viewMenu ); + connect( month_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showMonthView() ) ); + + icon = loadPixmap( pathString + "todo" ); + configureToolBarMenu->insertItem(icon, "Todo list", 80 ); + QAction* todoview_action = new QAction( "Todo", icon, "Todo", 0, this ); + todoview_action->addTo( viewMenu ); + connect( todoview_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showTodoView() ) ); + + icon = loadPixmap( pathString + "journal" ); + configureToolBarMenu->insertItem(icon, "Journal", 90 ); + QAction* viewjournal_action = new QAction( "Journal", icon, "Journal", 0, this ); + viewjournal_action->addTo( viewMenu ); + connect( viewjournal_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showJournalView() ) ); + + icon = loadPixmap( pathString + "xdays" ); + configureToolBarMenu->insertItem(icon, "Next days", 100,4 ); + QAction* xdays_action = new QAction( "Next days", icon, "Next Days", 0, this ); + xdays_action->addTo( viewMenu ); + connect( xdays_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showNextXView() ) ); + + icon = loadPixmap( pathString + "whatsnext" ); + configureToolBarMenu->insertItem(icon, "Whats next", 110, 4 ); + QAction* whatsnext_action = new QAction( "What's Next", icon, "What's Next", 0, this ); + whatsnext_action->addTo( viewMenu ); + connect( whatsnext_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showWhatsNextView() ) ); + +#if 0 + action = new QAction( "view_timespan", "Time Span", 0, this ); + action->addTo( viewMenu ); + connect( action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showTimeSpanView() ) ); +#endif + + menuBar->insertItem( "View", viewMenu ); + + +#if 0 + QPopupMenu *navigationMenu = new QPopupMenu( menuBar ); + + action = new QAction( "Go backward", "Go Backward", 0, navigationMenu ); + action->addTo( navigationMenu ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goPrevious() ) ); + + action = new QAction( "Go forward", "Go Forward", 0, navigationMenu ); + action->addTo( navigationMenu ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goNext() ) ); + + menuBar->insertItem( "Go", navigationMenu ); +#endif + + + + + + + mNewSubTodoAction = new QAction( "new_subtodo", "New Sub-Todo...", 0, + this ); + mNewSubTodoAction->addTo( actionMenu ); + connect( mNewSubTodoAction, SIGNAL( activated() ), + mView, SLOT( newSubTodo() ) ); + + actionMenu->insertSeparator(); + + mShowAction = new QAction( "show_incidence", "Show...", 0, this ); + mShowAction->addTo( actionMenu ); + connect( mShowAction, SIGNAL( activated() ), + mView, SLOT( showIncidence() ) ); + + mEditAction = new QAction( "edit_incidence", "Edit...", 0, this ); + mEditAction->addTo( actionMenu ); + connect( mEditAction, SIGNAL( activated() ), + mView, SLOT( editIncidence() ) ); + + mDeleteAction = new QAction( "delete_incidence", "Delete...", 0, this ); + mDeleteAction->addTo( actionMenu ); + connect( mDeleteAction, SIGNAL( activated() ), + mView, SLOT( deleteIncidence() ) ); + + actionMenu->insertSeparator(); + + action = new QAction( "purge_completed", i18n("Purge Completed"), 0, + this ); + action->addTo( actionMenu ); + connect( action, SIGNAL( activated() ), mView, SLOT( purgeCompleted() ) ); + + icon = loadPixmap( pathString + "search" ); + QAction* search_action = new QAction( "search", icon, "Search...", 0, this ); + configureToolBarMenu->insertItem(icon, "Search", 120 , 4); + search_action->addTo( actionMenu ); + connect( search_action, SIGNAL( activated() ), + mView->dialogManager(), SLOT( showSearchDialog() ) ); + + icon = loadPixmap( pathString + "today" ); + configureToolBarMenu->insertItem(icon, "Today", 130); + QAction* today_action = new QAction( "Today", icon, "Go to Today", 0, this ); + today_action->addTo( actionMenu ); + connect( today_action, SIGNAL( activated() ), + mView, SLOT( goToday() ) ); + + //#if 0 + actionMenu->insertSeparator(); + + action = new QAction( "configure", "Configure...", 0, this ); + action->addTo( actionMenu ); + connect( action, SIGNAL( activated() ), + mView, SLOT( edit_options() ) ); + //#endif + + // actionMenu->insertSeparator(); + action = new QAction( "import_qtopia", "Import (*.ics/*.vcs) file", 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( importIcal() ) ); + action = new QAction( "import_quick", "Import last file", 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( quickImportIcal() ) ); + importMenu->insertSeparator(); + action = new QAction( "import_qtopia", "Import Opie/Qtopia Cal.", 0, + this ); + action->addTo( importMenu ); + importMenu->insertSeparator(); + connect( action, SIGNAL( activated() ), SLOT( importQtopia() ) ); + + action = new QAction( "load_cal", "Load Calendar Backup", 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( loadCalendar() ) ); + + action = new QAction( "save_cal", "Save Calendar Backup", 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( saveCalendar() ) ); + + importMenu->insertSeparator(); + action = new QAction( "import_qtopia", "Export VCalendar", 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( exportVCalendar() ) ); + + + QPopupMenu *syncMenu = new QPopupMenu( this ); + action = new QAction( "syncssh", "Remote via ssh/scp(not implemented)", 0, + this ); + action->addTo( syncMenu ); + connect( action, SIGNAL( activated() ), SLOT( syncSSH() ) ); + action = new QAction( "synclocal", "With local file(not implemented)", 0, + this ); + action->addTo( syncMenu ); + connect( action, SIGNAL( activated() ), SLOT( syncLocalFile() ) ); + action = new QAction( "quicksynclocal", "With last file(not implemented)", 0, + this ); + action->addTo( syncMenu ); + connect( action, SIGNAL( activated() ), SLOT( quickSyncLocalFile() ) ); + + menuBar->insertItem( "Actions", actionMenu ); + menuBar->insertItem( "Load/Save", importMenu ); + menuBar->insertItem( "Synchronize", syncMenu ); + //menuBar->insertItem( "Configure",configureMenu ); + //configureMenu->insertItem( "Toolbar",configureToolBarMenu ); + menuBar->insertItem( "AgendaSize",configureAgendaMenu ); + menuBar->insertItem( "Toolbar",configureToolBarMenu ); + QPopupMenu *helpMenu = new QPopupMenu( menuBar ); + icon = loadPixmap( "korganizer/korganizer" ); + action = new QAction( "Key bindings", "Key Bindings...", 0, this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( keyBindings() ) ); + action = new QAction( "Auto saving", "Auto saving...", 0, this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( aboutAutoSaving() ) ); + action = new QAction( "Problemd", "Known Problems...", 0,this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( aboutKnownBugs() ) ); + action = new QAction( "about", "About...", 0, this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( about() ) ); + menuBar->insertItem( "Help", helpMenu ); +*/ + //menuBar->insertSeparator(); + + // ****************************************************** + // menubar icons + + + iconToolBar->setHorizontalStretchable (true ); + //menuBar->insertItem( iconToolBar ); + //xdays_action +/* + if (p-> mShowIconNewEvent) + ne_action->addTo( iconToolBar ); + if (p->mShowIconNewTodo ) + nt_action->addTo( iconToolBar ); + if (p-> mShowIconSearch) + search_action->addTo( iconToolBar ); + if (p-> mShowIconNext) + whatsnext_action->addTo( iconToolBar ); + if (p-> mShowIconNextDays) + xdays_action->addTo( iconToolBar ); + if (p-> mShowIconList) + showlist_action->addTo( iconToolBar ); + if (p-> mShowIconDay1) + day1_action->addTo( iconToolBar ); + if (p-> mShowIconDay5) + day5_action->addTo( iconToolBar ); + if (p-> mShowIconDay7) + day7_action->addTo( iconToolBar ); + if (p-> mShowIconMonth) + month_action->addTo( iconToolBar ); + if (p-> mShowIconTodoview) + todoview_action->addTo( iconToolBar ); + if (p-> mShowIconJournal) + viewjournal_action->addTo( iconToolBar ); + icon = loadPixmap( pathString + "2leftarrowB" ); + configureToolBarMenu->insertItem(icon, "Prev. month", 200, 14); + if (p-> mShowIconBackFast) { + action = new QAction( "Prev month", icon, "Go Backward",0 , this ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goPreviousMonth() ) ); + action->addTo( iconToolBar ); + } + icon = loadPixmap( pathString + "1leftarrowB" ); + configureToolBarMenu->insertItem(icon, "Go previous", 210,15); + if (p-> mShowIconBack) { + action = new QAction( "Go previous", icon, "Go Backward",0 , this ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goPrevious() ) ); + action->addTo( iconToolBar ); + } + if (p-> mShowIconToday) + today_action->addTo( iconToolBar ); + icon = loadPixmap( pathString + "1rightarrowB" ); + configureToolBarMenu->insertItem(icon, "Go next", 220); + if (p-> mShowIconForward) { + action = new QAction( "Go next", icon, "Go Backward",0 , this ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goNext() ) ); + action->addTo( iconToolBar ); + } + icon = loadPixmap( pathString + "2rightarrowB" ); + configureToolBarMenu->insertItem(icon, "Next month", 230); + if (p-> mShowIconForwardFast) { + action = new QAction( "Next month", icon, "Go Backward",0 , this ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goNextMonth() ) ); + action->addTo( iconToolBar ); + } +*/ + + configureToolBarMenu->insertItem("WhatsThis", 300); +/* + if (p-> mShowIconNewEvent) + configureToolBarMenu->setItemChecked( 10, true ); + if (p->mShowIconNewTodo ) + configureToolBarMenu->setItemChecked( 20, true ); + if (p-> mShowIconSearch) + configureToolBarMenu->setItemChecked( 120, true ); + if (p-> mShowIconList) + configureToolBarMenu->setItemChecked( 30, true ); + if (p-> mShowIconDay1) + configureToolBarMenu->setItemChecked( 40, true ); + if (p-> mShowIconDay5) + configureToolBarMenu->setItemChecked( 50, true ); + if (p-> mShowIconDay7) + configureToolBarMenu->setItemChecked( 60, true ); + if (p-> mShowIconMonth) + configureToolBarMenu->setItemChecked( 70, true ); + if (p-> mShowIconTodoview) + configureToolBarMenu->setItemChecked( 80, true ); + if (p-> mShowIconBackFast) + configureToolBarMenu->setItemChecked( 200, true ); + if (p-> mShowIconBack) + configureToolBarMenu->setItemChecked( 210, true ); + if (p-> mShowIconToday) + configureToolBarMenu->setItemChecked( 130, true ); + if (p-> mShowIconForward) + configureToolBarMenu->setItemChecked( 220, true ); + if (p-> mShowIconForwardFast) + configureToolBarMenu->setItemChecked( 230, true ); + if (p-> mShowIconNextDays) + configureToolBarMenu->setItemChecked( 100, true ); + if (p-> mShowIconNext) + configureToolBarMenu->setItemChecked( 110, true ); + if (p-> mShowIconJournal) + configureToolBarMenu->setItemChecked( 90, true ); + if (p-> mShowIconWhatsThis) + configureToolBarMenu->setItemChecked( 300, true ); + + QLabel* dummy = new QLabel( iconToolBar ); + dummy->setBackgroundColor( iconToolBar->backgroundColor() ); + if (!p-> mShowIconStretch) + iconToolBar->setStretchableWidget ( dummy ) ; + else + configureToolBarMenu->setItemChecked( 5, true ); + if (p-> mShowIconWhatsThis) + QWhatsThis::whatsThisButton ( iconToolBar ); + connect( configureToolBarMenu, SIGNAL( activated( int ) ),this, SLOT(configureToolBar( int ) ) ); + configureAgenda( p->mHourSize ); + connect( configureAgendaMenu, SIGNAL( activated( int ) ),this, SLOT(configureAgenda( int ) ) ); +*/ +} +/* +void MainWindow::setDefaultPreferences() +{ + KOPrefs *p = KOPrefs::instance(); + + p->mCompactDialogs = true; + p->mConfirm = true; + p->mEnableQuickTodo = false; +} +*/ +void MainWindow::about() +{ + QMessageBox::about( this, "About KOrganizer/Pi", + "KOrganizer/Platform-independent\n" + "(KO/Pi) 1.6.0e - " +#ifdef DESKTOP_VERSION + "Desktop Edition\n" +#else + "PDA-Edition\n" + "for: Zaurus 5500 / 7x0 / 8x0\n" +#endif + "(c) 2004 Lutz Rogowski\n" + "Email:lutz@pi-sync.net\n" + "KO/Pi is based on KOrganizer\n" + "(c) 2002,2003 Cornelius Schumacher\n" + "Email: schumacher@kde.org\n" + "KOrganizer/Pi is licensed\n" + "under the GPL.\n" + "KO/Pi can be compiled for\n" + "Linux, Zaurus-PDA and Windows\n" + "www.korganizer.org\n" ); +} +/* +void MainWindow::keyBindings() +{ + QMessageBox* msg; + msg = new QMessageBox( "Key bindings KOrganizer/Pi", + "Space: Toggle Fullscreen | P: Date Picker\n" + "H: This dialog | I: Show info | S: Search\n" + "F: Toggle Filterview | 1-4: Select Filter\n" + "N: Show next days | W: Whats next\n " + "V: Todo view | L: Event list view\n" + "T: Goto today | T+<ctrl>: New Todo\n" + "E: Edit item | E+<ctrl>: New Event\n" + "5: Work week view | 7: Week view\n" + "D: One day view | M: Month view\n" + "+,- : Zoom in/out Agenda | A: Toggle Allday\n" + "<ctrl>+<up>/<down>: Scroll todo view\n" + "<right>,C: Next week | <right>+<ctrl>: Next month\n" + "<left>,X: Prev. week | <left>+<ctrl>: Prev. month\n" + "<del>,<backspace>: Delete sel. item\n", + QMessageBox::NoIcon, + QMessageBox::Ok, + QMessageBox::NoButton, + QMessageBox::NoButton ); + msg->exec(); + delete msg; + +} +void MainWindow::aboutAutoSaving() +{ + QMessageBox* msg; + msg = new QMessageBox( "Auto Saving in KOrganizer/Pi", + "After changing something, the data is\n" + "automatically saved to the file\n" + "~/Applications/korganizer/mycalendar.ics\n " + "after (configureable) one minute.\n" + "For safety reasons there is one autosaving\n" + "after 10 minutes (of idle time) again. The \n" + "data is saved automatically when closing KO/Pi\n" + "You can create a backup file \n" + "with: Load/Save - Save Calendar Backup\n", + QMessageBox::NoIcon, + QMessageBox::Ok, + QMessageBox::NoButton, + QMessageBox::NoButton); + msg->exec(); + delete msg; + + +} +void MainWindow::aboutKnownBugs() +{ + QMessageBox* msg; + msg = new QMessageBox( "Known Problems in KOrganizer/Pi", + "1) The QWhatsThis help is not working.\n" + "There is only a black rectangle displayed\n" + "when clicking on an event.\n " + "2) Audio alarm is available!\n" + "as an additional small application\n" + "3) Syncing is missing.\n" + "Syncing via ssh/scp will be available in\n" + "KOrganizer/Pi 2.0\n" + "\n" + "Please report unexpected behaviour to\n" + "lutz@pi-sync.net\n", + QMessageBox::NoIcon, + QMessageBox::Ok, + QMessageBox::NoButton, + QMessageBox::NoButton); + msg->exec(); + delete msg; + +} + +QString MainWindow::defaultFileName() +{ +#ifndef DESKTOP_VERSION + return Global::applicationFileName( "korganizer", "mycalendar.ics" ); +#else + // pending + QString file; + file = QDir::homeDirPath()+"/korganizer/mycalendar.ics"; + return QDir::convertSeparators( file ); +#endif +} + +void MainWindow::processIncidenceSelection( Incidence *incidence ) +{ + if ( !incidence ) { + enableIncidenceActions( false ); + + mNewSubTodoAction->setEnabled( false ); + setCaptionToDates(); + return; + + } + + QString startString = ""; + if ( incidence->type() != "Todo" ) { + if ( incidence->dtStart().date() < incidence->dtEnd().date() ) { + startString = ": "+incidence->dtStart().time().toString().left(5); + startString += " "+ incidence->dtStart().date().toString(); + startString += "-"+incidence->dtEnd().time().toString().left(5); + startString += " "+ incidence->dtEnd().date().toString(); + + } else { + if ( incidence->dtStart().time() != incidence->dtEnd().time() ) + startString = ": "+incidence->dtStart().time().toString().left(5)+"-"+incidence->dtEnd().time().toString().left(5); + startString +=" "+incidence->dtStart().date().toString(); + } + + } + else + startString = ": (Prio "+QString::number( (( KCal::Todo*)incidence)->priority() ) +") "+QString::number( (( KCal::Todo*)incidence)->percentComplete() ) +"\% completed"; + + setCaption( incidence->summary()+startString); + + enableIncidenceActions( true ); + + if ( incidence->type() == "Event" ) { + mShowAction->setText( i18n("Show Event...") ); + mEditAction->setText( i18n("Edit Event...") ); + mDeleteAction->setText( i18n("Delete Event...") ); + + mNewSubTodoAction->setEnabled( false ); + } else if ( incidence->type() == "Todo" ) { + mShowAction->setText( i18n("Show Todo...") ); + mEditAction->setText( i18n("Edit Todo...") ); + mDeleteAction->setText( i18n("Delete Todo...") ); + + mNewSubTodoAction->setEnabled( true ); + } else { + mShowAction->setText( i18n("Show...") ); + mShowAction->setText( i18n("Edit...") ); + mShowAction->setText( i18n("Delete...") ); + + mNewSubTodoAction->setEnabled( false ); + } +} + +void MainWindow::enableIncidenceActions( bool enabled ) +{ + mShowAction->setEnabled( enabled ); + mEditAction->setEnabled( enabled ); + mDeleteAction->setEnabled( enabled ); +} + +void MainWindow::importQtopia() +{ +#ifndef DESKTOP_VERSION + int result = QMessageBox::warning( this, "KO/Pi: Warning!", + "When importing a calendar twice\n" + "duplicated events will be ignored!\n" + "You can create a backup file with\n" + "Load/Save - Save Calendar Backup\n" + "to revert importing", + "Import!", "Cancel", 0, + 0, 1 ); + if ( result == 0 ) { + QString datebook = Global::applicationFileName( "datebook", "datebook.xml"); + QString todolist = Global::applicationFileName( "todolist", "todolist.xml"); + QString categories = QString( getenv( "HOME" ) ) + "/Settings/Categories.xml"; + mView->importQtopia( categories, datebook, todolist ); + } +#else + int result = QMessageBox::warning( this, "KO/Pi: Warning!", + "NOT SUPPORTED \n" + "ON DESKTOP!\n", + "OK", "Cancel", 0, + 0, 1 ); + +#endif +} +void MainWindow::checkAlarms() +{ + if ( mBlockAtStartup ) + return; + alarmTimer.start( 1000 * 3); + +} +void MainWindow::slotModifiedChanged( bool changed ) +{ + if ( mBlockAtStartup ) + return; + int msec; + // we store the changes after 1 minute, + // and for safety reasons after 10 minutes again + if ( !mBlockSaveFlag ) + msec = (1000 * 60*KOPrefs::instance()->mAutoSaveInterval) +1000; + else + msec = 1000 * 600; + mSaveTimer.start( msec, true ); // 1 minute + qDebug("KO: Saving File in %d secs!", msec/1000); + mCalendarModifiedFlag = true; +} +void MainWindow::writeAlarm() +{ + if ( mBlockAtStartup ) + return; + //QCopEnvelope e3("koalarm", "-showWN"); + QDateTime nextA ; + QDateTime reference ( QDate( 2000, 1, 1 ) ); + QString summary; + alarmTimer.stop(); + Calendar* cal = mView->calendar(); + if ( ! cal ){ + qDebug("KO: Calendar undefined. No alarm notification"); + return; + } + nextA = cal->nextAlarm( 720 ); + summary = cal->nextSummary(); + qDebug("KO: Next Alarm %s %s", nextA.toString().latin1(), summary.latin1()); + if ( nextA < QDateTime::currentDateTime().addDays( 720-1 ) ) { + KConfig *config = KOGlobals::config(); + config->setGroup("NextSystemAlarm"); + QString date, sum; + date = config->readEntry("TimeDateinSecs", "xxx"); + bool ok = false; + int shsecs = date.toInt(&ok ); + QDateTime scheduledAlarm; + QDateTime eventDateTime = cal->nextAlarmEvent(); + sum = config->readEntry("Summary", "sss"); + if ( ok ) { + scheduledAlarm = reference.addSecs( shsecs ); + //qDebug("sheduledAlarm %s ", scheduledAlarm.toString().latin1()); + if ( scheduledAlarm == nextA && sum == summary ) { + qDebug("KO: Same alarm time+summary - nothing to do! "); + return; + } + } + if ( ok ) { + // delete alarm from system + //qDebug("delete Alarm %s ", scheduledAlarm.toString().latin1()); +#ifndef DESKTOP_VERSION + AlarmServer::deleteAlarm ( scheduledAlarm,"koalarm" , sum.latin1() ); +#endif + } + // add new alarm to system + qDebug("KO: Add Alarm: %s ", nextA.toString().latin1() ); +#ifndef DESKTOP_VERSION + AlarmServer::addAlarm ( nextA,"koalarm", summary.latin1() ); +#endif + // write new alarm to config file + //qDebug("Entry %s %s ", date.latin1(), sum.latin1()); + int secs = reference.secsTo( nextA ); + //qDebug(" secs %d ", secs); + setCaption( i18n("Next Alarm: ")+ nextA.toString() +"-"+summary ); + config->writeEntry("TimeDateinSecs",QString::number ( secs )); + config->writeEntry("Summary",summary); + config->writeEntry("TimeDate",nextA.toString()); + config->writeEntry("WriteDateTime",QDateTime::currentDateTime().toString()); + config->writeEntry("EventStartDateTime",eventDateTime.toString()); + config->writeEntry("SystemNotifyInSecs",QString::number (QDateTime::currentDateTime().secsTo( nextA ) )); + config->sync(); + + } +} +void MainWindow::save() +{ + if ( mBlockSaveFlag ) + return; + + mBlockSaveFlag = true; + QTime neededSaveTime = QDateTime::currentDateTime().time(); + setCaption("KO/Pi:Saving Data to File ..." ); + qDebug("KO: Start saving data to file!"); + mView->saveCalendar( defaultFileName() ); + int msNeeded = neededSaveTime.msecsTo( QDateTime::currentDateTime().time() ); + qDebug("KO: Needed %d ms for saving.",msNeeded ); + QString savemes; + savemes.sprintf("KO/Pi:File Saved. Needed %d sec, %d ms",(msNeeded/1000)%100,msNeeded%1000 ); + setCaption(savemes); + mCalendarModifiedFlag = false; + mBlockSaveFlag = false; +} + +void MainWindow::keyReleaseEvent ( QKeyEvent * e) +{ + if ( !e->isAutoRepeat() ) { + mFlagKeyPressed = false; + } +} +void MainWindow::keyPressEvent ( QKeyEvent * e ) +{ + qApp->processEvents(); + if ( e->isAutoRepeat() && !mFlagKeyPressed ) { + e->ignore(); + // qDebug(" ignore %d",e->isAutoRepeat() ); + return; + } + if (! e->isAutoRepeat() ) + mFlagKeyPressed = true; + KOPrefs *p = KOPrefs::instance(); + bool showSelectedDates = false; + int size; + //qDebug("MainWindow::keyPressEvent "); + switch ( e->key() ) { + case Qt::Key_Right: + if ( e->state() == Qt::ControlButton ) + mView->goNextMonth(); + else + mView->goNext(); + showSelectedDates = true; + break; + case Qt::Key_Left: + if ( e->state() == Qt::ControlButton ) + mView->goPreviousMonth(); + else + mView->goPrevious(); + showSelectedDates = true; + break; + case Qt::Key_Down: + mView->viewManager()->agendaView()->scrollOneHourDown(); + break; + case Qt::Key_Up: + mView->viewManager()->agendaView()->scrollOneHourUp(); + break; + case Qt::Key_I: + mView->showIncidence(); + break; + case Qt::Key_Delete: + case Qt::Key_Backspace: + mView->deleteIncidence(); + break; + case Qt::Key_D: + mView->viewManager()->showDayView(); + showSelectedDates = true; + break; + case Qt::Key_0: + mView->toggleFilerEnabled( ); + break; + case Qt::Key_1: + mView->selectFilter( 0 ); + break; + case Qt::Key_2: + mView->selectFilter( 1 ); + break; + case Qt::Key_3: + mView->selectFilter( 2 ); + break; + case Qt::Key_4: + mView->selectFilter( 3 ); + break; + case Qt::Key_5: + mView->viewManager()->showWorkWeekView(); + showSelectedDates = true; + break; + case Qt::Key_7: + mView->viewManager()->showWeekView(); + showSelectedDates = true; + break; + case Qt::Key_M: + mView->viewManager()->showMonthView(); + showSelectedDates = true; + break; + case Qt::Key_Insert: + mView->newEvent(); + break; + case Qt::Key_S : + mView->dialogManager()->showSearchDialog(); + break; + case Qt::Key_H : + keyBindings(); + break; + case Qt::Key_W: + mView->viewManager()->showWhatsNextView(); + break; + case Qt::Key_L: + mView->viewManager()->showListView(); + break; + case Qt::Key_N: + mView->viewManager()->showNextXView(); + showSelectedDates = true; + break; + case Qt::Key_V: + mView->viewManager()->showTodoView(); + break; + case Qt::Key_C: + mView->goNext(); + showSelectedDates = true; + break; + case Qt::Key_P: + mView->showDatePicker( ); + break; + case Qt::Key_F: + mView->toggleFilter(); + break; + case Qt::Key_X: + mView->goPrevious(); + showSelectedDates = true; + break; + case Qt::Key_Space: + mView->toggleExpand(); + break; + case Qt::Key_A: + mView->toggleAllDaySize(); + break; + case Qt::Key_T: + if ( e->state() == Qt::ControlButton ) + mView->newTodo(); + else { + mView->goToday(); + showSelectedDates = true; + } + break; + case Qt::Key_J: + mView->viewManager()->showJournalView(); + break; + case Qt::Key_Return: + case Qt::Key_E: + if ( e->state() == Qt::ControlButton ) + mView->newEvent(); + else + mView->editIncidence(); + break; + case Qt::Key_Plus: + size = p->mHourSize +2; + if ( size <= 18 ) + configureAgenda( size ); + break; + case Qt::Key_Minus: + size = p->mHourSize - 2; + if ( size >= 4 ) + configureAgenda( size ); + break; + + + default: + e->ignore(); + } + + if ( showSelectedDates ) { + ;// setCaptionToDates(); + } + +} + +void MainWindow::configureToolBar( int item ) +{ + + configureToolBarMenu->setItemChecked( item, !configureToolBarMenu-> isItemChecked ( item ) ); + KOPrefs *p = KOPrefs::instance(); + p-> mShowIconStretch= configureToolBarMenu->isItemChecked( 5 ); + p-> mShowIconNewEvent= configureToolBarMenu->isItemChecked( 10 ); + p->mShowIconNewTodo = configureToolBarMenu->isItemChecked( 20 ); + p-> mShowIconSearch= configureToolBarMenu->isItemChecked( 120 ); + p-> mShowIconList= configureToolBarMenu->isItemChecked( 30 ); + p-> mShowIconDay1= configureToolBarMenu->isItemChecked( 40 ); + p-> mShowIconDay5= configureToolBarMenu->isItemChecked( 50 ); + p-> mShowIconDay7= configureToolBarMenu->isItemChecked( 60 ); + p-> mShowIconMonth= configureToolBarMenu->isItemChecked( 70 ); + p-> mShowIconTodoview= configureToolBarMenu->isItemChecked( 80 ); + p-> mShowIconBackFast= configureToolBarMenu->isItemChecked( 200 ); + p-> mShowIconBack = configureToolBarMenu->isItemChecked( 210 ); + p-> mShowIconToday= configureToolBarMenu->isItemChecked( 130 ); + p-> mShowIconForward= configureToolBarMenu->isItemChecked( 220 ); + p-> mShowIconForwardFast= configureToolBarMenu->isItemChecked( 230 ); + p-> mShowIconNextDays= configureToolBarMenu->isItemChecked( 100 ); + p-> mShowIconNext= configureToolBarMenu->isItemChecked( 110 ); + p-> mShowIconJournal= configureToolBarMenu->isItemChecked( 90 ); + p-> mShowIconWhatsThis= configureToolBarMenu->isItemChecked( 300 ); + initActions(); +} + +void MainWindow::setCaptionToDates() +{ + QString selDates; + selDates = mView->startDate().toString(); + if (mView->startDate() < mView->endDate() ) + selDates += " - " + mView->endDate().toString(); + setCaption( "Dates: " + selDates ); + +} +// parameter item == 0: reinit +void MainWindow::configureAgenda( int item ) +{ + + KOPrefs *p = KOPrefs::instance(); + + int i; + if ( item == 1 ) { + mView->toggleAllDaySize(); + return; + } + // do not allow 4 for widgets higher than 480 + if ( QApplication::desktop()->height() > 480 ) { + if ( item == 4 ) + item = 6; + } + for ( i = 4; i <= 18; i= i+2 ) + configureAgendaMenu->setItemChecked( i, false ); + configureAgendaMenu->setItemChecked( item, true ); + if ( p->mHourSize == item ) + return; + p->mHourSize=item; + mView->viewManager()->agendaView()->updateConfig(); +} + +void MainWindow::saveCalendar() +{ + QString fn = KOPrefs::instance()->mLastSaveFile; + fn = KFileDialog::getSaveFileName( fn, "Save backup filename", this ); + + if ( fn == "" ) + return; + QFileInfo info; + info.setFile( fn ); + QString mes; + bool createbup = true; + if ( info. exists() ) { + mes.sprintf( "Backup file\nalready exists!\nOld backup file from:\n%s\nOverwrite?\n",info.lastModified ().toString().latin1() ); + int result = QMessageBox::warning( this, "KO/Pi: Warning!",mes, + "Overwrite!", "Cancel", 0, + 0, 1 ); + if ( result != 0 ) { + createbup = false; + } + } + if ( createbup ) { + mView->saveCalendar( fn ); + mes.sprintf("KO/Pi:Saved %s",fn.latin1() ); + KOPrefs::instance()->mLastSaveFile = fn; + setCaption(mes); + } +} +void MainWindow::loadCalendar() +{ + + QString fn = KOPrefs::instance()->mLastLoadFile; + fn = KFileDialog::getOpenFileName( fn, "Load backup filename", this ); + + if ( fn == "" ) + return; + QFileInfo info; + info.setFile( fn ); + QString mess; + bool loadbup = true; + if ( info. exists() ) { + mess.sprintf( "Backup file from:\n%s\nLoading backup\nfile will delete\nyour current Data!\n",info.lastModified ().toString().latin1() ); + int result = QMessageBox::warning( this, "KO/Pi: Warning!", + mess, + "Load!", "Cancel", 0, + 0, 1 ); + if ( result != 0 ) { + loadbup = false; + } + } else { + QMessageBox::warning( this, "KO/Pi: Warning!", + "Backup file\ndoes not exist!\n" + "Nothing loaded!", 0, 0, + 0, 1 ); + + return; + } + if ( loadbup ) { + mView->openCalendar( fn ); + KOPrefs::instance()->mLastLoadFile = fn; + mess.sprintf("KO/Pi:Loaded %s",fn.latin1() ); + setCaption(mess); + } + +} +void MainWindow::quickImportIcal() +{ + importFile( KOPrefs::instance()->mLastImportFile, false ); +} +void MainWindow::importFile( QString fn, bool quick ) +{ + QFileInfo info; + info.setFile( fn ); + QString mess; + bool loadbup = true; + if ( !info. exists() ) { + mess= "Import file \n..."+fn.right( 30)+ "\ndoes not exist!\nNothing imported!\n"; + int result = QMessageBox::warning( this, "KO/Pi: Warning!", + mess ); + return; + } + int result = 0; + if ( !quick ) { + mess.sprintf( "Import file \n..."+fn.right( 25)+"\nfrom:\n%s\nDuplicated entries\nwill not be imported!\n",info.lastModified ().toString().latin1() ); + result = QMessageBox::warning( this, "KO/Pi: Warning!", + mess, + "Import", "Cancel", 0, + 0, 1 ); + } + if ( result == 0 ) { + if ( mView->openCalendar( fn, true )) { + KOPrefs::instance()->mLastImportFile = fn; + setCaption(i18n(" ")); + setCaption(i18n("Imported file successfully")); + } else { + setCaption(i18n("Error importing file")); + } + } +} +void MainWindow::importIcal() +{ + + QString fn =KOPrefs::instance()->mLastImportFile; + + fn =KFileDialog:: getOpenFileName( fn, "Import filename(*.ics/*.vcs)", this ); + if ( fn == "" ) + return; + importFile( fn, true ); + +} + +void MainWindow::exportVCalendar() +{ + QString fn = KOPrefs::instance()->mLastVcalFile; + fn = KFileDialog::getSaveFileName( fn, "Export vcal filename(*.vcs)", this ); + if ( fn == "" ) + return; + QFileInfo info; + info.setFile( fn ); + QString mes; + bool createbup = true; + if ( info. exists() ) { + mes.sprintf( i18n("Save file\nalready exists!\nOld save file from:\n%s\nOverwrite?\n"),info.lastModified ().toString().latin1() ); + int result = QMessageBox::warning( this, "KO/Pi: Warning!",mes, + "Overwrite!", "Cancel", 0, + 0, 1 ); + if ( result != 0 ) { + createbup = false; + } + } + if ( createbup ) { + if ( mView->exportVCalendar( fn ) ) { + KOPrefs::instance()->mLastVcalFile = fn; + if ( fn.length() > 20 ) + mes.sprintf(i18n("KO/Pi:Exported to ...%s"),(fn.right(20)).latin1() ); + else + mes.sprintf(i18n("KO/Pi:Exported to %s"),fn.latin1() ); + setCaption(mes); + } + } + +} + +QString MainWindow::getPassword( ) +{ + QString retfile = ""; + QDialog dia ( this, "input-dialog", true ); + QLineEdit lab ( &dia ); + lab.setEchoMode( QLineEdit::Password ); + QVBoxLayout lay( &dia ); + lay.setMargin(7); + lay.setSpacing(7); + lay.addWidget( &lab); + dia.setFixedSize( 230,50 ); + dia.setCaption( i18n("Input password") ); + dia.show(); + int res = dia.exec(); + if ( res ) + retfile = lab.text(); + return retfile; + +} +#ifndef _WIN32_ +#include <unistd.h> +#endif +void MainWindow::syncLocalFile() +{ + + QString fn =KOPrefs::instance()->mLastSyncedLocalFile; + + fn =KFileDialog:: getOpenFileName( fn, i18n("Sync filename(*.ics/*.vcs)"), this ); + if ( fn == "" ) + return; + syncWithFile( fn, false ); + +} + +void MainWindow::syncWithFile( QString fn , bool quick ) +{ + QFileInfo info; + info.setFile( fn ); + QString mess; + bool loadbup = true; + if ( !info. exists() ) { + mess.sprintf( i18n( "Sync file \n...%s\ndoes not exist!\nNothing synced!\n"),fn.right( 30).latin1() ); + int result = QMessageBox::warning( this, "KO/Pi: Warning!", + mess ); + return; + } + int result = 0; + if ( !quick ) { + mess.sprintf( "Sync with file \n..."+fn.right( 25)+"\nfrom:\n%s\n",info.lastModified ().toString().latin1() ); + result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + mess, + i18n("Sync"), i18n("Cancel"), 0, + 0, 1 ); + } + if ( KOPrefs::instance()->mAskForPreferences ) + mView->edit_sync_options(); + if ( result == 0 ) { + qDebug("Now sycing ... "); + mView->syncCalendar( fn, true ); + if ( ! quick ) + KOPrefs::instance()->mLastSyncedLocalFile = fn; + } + +} + +void MainWindow::quickSyncLocalFile() +{ + qDebug("quickSyncLocalFile() "); + syncWithFile( KOPrefs::instance()->mLastSyncedLocalFile, false ); +} + +void MainWindow::syncSSH() +{ + QTime timer; + timer.start(); + qDebug("MainWindow::syncssh() "); + KOPrefs *p = KOPrefs::instance(); + QString localFile = p->mLocalTempFile; + QString remoteIP = p->mRemoteIP; + QString remoteUser = p->mRemoteUser; + QString remoteFile = p->mRemoteFile; + if ( p->mUsePassWd && p->mRemotePassWd.length() > 0 ) + remoteUser += ":" + p->mRemotePassWd; + + QString question = i18n("Do you really want\nto remote sync?\n \n") + + i18n("IP: " ) +remoteIP +"\n" + + i18n("User: " ) + remoteUser +"\n" ; + int maxlen = 30; + if ( QApplication::desktop()->width() > 320 ) + maxlen += 25; + if ( remoteFile.length() > maxlen ) + question += i18n("Remote file:\n..." ) + remoteFile.right(maxlen) +"\n"; + else + question += i18n("Remote file:\n " ) + remoteFile +"\n"; + if ( localFile.length() > maxlen ) + question += i18n("Local temp file:\n..." ) + localFile.right(maxlen) +"\n"; + else + question += i18n("Local temp file:\n " ) + localFile +"\n"; + + if ( QMessageBox::information( this, "KO/Pi Sync", + question, + i18n("Yes"), i18n("No"), + 0, 0 ) != 0 ) + return; + if ( !p->mUsePassWd ) { + QString pass = getPassword(); + if ( pass.length() > 0 ) + remoteUser += ":" + pass; + } + QString command = "scp " + remoteUser + "@" + remoteIP +":" + remoteFile +" " +localFile; + setCaption ( i18n( "Copy remote file to local machine..." ) ); + int fileSize = 0; + int result = system ( command ); + // 0 : okay + // 256: no such file or dir + // + qDebug("KO: Remote copy result(0 = okay): %d ",result ); + if ( result != 0 ) { + int len = maxlen; + while ( len < command.length() ) { + command.insert( len , "\n" ); + len += maxlen +2; + } + question = i18n("Sorry, the copy command failed!\nCommand was:\n") + command + "\n \nTry command on console to get more\ndetailed info about the reason.\n"; + QMessageBox::information( this, "KO/Pi Sync - ERROR", + question, + i18n("Okay!")) ; + return; + } + + + setCaption ( i18n( "Copying succeed. Syncing not yet implemented" ) ); + syncWithFile(localFile , true ); + return; +#if 0 + system ("scp zaurus@192.168.0.65:/home/zaurus/Applications/korganizer/mycalendar.ics /home/polo/Applications/korganizer/z_sync.ics"); + while ( timer.elapsed() < 5000 ) + qApp->processEvents(); + + qDebug("MainWindow::merging) "); + mView->syncCalendar( "/home/polo/Applications/korganizer/z_sync.ics", 0 ); + while ( mBlockSaveFlag ) + qApp->processEvents(); + save(); + system ("scp /home/polo/Applications/korganizer/mycalendar.ics zaurus@192.168.0.65:/home/zaurus/Applications/korganizer/mycalendar.ics"); +#endif + +} +*/ + diff --git a/kaddressbook/old_mainwindow.h b/kaddressbook/old_mainwindow.h new file mode 100644 index 0000000..7b6f68c --- a/dev/null +++ b/kaddressbook/old_mainwindow.h @@ -0,0 +1,122 @@ +#ifndef KADR_MAINWINDOW_H +#define KADR_MAINWINDOW_H + +#include <qmainwindow.h> +#include "kabcore.h" + +//US#include <qtimer.h> + +//US#include <libkcal/incidence.h> + +//US#include "simplealarmclient.h" + +//USclass QAction; +//USclass CalendarView; + +//US#ifdef DESKTOP_VERSION +//US#define QPEToolBar QToolBar +//US#define QPEMenuBar QMenuBar +//US#endif + +class KABCore; + +//USclass QPEToolBar; + +//US namespace KACore { +//USclass CalendarLocal; +//US} + +//USusing namespace KACore; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + public: + MainWindow( QWidget *parent = 0, const char *name = 0, QString command = ""); + ~MainWindow(); + + public slots: +// void configureAgenda( int ); + void recieve( const QCString& msg, const QByteArray& data ); + + protected slots: +/* + void setCaptionToDates(); + + void about(); + + void keyBindings(); + void aboutAutoSaving();; + void aboutKnownBugs(); + + void processIncidenceSelection( Incidence * ); + + void importQtopia(); + void importIcal(); + void importFile( QString, bool ); + void quickImportIcal(); + + void slotModifiedChanged( bool ); + + void save(); + void configureToolBar( int ); + void saveCalendar(); + void loadCalendar(); + void exportVCalendar(); + void checkAlarms(); + void writeAlarm(); + + + void syncSSH(); + void syncLocalFile(); + void syncWithFile( QString, bool ); + void quickSyncLocalFile(); + + + protected: + QString defaultFileName(); + + void enableIncidenceActions( bool ); +*/ + + private: +/* + bool mFlagKeyPressed; + bool mBlockAtStartup; + + QPEToolBar *iconToolBar; + + void initActions(); +*/ +/* void setDefaultPreferences(); + void keyPressEvent ( QKeyEvent * ) ; + void keyReleaseEvent ( QKeyEvent * ) ; + + QPopupMenu *configureToolBarMenu; + QPopupMenu *configureAgendaMenu; + CalendarLocal *mCalendar; + CalendarView *mView; + QString getPassword(); + QAction *mNewSubTodoAction; + + QAction *mShowAction; + QAction *mEditAction; + QAction *mDeleteAction; + + void closeEvent( QCloseEvent* ce ); + + SimpleAlarmClient mAlarmClient; + + QTimer mSaveTimer; + QTimer alarmTimer; + bool mBlockSaveFlag; + bool mCalendarModifiedFlag; + + QPixmap loadPixmap( QString ); +*/ + private: + KABCore *mCore; + +}; + +#endif diff --git a/kaddressbook/phoneeditwidget.cpp b/kaddressbook/phoneeditwidget.cpp new file mode 100644 index 0000000..78b9941 --- a/dev/null +++ b/kaddressbook/phoneeditwidget.cpp @@ -0,0 +1,532 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> +#include <qlabel.h> +#include <qtooltip.h> +#include <qpushbutton.h> +#include <qcheckbox.h> +#include <qstring.h> +#include <qlistbox.h> +#include <qlistview.h> +#include <qbuttongroup.h> + +#include <kbuttonbox.h> +#include <klistview.h> +#include <kapplication.h> +#include <qapplication.h> +#include <kconfig.h> +#include <klineedit.h> +#include <kcombobox.h> +#include <klocale.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> + +#include <kabc/phonenumber.h> + +#include "typecombo.h" + +#include "phoneeditwidget.h" + +PhoneEditWidget::PhoneEditWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QGridLayout *layout = new QGridLayout( this, 4, 1 ); +//US layout->setSpacing( KDialog::spacingHint() ); + layout->setSpacing( KDialogBase::spacingHintSmall() ); + + + + QLabel* label = new QLabel( this ); +//US loadIcon call is ambiguous. Add one more parameter +//US label->setPixmap( KGlobal::iconLoader()->loadIcon( "kaddressbook", KIcon::Desktop ) ); + label->setPixmap( KGlobal::iconLoader()->loadIcon( "kaddressbook", KIcon::Desktop, 0 ) ); + label->setAlignment( AlignCenter ); +//US layout->addMultiCellWidget( label, 0, 1, 3, 3 ); + layout->addWidget( label, 0, 0 ); + + QPushButton *editButton = new QPushButton( i18n( "Edit Phone Numbers..." ), + this ); + if ( QApplication::desktop()->width() < 640 ) + layout->addWidget( editButton, 0, 1 ); + else + layout->addMultiCellWidget( editButton, 0, 0, 1, 3); + + mPrefCombo = new PhoneTypeCombo( mPhoneList, this ); + mPrefEdit = new KLineEdit( this ); + //mPrefEdit->setMinimumWidth( int(mPrefEdit->sizeHint().width() * 1.5) ); + mPrefCombo->setLineEdit( mPrefEdit ); + layout->addWidget( mPrefCombo, 1, 0 ); + layout->addWidget( mPrefEdit, 1, 1 ); + int x = 1, y = 2; + if ( QApplication::desktop()->width() < 640 ) { + ++x; + y = 0; + } + mSecondCombo = new PhoneTypeCombo( mPhoneList, this ); + mSecondEdit = new KLineEdit( this ); + mSecondCombo->setLineEdit( mSecondEdit ); + layout->addWidget( mSecondCombo, x, y++ ); + layout->addWidget( mSecondEdit, x, y++ ); + + y = 0; + ++x; + mThirdCombo = new PhoneTypeCombo( mPhoneList, this ); + mThirdEdit = new KLineEdit( this ); + mThirdCombo->setLineEdit( mThirdEdit ); + layout->addWidget( mThirdCombo, x, y++ ); + layout->addWidget( mThirdEdit, x, y++ ); + if ( QApplication::desktop()->width() < 640 ) { + ++x; + y = 0; + } + mFourthCombo = new PhoneTypeCombo( mPhoneList, this ); + mFourthEdit = new KLineEdit( this ); + mFourthCombo->setLineEdit( mFourthEdit ); + layout->addWidget( mFourthCombo, x, y++ ); + layout->addWidget( mFourthEdit, x, y++ ); + + // Four numbers don't fit in the current dialog + if ( QApplication::desktop()->width() < 640 ) { + mFourthCombo->hide(); + mFourthEdit->hide(); + } else { + QFontMetrics fm ( font () ) ; + int wid = fm.width( "Messenger" ) +60; + mPrefCombo->setMaximumWidth( wid ); + mSecondCombo->setMaximumWidth( wid ); + mThirdCombo->setMaximumWidth( wid ); + mFourthCombo->setMaximumWidth( wid ); + } + + + connect( mPrefEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( slotPrefEditChanged() ) ); + connect( mSecondEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( slotSecondEditChanged() ) ); + connect( mThirdEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( slotThirdEditChanged() ) ); + connect( mFourthEdit, SIGNAL( textChanged( const QString& ) ), + SLOT( slotFourthEditChanged() ) ); + + connect( editButton, SIGNAL( clicked() ), SLOT( edit() ) ); + + connect( mPrefCombo, SIGNAL( activated( int ) ), + SLOT( updatePrefEdit() ) ); + connect( mSecondCombo, SIGNAL( activated( int ) ), + SLOT( updateSecondEdit() ) ); + connect( mThirdCombo, SIGNAL( activated( int ) ), + SLOT( updateThirdEdit() ) ); + connect( mFourthCombo, SIGNAL( activated( int ) ), + SLOT( updateFourthEdit() ) ); +} + +PhoneEditWidget::~PhoneEditWidget() +{ +} + +void PhoneEditWidget::setPhoneNumbers( const KABC::PhoneNumber::List &list ) +{ + mPhoneList.clear(); + + // Insert types for existing numbers. + mPrefCombo->insertTypeList( list ); + + QValueList<int> defaultTypes; + defaultTypes << KABC::PhoneNumber::Home; + defaultTypes << KABC::PhoneNumber::Work; + defaultTypes << KABC::PhoneNumber::Cell; + defaultTypes << ( KABC::PhoneNumber::Work | KABC::PhoneNumber::Fax ); + defaultTypes << ( KABC::PhoneNumber::Home | KABC::PhoneNumber::Fax ); + + // Insert default types. + // Doing this for mPrefCombo is enough because the list is shared by all + // combos. + QValueList<int>::ConstIterator it; + for( it = defaultTypes.begin(); it != defaultTypes.end(); ++it ) { + if ( !mPrefCombo->hasType( *it ) ) + mPrefCombo->insertType( list, *it, PhoneNumber( "", *it ) ); + } + + updateCombos(); + + mPrefCombo->selectType( defaultTypes[ 0 ] ); + mSecondCombo->selectType( defaultTypes[ 1 ] ); + mThirdCombo->selectType( defaultTypes[ 2 ] ); + mFourthCombo->selectType( defaultTypes[ 3 ] ); + + updateLineEdits(); +} + +void PhoneEditWidget::updateLineEdits() +{ + updatePrefEdit(); + updateSecondEdit(); + updateThirdEdit(); + updateFourthEdit(); +} + +void PhoneEditWidget::updateCombos() +{ + mPrefCombo->updateTypes(); + mSecondCombo->updateTypes(); + mThirdCombo->updateTypes(); + mFourthCombo->updateTypes(); +} + +KABC::PhoneNumber::List PhoneEditWidget::phoneNumbers() +{ + KABC::PhoneNumber::List retList; + + KABC::PhoneNumber::List::Iterator it; + for ( it = mPhoneList.begin(); it != mPhoneList.end(); ++it ) + if ( !(*it).number().isEmpty() ) + retList.append( *it ); + + return retList; +} + +void PhoneEditWidget::edit() +{ + PhoneEditDialog dlg( mPhoneList, this ); + + if ( dlg.exec() ) { + if ( dlg.changed() ) { + mPhoneList = dlg.phoneNumbers(); + updateCombos(); + emit modified(); + } + } +} + +void PhoneEditWidget::updatePrefEdit() +{ + updateEdit( mPrefCombo ); +} + +void PhoneEditWidget::updateSecondEdit() +{ + updateEdit( mSecondCombo ); +} + +void PhoneEditWidget::updateThirdEdit() +{ + updateEdit( mThirdCombo ); +} + +void PhoneEditWidget::updateFourthEdit() +{ + updateEdit( mFourthCombo ); +} + +void PhoneEditWidget::updateEdit( PhoneTypeCombo *combo ) +{ + QLineEdit *edit = combo->lineEdit(); + if ( !edit ) + return; + +#if 0 + if ( edit == mPrefEdit ) kdDebug(5720) << " prefEdit" << endl; + if ( edit == mSecondEdit ) kdDebug(5720) << " secondEdit" << endl; + if ( edit == mThirdEdit ) kdDebug(5720) << " thirdEdit" << endl; + if ( edit == mFourthEdit ) kdDebug(5720) << " fourthEdit" << endl; +#endif + + PhoneNumber::List::Iterator it = combo->selectedElement(); + if ( it != mPhoneList.end() ) { + edit->setText( (*it).number() ); + } else { + kdDebug(5720) << "PhoneEditWidget::updateEdit(): no selected element" << endl; + } +} + +void PhoneEditWidget::slotPrefEditChanged() +{ + updatePhoneNumber( mPrefCombo ); +} + +void PhoneEditWidget::slotSecondEditChanged() +{ + updatePhoneNumber( mSecondCombo ); +} + +void PhoneEditWidget::slotThirdEditChanged() +{ + updatePhoneNumber( mThirdCombo ); +} + +void PhoneEditWidget::slotFourthEditChanged() +{ + updatePhoneNumber( mFourthCombo ); +} + +void PhoneEditWidget::updatePhoneNumber( PhoneTypeCombo *combo ) +{ + QLineEdit *edit = combo->lineEdit(); + if ( !edit ) return; + + PhoneNumber::List::Iterator it = combo->selectedElement(); + if ( it != mPhoneList.end() ) { + (*it).setNumber( edit->text() ); + } else { + kdDebug(5720) << "PhoneEditWidget::updatePhoneNumber(): no selected element" + << endl; + } + + updateOtherEdit( combo, mPrefCombo ); + updateOtherEdit( combo, mSecondCombo ); + updateOtherEdit( combo, mThirdCombo ); + updateOtherEdit( combo, mFourthCombo ); + + emit modified(); +} + +void PhoneEditWidget::updateOtherEdit( PhoneTypeCombo *combo, PhoneTypeCombo *otherCombo ) +{ + if ( combo == otherCombo ) return; + + if ( combo->currentItem() == otherCombo->currentItem() ) { + updateEdit( otherCombo ); + } +} + +/////////////////////////////////////////// +// PhoneEditDialog + +class PhoneViewItem : public QListViewItem +{ +public: + PhoneViewItem( QListView *parent, const KABC::PhoneNumber &number ); + + void setPhoneNumber( const KABC::PhoneNumber &number ) + { + mPhoneNumber = number; + makeText(); + } + + QString key() { return mPhoneNumber.id(); } + QString country() { return ""; } + QString region() { return ""; } + QString number() { return ""; } + + KABC::PhoneNumber phoneNumber() { return mPhoneNumber; } + +private: + void makeText(); + + KABC::PhoneNumber mPhoneNumber; +}; + +PhoneViewItem::PhoneViewItem( QListView *parent, const KABC::PhoneNumber &number ) + : QListViewItem( parent ), mPhoneNumber( number ) +{ + makeText(); +} + +void PhoneViewItem::makeText() +{ + /** + * Will be used in future versions of kaddressbook/libkabc + + setText( 0, mPhoneNumber.country() ); + setText( 1, mPhoneNumber.region() ); + setText( 2, mPhoneNumber.number() ); + setText( 3, mPhoneNumber.typeLabel() ); + */ + + setText( 0, mPhoneNumber.number() ); + setText( 1, mPhoneNumber.typeLabel() ); +} + +PhoneEditDialog::PhoneEditDialog( const KABC::PhoneNumber::List &list, QWidget *parent, const char *name ) + : KDialogBase( KDialogBase::Plain, i18n( "Edit Phone Numbers" ), + KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, + parent, name, true) +{ + mPhoneNumberList = list; + + QWidget *page = plainPage(); + + QGridLayout *layout = new QGridLayout( page, 1, 2 ); + layout->setSpacing( spacingHint() ); + + mListView = new KListView( page ); + mListView->setAllColumnsShowFocus( true ); + mListView->addColumn( i18n( "Number" ) ); + mListView->addColumn( i18n( "Type" ) ); + + KButtonBox *buttonBox = new KButtonBox( page, Vertical ); + + buttonBox->addButton( i18n( "&Add..." ), this, SLOT( slotAddPhoneNumber() ) ); + mEditButton = buttonBox->addButton( i18n( "&Edit..." ), this, SLOT( slotEditPhoneNumber() ) ); + mEditButton->setEnabled( false ); + mRemoveButton = buttonBox->addButton( i18n( "&Remove" ), this, SLOT( slotRemovePhoneNumber() ) ); + mRemoveButton->setEnabled( false ); + buttonBox->layout(); + + layout->addWidget( mListView, 0, 0 ); + layout->addWidget( buttonBox, 0, 1 ); + + connect( mListView, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()) ); + connect( mListView, SIGNAL(doubleClicked( QListViewItem *, const QPoint &, int )), this, SLOT( slotEditPhoneNumber())); + + KABC::PhoneNumber::List::Iterator it; + for ( it = mPhoneNumberList.begin(); it != mPhoneNumberList.end(); ++it ) + new PhoneViewItem( mListView, *it ); + + mChanged = false; +} + +PhoneEditDialog::~PhoneEditDialog() +{ +} + +void PhoneEditDialog::slotAddPhoneNumber() +{ + KABC::PhoneNumber tmp( "", 0 ); + PhoneTypeDialog dlg( tmp, this ); + + if ( dlg.exec() ) { + KABC::PhoneNumber phoneNumber = dlg.phoneNumber(); + mPhoneNumberList.append( phoneNumber ); + new PhoneViewItem( mListView, phoneNumber ); + + mChanged = true; + } +} + +void PhoneEditDialog::slotRemovePhoneNumber() +{ + PhoneViewItem *item = static_cast<PhoneViewItem*>( mListView->currentItem() ); + if ( !item ) + return; + + mPhoneNumberList.remove( item->phoneNumber() ); + QListViewItem *currItem = mListView->currentItem(); + mListView->takeItem( currItem ); + delete currItem; + + mChanged = true; +} + +void PhoneEditDialog::slotEditPhoneNumber() +{ + PhoneViewItem *item = static_cast<PhoneViewItem*>( mListView->currentItem() ); + if ( !item ) + return; + + PhoneTypeDialog dlg( item->phoneNumber(), this ); + + if ( dlg.exec() ) { + slotRemovePhoneNumber(); + KABC::PhoneNumber phoneNumber = dlg.phoneNumber(); + mPhoneNumberList.append( phoneNumber ); + new PhoneViewItem( mListView, phoneNumber ); + + mChanged = true; + } +} + +void PhoneEditDialog::slotSelectionChanged() +{ + bool state = ( mListView->currentItem() != 0 ); + + mRemoveButton->setEnabled( state ); + mEditButton->setEnabled( state ); +} + +const KABC::PhoneNumber::List &PhoneEditDialog::phoneNumbers() +{ + return mPhoneNumberList; +} + +bool PhoneEditDialog::changed() const +{ + return mChanged; +} + +/////////////////////////////////////////// +// PhoneTypeDialog +PhoneTypeDialog::PhoneTypeDialog( const KABC::PhoneNumber &phoneNumber, + QWidget *parent, const char *name) + : KDialogBase( KDialogBase::Plain, i18n( "Edit Phone Number" ), + KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, + parent, name, true), mPhoneNumber( phoneNumber ) +{ + QWidget *page = plainPage(); + QLabel *label = 0; + QGridLayout *layout = new QGridLayout( page, 3, 2, marginHint(), spacingHint() ); + + label = new QLabel( i18n( "Number:" ), page ); + layout->addWidget( label, 0, 0 ); + mNumber = new KLineEdit( page ); + layout->addWidget( mNumber, 0, 1 ); + + mPreferredBox = new QCheckBox( i18n( "This is the preferred phone number" ), page ); + layout->addMultiCellWidget( mPreferredBox, 1, 1, 0, 1 ); + + mGroup = new QButtonGroup( 2, Horizontal, i18n( "Types" ), page ); + layout->addMultiCellWidget( mGroup, 2, 2, 0, 1 ); + + // fill widgets + mNumber->setText( mPhoneNumber.number() ); + + mTypeList = KABC::PhoneNumber::typeList(); + mTypeList.remove( KABC::PhoneNumber::Pref ); + + KABC::PhoneNumber::TypeList::Iterator it; + for ( it = mTypeList.begin(); it != mTypeList.end(); ++it ) + new QCheckBox( KABC::PhoneNumber::typeLabel( *it ), mGroup ); + + for ( int i = 0; i < mGroup->count(); ++i ) { + int type = mPhoneNumber.type(); + QCheckBox *box = (QCheckBox*)mGroup->find( i ); + box->setChecked( type & mTypeList[ i ] ); + } + + mPreferredBox->setChecked( mPhoneNumber.type() & KABC::PhoneNumber::Pref ); +} + +KABC::PhoneNumber PhoneTypeDialog::phoneNumber() +{ + mPhoneNumber.setNumber( mNumber->text() ); + + int type = 0; + for ( int i = 0; i < mGroup->count(); ++i ) { + QCheckBox *box = (QCheckBox*)mGroup->find( i ); + if ( box->isChecked() ) + type += mTypeList[ i ]; + } + + if ( mPreferredBox->isChecked() ) + mPhoneNumber.setType( type | KABC::PhoneNumber::Pref ); + else + mPhoneNumber.setType( type & ~KABC::PhoneNumber::Pref ); + + return mPhoneNumber; +} + +#ifndef KAB_EMBEDDED +#include "phoneeditwidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/phoneeditwidget.h b/kaddressbook/phoneeditwidget.h new file mode 100644 index 0000000..7fe4bc0 --- a/dev/null +++ b/kaddressbook/phoneeditwidget.h @@ -0,0 +1,147 @@ +#ifndef PHONEEDITWIDGET_H +#define PHONEEDITWIDGET_H +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kdialogbase.h> + +#include "addresseeconfig.h" +#include "typecombo.h" + +class QButtonGroup; +class QCheckBox; + +class KListView; +class KLineEdit; +class KComboBox; + +typedef TypeCombo<KABC::PhoneNumber> PhoneTypeCombo; + +/** + Widget for editing phone numbers. +*/ +class PhoneEditWidget : public QWidget +{ + Q_OBJECT + + public: + PhoneEditWidget( QWidget *parent, const char *name = 0 ); + ~PhoneEditWidget(); + + void setPhoneNumbers( const KABC::PhoneNumber::List &list ); + KABC::PhoneNumber::List phoneNumbers(); + + void updateTypeCombo( const KABC::PhoneNumber::List&, KComboBox* ); + KABC::PhoneNumber currentPhoneNumber( KComboBox*, int ); + + signals: + void modified(); + + private slots: + void edit(); + + void updatePrefEdit(); + void updateSecondEdit(); + void updateThirdEdit(); + void updateFourthEdit(); + + void slotPrefEditChanged(); + void slotSecondEditChanged(); + void slotThirdEditChanged(); + void slotFourthEditChanged(); + + protected: + void updateLineEdits(); + void updateCombos(); + + private: + void updateEdit( PhoneTypeCombo *combo ); + void updatePhoneNumber( PhoneTypeCombo *combo ); + void updateOtherEdit( PhoneTypeCombo *combo, PhoneTypeCombo *otherCombo ); + + PhoneTypeCombo *mPrefCombo; + PhoneTypeCombo *mSecondCombo; + PhoneTypeCombo *mThirdCombo; + PhoneTypeCombo *mFourthCombo; + + KLineEdit *mPrefEdit; + KLineEdit *mSecondEdit; + KLineEdit *mThirdEdit; + KLineEdit *mFourthEdit; + + KABC::PhoneNumber::List mPhoneList; +}; + +/** + Dialog for editing lists of phonenumbers. +*/ +class PhoneEditDialog : public KDialogBase +{ + Q_OBJECT + + public: + PhoneEditDialog( const KABC::PhoneNumber::List &list, QWidget *parent, const char *name = 0 ); + ~PhoneEditDialog(); + + const KABC::PhoneNumber::List &phoneNumbers(); + bool changed() const; + + protected slots: + void slotAddPhoneNumber(); + void slotRemovePhoneNumber(); + void slotEditPhoneNumber(); + void slotSelectionChanged(); + + private: + KABC::PhoneNumber::List mPhoneNumberList; + KABC::PhoneNumber::TypeList mTypeList; + KComboBox *mTypeBox; + KListView *mListView; + + QPushButton *mRemoveButton; + QPushButton *mEditButton; + + bool mChanged; +}; + +/** + Dialog for editing phone number types. +*/ +class PhoneTypeDialog : public KDialogBase +{ + Q_OBJECT +public: + PhoneTypeDialog( const KABC::PhoneNumber &phoneNumber, QWidget *parent, const char *name = 0 ); + + KABC::PhoneNumber phoneNumber(); + +private: + KABC::PhoneNumber mPhoneNumber; + KABC::PhoneNumber::TypeList mTypeList; + + QButtonGroup *mGroup; + QCheckBox *mPreferredBox; + KLineEdit *mNumber; +}; + +#endif diff --git a/kaddressbook/secrecywidget.cpp b/kaddressbook/secrecywidget.cpp new file mode 100644 index 0000000..4a2acc8 --- a/dev/null +++ b/kaddressbook/secrecywidget.cpp @@ -0,0 +1,70 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> + +#include <kabc/secrecy.h> +#include <kcombobox.h> +#include <kdialog.h> + +#include "secrecywidget.h" + +SecrecyWidget::SecrecyWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + mSecrecyCombo = new KComboBox( this ); + layout->addWidget( mSecrecyCombo ); + + KABC::Secrecy::TypeList list = KABC::Secrecy::typeList(); + KABC::Secrecy::TypeList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) + mSecrecyCombo->insertItem( KABC::Secrecy::typeLabel( *it ), *it ); + + connect( mSecrecyCombo, SIGNAL( activated( const QString& ) ), + SIGNAL( changed() ) ); +} + +SecrecyWidget::~SecrecyWidget() +{ +} + +void SecrecyWidget::setSecrecy( const KABC::Secrecy &secrecy ) +{ +//US to avoid an indexoutofbounds error if value is invalid + if (secrecy.isValid()) + mSecrecyCombo->setCurrentItem( secrecy.type() ); +} + +KABC::Secrecy SecrecyWidget::secrecy() const +{ + KABC::Secrecy secrecy; + secrecy.setType( mSecrecyCombo->currentItem() ); + + return secrecy; +} + +#ifndef KAB_EMBEDDED +#include "secrecywidget.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/secrecywidget.h b/kaddressbook/secrecywidget.h new file mode 100644 index 0000000..96e6905 --- a/dev/null +++ b/kaddressbook/secrecywidget.h @@ -0,0 +1,50 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef SECRECYWIDGET_H +#define SECRECYWIDGET_H + +#include <qwidget.h> + +namespace KABC { class Secrecy; } +class KComboBox; + +class SecrecyWidget : public QWidget +{ + Q_OBJECT + + public: + SecrecyWidget( QWidget *parent, const char *name = 0 ); + ~SecrecyWidget(); + + void setSecrecy( const KABC::Secrecy &secrecy ); + KABC::Secrecy secrecy() const; + + signals: + void changed(); + + private: + KComboBox *mSecrecyCombo; +}; + +#endif diff --git a/kaddressbook/typecombo.h b/kaddressbook/typecombo.h new file mode 100644 index 0000000..191273d --- a/dev/null +++ b/kaddressbook/typecombo.h @@ -0,0 +1,193 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef TYPECOMBO_H +#define TYPECOMBO_H + +#include <kabc/phonenumber.h> +#include <kcombobox.h> + +/** + Combo box for type information of Addresses and Phone numbers. +*/ +template <class T> +class TypeCombo : public KComboBox +{ + public: + typedef typename T::List List; + typedef typename T::List::Iterator Iterator; + + TypeCombo( List &list, QWidget *parent, const char *name = 0 ); + + void setLineEdit( QLineEdit *edit ) { mLineEdit = edit; } + QLineEdit *lineEdit() const { return mLineEdit; } + + void updateTypes(); + + void selectType( int type ); + + int selectedType(); + + Iterator selectedElement(); + + void insertType( const List &list, int type, + const T &defaultObject ); + void insertTypeList( const List &list ); + + bool hasType( int type ); + + private: + List &mTypeList; + QLineEdit *mLineEdit; +}; + +template <class T> +#ifdef _WIN32_ +TypeCombo<T>::TypeCombo( typename TypeCombo::List &list, QWidget *parent, +#else +TypeCombo<T>::TypeCombo( TypeCombo::List &list, QWidget *parent, + +#endif + const char *name ) + : KComboBox( parent), +//US my kde version has no KComboBox constructor witgh two parameters +//US : KComboBox( parent, name ), + mTypeList( list ) +{ +} + +template <class T> +void TypeCombo<T>::updateTypes() +{ + // Remember current item + QString currentId; + int current = currentItem(); + if ( current >= 0 ) currentId = mTypeList[ current ].id(); + + clear(); + + QMap<int,int> labelCount; + + uint i; + for( i = 0; i < mTypeList.count(); ++i ) { + int type = ( mTypeList[ i ].type() & ~( T::Pref ) ); + QString label = mTypeList[ i ].typeLabel( type ); + int count = 1; + if ( labelCount.contains( type ) ) { + count = labelCount[ type ] + 1; + } + labelCount[ type ] = count; + if ( count > 1 ) { + label = i18n("label (number)", "%1 (%2)").arg( label ) + .arg( QString::number( count ) ); + } + insertItem( label ); + } + + // Restore previous current item + if ( !currentId.isEmpty() ) { + for( i = 0; i < mTypeList.count(); ++i ) { + if ( mTypeList[ i ].id() == currentId ) { + setCurrentItem( i ); + break; + } + } + } +} + +template <class T> +void TypeCombo<T>::selectType( int type ) +{ + uint i; + for( i = 0; i < mTypeList.count(); ++i ) { + if ( (mTypeList[ i ].type() & ~T::Pref) == type ) { + setCurrentItem( i ); + break; + } + } +} + +template <class T> +int TypeCombo<T>::selectedType() +{ + return mTypeList[ currentItem() ].type(); +} + +template <class T> +typename TypeCombo<T>::Iterator TypeCombo<T>::selectedElement() +{ + return mTypeList.at( currentItem() ); +} + +template <class T> +#ifdef _WIN32_ +void TypeCombo<T>::insertType( typename const TypeCombo::List &list, int type, +#else +void TypeCombo<T>::insertType( const TypeCombo::List &list, int type, +#endif + const T &defaultObject ) +{ + uint i; + for ( i = 0; i < list.count(); ++i ) { + if ( list[ i ].type() == type ) { + mTypeList.append( list[ i ] ); + break; + } + } + if ( i == list.count() ) { + mTypeList.append( defaultObject ); + } +} + +template <class T> +#ifdef _WIN32_ +void TypeCombo<T>::insertTypeList( typename const TypeCombo::List &list ) +#else +void TypeCombo<T>::insertTypeList( const TypeCombo::List &list ) + +#endif +{ + uint i; + for ( i = 0; i < list.count(); ++i ) { + uint j; + for( j = 0; j < mTypeList.count(); ++j ) { + if ( list[ i ].id() == mTypeList[ j ].id() ) break; + } + if ( j == mTypeList.count() ) { + mTypeList.append( list[ i ] ); + } + } +} + +template <class T> +bool TypeCombo<T>::hasType( int type ) +{ + for( uint i = 0; i < mTypeList.count(); ++i ) { + if ( ( mTypeList[ i ].type() & ~T::Pref ) == type ) + return true; + } + + return false; +} + +#endif diff --git a/kaddressbook/undo.cpp b/kaddressbook/undo.cpp new file mode 100644 index 0000000..4442087 --- a/dev/null +++ b/kaddressbook/undo.cpp @@ -0,0 +1,119 @@ +/* + This file is part of KAddressBook. + Copyright (C) 1999 Don Sanders <sanders@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "undo.h" + +/////////////////////////////// +// StackBase + +void StackBase::push(Command *c) +{ + mCommandStack.push(c); + emit changed(); +} + +bool StackBase::isEmpty() +{ + return mCommandStack.isEmpty(); +} + +Command *StackBase::top() +{ + return mCommandStack.top(); +} + +void StackBase::clear() +{ + mCommandStack.clear(); + emit changed(); +} + +Command *StackBase::pop() +{ + Command *c = mCommandStack.pop(); + if (c) + emit changed(); + + return c; +} + +/////////////////////////////// +// UndoStack + +UndoStack* UndoStack::instance_ = 0; + +UndoStack::UndoStack() + : StackBase() +{ + // setAutoDelete( true ); +} + +UndoStack* UndoStack::instance() +{ + if (!instance_) + instance_ = new UndoStack(); + return instance_; +} + +void UndoStack::undo() +{ + if (isEmpty()) + return; + + Command *command = pop(); + command->undo(); + + RedoStack::instance()->push( command ); +} + +//////////////////// +// RedoStack + +RedoStack* RedoStack::instance_ = 0; + +RedoStack::RedoStack() +{ + mCommandStack.setAutoDelete( true ); +} + +RedoStack* RedoStack::instance() +{ + if (!instance_) + instance_ = new RedoStack(); + return instance_; +} + +void RedoStack::redo() +{ + Command *command; + if (isEmpty()) + return; + + command = pop(); + command->redo(); + UndoStack::instance()->push( command ); +} + +#ifndef KAB_EMBEDDED +#include "undo.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/undo.h b/kaddressbook/undo.h new file mode 100644 index 0000000..843bc26 --- a/dev/null +++ b/kaddressbook/undo.h @@ -0,0 +1,95 @@ +/* + This file is part of KAddressBook. + Copyright (C) 1999 Don Sanders <sanders@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef UNDO_H +#define UNDO_H + +#include <qobject.h> +#include <qptrstack.h> +#include <qstring.h> + +class Command +{ +public: + Command() {} + virtual ~Command() {}; + virtual QString name() = 0; + virtual void redo() = 0; // egcs requires these methods to have + virtual void undo() = 0; // implementations (Seems like a bug) + // pure virtual may not work +}; + +/** The Undo and Redo stacks now no longer inherit directly from a stack. +* They now contain a stack internally and inherit from StackBase, which +* has a signal for when the stack is modified. This is need to keep +* the edit menu and toolbar up to date. +* +* Really this is a simple observable stack. +*/ +class StackBase : public QObject +{ + Q_OBJECT + + public: + StackBase() : QObject() {} + + void push(Command *c); + bool isEmpty(); + Command *top(); + void clear(); + + signals: + void changed(); + + protected: + /** Protect the pop method so users must call undo/redo to properly + * use the stack, however the subclasses need it to modify the stack. + */ + Command *pop(); + + QPtrStack<Command> mCommandStack; +}; + +class UndoStack : public StackBase +{ +public: + static UndoStack *instance(); + void undo(); + +protected: + UndoStack(); + static UndoStack* instance_; +}; + +class RedoStack : public StackBase +{ +public: + static RedoStack *instance(); + void redo(); + +protected: + RedoStack(); + static RedoStack* instance_; +}; + +#endif diff --git a/kaddressbook/undocmds.cpp b/kaddressbook/undocmds.cpp new file mode 100644 index 0000000..db773be --- a/dev/null +++ b/kaddressbook/undocmds.cpp @@ -0,0 +1,240 @@ +/* + This file is part of KAddressBook. + Copyright (C) 1999 Don Sanders <sanders@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qtextstream.h> + +#include <qapplication.h> +#include <qclipboard.h> + +#include <klocale.h> +#include <kdebug.h> +#include <kapplication.h> +#include <kabc/addressbook.h> + +#include "addresseeutil.h" +#include "addresseeconfig.h" +#include "kabcore.h" + +#include "undocmds.h" + +///////////////////////////////// +// PwDelete Methods + +PwDeleteCommand::PwDeleteCommand(KABC::AddressBook *doc, + const QStringList &uidList) + : Command(), mDocument(doc), mAddresseeList(), mUidList(uidList) +{ + redo(); +} + +PwDeleteCommand::~PwDeleteCommand() +{ +} + +QString PwDeleteCommand::name() +{ + return i18n( "Delete" ); +} + +void PwDeleteCommand::undo() +{ + // Put it back in the document + KABC::Addressee::List::Iterator iter; + for (iter = mAddresseeList.begin(); iter != mAddresseeList.end(); ++iter) + { + mDocument->insertAddressee(*iter); + } + + mAddresseeList.clear(); +} + +void PwDeleteCommand::redo() +{ + // Just remove it from the document. This is enough to make the user + // Think the item has been deleted + KABC::Addressee a; + QStringList::Iterator iter; + for (iter = mUidList.begin(); iter != mUidList.end(); ++iter) + { + a = mDocument->findByUid(*iter); + mDocument->removeAddressee(a); + mAddresseeList.append(a); + AddresseeConfig::instance()->remove(a.uid()); + } +} + +///////////////////////////////// +// PwPaste Methods + +PwPasteCommand::PwPasteCommand( KABCore *core, const KABC::Addressee::List &list ) + : Command(), mCore( core ), mAddresseeList( list ) +{ + redo(); +} + +QString PwPasteCommand::name() +{ + return i18n( "Paste" ); +} + +void PwPasteCommand::undo() +{ + KABC::Addressee::List::Iterator it; + for ( it = mAddresseeList.begin(); it != mAddresseeList.end(); ++it ) + mCore->addressBook()->removeAddressee( *it ); +} + +void PwPasteCommand::redo() +{ + QStringList uids; + KABC::Addressee::List::Iterator it; + for ( it = mAddresseeList.begin(); it != mAddresseeList.end(); ++it ) { + /* we have to set a new uid for the contact, otherwise insertAddressee() + ignore it. + */ + (*it).setUid( KApplication::randomString( 10 ) ); + uids.append( (*it).uid() ); + mCore->addressBook()->insertAddressee( *it ); + } + + QStringList::Iterator uidIt; + for ( uidIt = uids.begin(); uidIt != uids.end(); ++uidIt ) + mCore->editContact( *uidIt ); +} + +///////////////////////////////// +// PwNew Methods + +PwNewCommand::PwNewCommand( KABC::AddressBook *doc, const KABC::Addressee &a ) + : Command(), mDocument( doc ), mA( a ) +{ + mDocument->insertAddressee(mA); +} + +PwNewCommand::~PwNewCommand() +{ +} + +QString PwNewCommand::name() +{ + return i18n( "New Contact" ); +} + +void PwNewCommand::undo() +{ + mDocument->removeAddressee( mA ); +} + +void PwNewCommand::redo() +{ + mDocument->insertAddressee( mA ); +} + +///////////////////////////////// +// PwEdit Methods + +PwEditCommand::PwEditCommand(KABC::AddressBook *doc, + const KABC::Addressee &oldA, + const KABC::Addressee &newA ) + : Command(), mDocument(doc), mOldA(oldA), mNewA(newA) +{ + redo(); +} + +PwEditCommand::~PwEditCommand() +{ +} + +QString PwEditCommand::name() +{ + return i18n( "Entry Edit" ); +} + +void PwEditCommand::undo() +{ + mDocument->insertAddressee(mOldA); +} + +void PwEditCommand::redo() +{ + mDocument->insertAddressee(mNewA); +} + +///////////////////////////////// +// PwCut Methods + +PwCutCommand::PwCutCommand(KABC::AddressBook *doc, const QStringList &uidList) + : Command(), mDocument(doc), mAddresseeList(), mUidList(uidList), + mClipText(), mOldText() +{ + redo(); +} + +QString PwCutCommand::name() +{ + return i18n( "Cut" ); +} + +void PwCutCommand::undo() +{ + KABC::Addressee::List::Iterator iter; + for (iter = mAddresseeList.begin(); iter != mAddresseeList.end(); ++iter) + { + mDocument->insertAddressee(*iter); + } + mAddresseeList.clear(); + + QClipboard *cb = QApplication::clipboard(); +//US +#ifndef KAB_EMBEDDED + kapp->processEvents(); +#else //KAB_EMBEDDED + qApp->processEvents(); +#endif //KAB_EMBEDDED + cb->setText( mOldText ); +} + +void PwCutCommand::redo() +{ + KABC::Addressee a; + QStringList::Iterator iter; + for (iter = mUidList.begin(); iter != mUidList.end(); ++iter) + { + a = mDocument->findByUid(*iter); + mDocument->removeAddressee(a); + mAddresseeList.append(a); + } + + // Convert to clipboard + mClipText = AddresseeUtil::addresseesToClipboard(mAddresseeList); + + QClipboard *cb = QApplication::clipboard(); + mOldText = cb->text(); +//US +#ifndef KAB_EMBEDDED + kapp->processEvents(); +#else //KAB_EMBEDDED + qApp->processEvents(); +#endif //KAB_EMBEDDED + cb->setText( mClipText ); +} diff --git a/kaddressbook/undocmds.h b/kaddressbook/undocmds.h new file mode 100644 index 0000000..c3f23cc --- a/dev/null +++ b/kaddressbook/undocmds.h @@ -0,0 +1,117 @@ +/* + This file is part of KAddressBook. + Copyright (C) 1999 Don Sanders <sanders@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef UNDOCMDS_H +#define UNDOCMDS_H +// +// Commands for undo/redo functionality. + +#include <qstring.h> +#include <qstringlist.h> + +#include <kabc/addressee.h> + +#include "undo.h" + +namespace KABC { + class AddressBook; +} + +class KABCore; + +class PwDeleteCommand : public Command +{ +public: + PwDeleteCommand(KABC::AddressBook *doc, const QStringList &uidList ); + virtual ~PwDeleteCommand(); + virtual QString name(); + virtual void undo(); + virtual void redo(); + +private: + KABC::AddressBook *mDocument; + KABC::Addressee::List mAddresseeList; + QStringList mUidList; +}; + +class PwPasteCommand : public Command +{ + public: + PwPasteCommand( KABCore *core, const KABC::Addressee::List &list ); + virtual QString name(); + virtual void undo(); + virtual void redo(); + + private: + KABCore *mCore; + KABC::Addressee::List mAddresseeList; +}; + +class PwCutCommand : public Command +{ +public: + PwCutCommand(KABC::AddressBook *doc, const QStringList &uidList); + virtual QString name(); + virtual void undo(); + virtual void redo(); + +private: + KABC::AddressBook *mDocument; + KABC::Addressee::List mAddresseeList; + QStringList mUidList; + QString mClipText; + QString mOldText; +}; + +class PwNewCommand : public Command +{ +public: + PwNewCommand(KABC::AddressBook *doc, const KABC::Addressee &a ); + ~PwNewCommand(); + virtual QString name(); + virtual void undo(); + virtual void redo(); + +private: + KABC::AddressBook *mDocument; + KABC::Addressee mA; +}; + +class PwEditCommand : public Command +{ +public: + PwEditCommand(KABC::AddressBook *doc, + const KABC::Addressee &oldA, + const KABC::Addressee &newA); + virtual ~PwEditCommand(); + virtual QString name(); + virtual void undo(); + virtual void redo(); + +private: + KABC::AddressBook *mDocument; + KABC::Addressee mOldA; + KABC::Addressee mNewA; +}; + +#endif diff --git a/kaddressbook/viewconfigurefieldspage.cpp b/kaddressbook/viewconfigurefieldspage.cpp new file mode 100644 index 0000000..2c827eb --- a/dev/null +++ b/kaddressbook/viewconfigurefieldspage.cpp @@ -0,0 +1,345 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KAB_EMBEDDED +#include <kcombobox.h> +#include <qpushbutton.h> +#include <kdebug.h> + +#else //KAB_EMBEDDED +#include <qcombobox.h> +#endif //KAB_EMBEDDED + +#include <kiconloader.h> +#include <kdialog.h> +#include <klocale.h> + +#include <qtoolbutton.h> +#include <qlabel.h> +#include <qlistbox.h> +#include <qlayout.h> + +#include "viewconfigurefieldspage.h" + +class FieldItem : public QListBoxText +{ + public: + FieldItem( QListBox *parent, KABC::Field *field ) + : QListBoxText( parent, field->label() ), mField( field ) {} + + FieldItem( QListBox *parent, KABC::Field *field, int index ) + : QListBoxText( parent, field->label(), parent->item( index ) ), + mField( field ) {} + + KABC::Field *field() { return mField; } + + private: + KABC::Field *mField; +}; + + +ViewConfigureFieldsPage::ViewConfigureFieldsPage( KABC::AddressBook *ab, + QWidget *parent, + const char *name ) + : QWidget( parent, name ), mAddressBook( ab ) +{ + initGUI(); +} + +void ViewConfigureFieldsPage::restoreSettings( KConfig *config ) +{ + KABC::Field::List fields = KABC::Field::restoreFields( config, "KABCFields" ); + + if ( fields.isEmpty() ) + fields = KABC::Field::defaultFields(); + + KABC::Field::List::ConstIterator it; + for( it = fields.begin(); it != fields.end(); ++it ) + new FieldItem( mSelectedBox, *it ); + + slotShowFields( mCategoryCombo->currentItem() ); +} + +void ViewConfigureFieldsPage::saveSettings( KConfig *config ) +{ + KABC::Field::List fields; + + for( uint i = 0; i < mSelectedBox->count(); ++i ) { + FieldItem *fieldItem = static_cast<FieldItem *>( mSelectedBox->item( i ) ); + fields.append( fieldItem->field() ); + } + + KABC::Field::saveFields( config, "KABCFields", fields ); +} + +void ViewConfigureFieldsPage::slotShowFields( int index ) +{ + int currentPos = mUnSelectedBox->currentItem(); + mUnSelectedBox->clear(); + + int category; + if ( index == 0 ) category = KABC::Field::All; + else category = 1 << ( index - 1 ); + + KABC::Field::List allFields = mAddressBook->fields( category ); + + KABC::Field::List::ConstIterator it; + for ( it = allFields.begin(); it != allFields.end(); ++it ) { + QListBoxItem *item = mSelectedBox->firstItem(); + while( item ) { + FieldItem *fieldItem = static_cast<FieldItem *>( item ); + if ( (*it)->equals( fieldItem->field() ) ) + break; + item = item->next(); + } + + if ( !item ) + new FieldItem( mUnSelectedBox, *it ); + } + + mUnSelectedBox->sort(); + mUnSelectedBox->setCurrentItem( currentPos ); +} + +void ViewConfigureFieldsPage::slotSelect() +{ + // insert selected items in the unselected list to the selected list, + // directoy under the current item if selected, or at the bottonm if + // nothing is selected in the selected list + int where = mSelectedBox->currentItem(); +//US QListBoxItem::isSelected()) is not available in QT 2.x. Use selected instead. + if ( !(where > -1 && mSelectedBox->item( where )->selected()) ) + where = mSelectedBox->count() - 1; + + for ( uint i = 0; i < mUnSelectedBox->count(); ++i ) + if ( mUnSelectedBox->isSelected( mUnSelectedBox->item( i ) ) ) { + FieldItem *fieldItem = static_cast<FieldItem *>( mUnSelectedBox->item( i ) ); + new FieldItem( mSelectedBox, fieldItem->field(), where ); + where++; + } + + slotShowFields( mCategoryCombo->currentItem() ); +} + +void ViewConfigureFieldsPage::slotUnSelect() +{ + for ( uint i = 0; i < mSelectedBox->count(); ++i ) + if ( mSelectedBox->isSelected( mSelectedBox->item( i ) ) ) { + mSelectedBox->removeItem( i ); + --i; + } + + slotShowFields( mCategoryCombo->currentItem() ); +} + +void ViewConfigureFieldsPage::slotButtonsEnabled() +{ + bool state = false; + // add button: enabled if any items are selected in the unselected list + for( uint i = 0; i < mUnSelectedBox->count(); ++i ) +//US QListBoxItem::isSelected()) is not available in QT 2.x. Use selected instead. + if ( mUnSelectedBox->item( i )->selected() ) { + state = true; + break; + } + mAddButton->setEnabled( state ); + + int j = mSelectedBox->currentItem(); + state = ( j > -1 && mSelectedBox->isSelected( j ) ); + + // up button: enabled if there is a current item > 0 and that is selected + mUpButton->setEnabled( ( j > 0 && state ) ); + + // down button: enabled if there is a current item < count - 2 and that is selected + mDownButton->setEnabled( ( j > -1 && j < (int)mSelectedBox->count() - 1 && state ) ); + + // remove button: enabled if any items are selected in the selected list + state = false; + for ( uint i = 0; i < mSelectedBox->count(); ++i ) +//US QListBoxItem::isSelected()) is not available in QT 2.x. Use selected instead. + if ( mSelectedBox->item( i )->selected() ) { + state = true; + break; + } + mRemoveButton->setEnabled( state ); +} + +void ViewConfigureFieldsPage::slotMoveUp() +{ + int i = mSelectedBox->currentItem(); + if ( i > 0 ) { + QListBoxItem *item = mSelectedBox->item( i ); + mSelectedBox->takeItem( item ); + mSelectedBox->insertItem( item, i - 1 ); + mSelectedBox->setCurrentItem( item ); + mSelectedBox->setSelected( i - 1, true ); + } +} + +void ViewConfigureFieldsPage::slotMoveDown() +{ + int i = mSelectedBox->currentItem(); + if ( i > -1 && i < (int)mSelectedBox->count() - 1 ) { + QListBoxItem *item = mSelectedBox->item( i ); + mSelectedBox->takeItem( item ); + mSelectedBox->insertItem( item, i + 1 ); + mSelectedBox->setCurrentItem( item ); + mSelectedBox->setSelected( i + 1, true ); + } +} + +void ViewConfigureFieldsPage::initGUI() +{ + //US change the orientation dependent on the following flag + // right the flag is set only staticly. + // 0 = 640x480 ; 1 = 240x320 + bool orientation = 1; + + + setCaption( i18n("Select Fields to Display") ); + + QGridLayout *gl = 0; + + if (orientation == 0) + gl = new QGridLayout( this , 6, 4, 0, KDialog::spacingHint() ); + else + gl = new QGridLayout( this , 4, 6, 0, KDialog::spacingHint() ); + + #ifndef KAB_EMBEDDED + mCategoryCombo = new KComboBox( false, this ); + #else //KAB_EMBEDDED + mCategoryCombo = new QComboBox( false, this ); + #endif //KAB_EMBEDDED + + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::All ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Frequent ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Address ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Email ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Personal ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::Organization ) ); + mCategoryCombo->insertItem( KABC::Field::categoryLabel( KABC::Field::CustomCategory ) ); + connect( mCategoryCombo, SIGNAL( activated(int) ), SLOT( slotShowFields(int) ) ); + gl->addWidget( mCategoryCombo, 0, 0 ); + + QLabel *label = new QLabel( i18n( "&Selected fields:" ), this ); + if (orientation == 0) + gl->addWidget( label, 0, 2 ); + else + gl->addWidget( label, 2, 0 ); + + + mUnSelectedBox = new QListBox( this ); + mUnSelectedBox->setSelectionMode( QListBox::Extended ); + mUnSelectedBox->setMinimumHeight( 100 ); + if (orientation == 0) + gl->addWidget( mUnSelectedBox, 1, 0 ); + else + gl->addWidget( mUnSelectedBox, 0, 1 ); + + mSelectedBox = new QListBox( this ); + mSelectedBox->setSelectionMode( QListBox::Extended ); + label->setBuddy( mSelectedBox ); + if (orientation == 0) + gl->addWidget( mSelectedBox, 1, 2 ); + else + gl->addWidget( mSelectedBox, 2, 1 ); + + QBoxLayout *vb1 = 0; + if (orientation == 0) + vb1 = new QBoxLayout( QBoxLayout::TopToBottom, KDialog::spacingHint() ); + else + vb1 = new QBoxLayout( QBoxLayout::LeftToRight, KDialog::spacingHint() ); + + vb1->addStretch(); + + mAddButton = new QToolButton( this ); + if (orientation == 0) + mAddButton->setIconSet( SmallIconSet( "1rightarrow" ) ); + else + mAddButton->setIconSet( SmallIconSet( "1downarrow" ) ); + connect( mAddButton, SIGNAL( clicked() ), SLOT( slotSelect() ) ); + vb1->addWidget( mAddButton ); + + mRemoveButton = new QToolButton( this ); + if (orientation == 0) + mRemoveButton->setIconSet( SmallIconSet( "1leftarrow" ) ); + else + mRemoveButton->setIconSet( SmallIconSet( "1uparrow" ) ); + + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( slotUnSelect() ) ); + vb1->addWidget( mRemoveButton ); + + vb1->addStretch(); + if (orientation == 0) + gl->addLayout( vb1, 1, 1 ); + else + gl->addLayout( vb1, 1, 1 ); + + QBoxLayout *vb2 = 0; + if (orientation == 0) + vb2 = new QBoxLayout( QBoxLayout::TopToBottom, KDialog::spacingHint() ); + else + vb2 = new QBoxLayout( QBoxLayout::LeftToRight, KDialog::spacingHint() ); + + vb2->addStretch(); + + mUpButton = new QToolButton( this ); + mUpButton->setIconSet( SmallIconSet( "1uparrow" ) ); + connect( mUpButton, SIGNAL( clicked() ), SLOT( slotMoveUp() ) ); + vb2->addWidget( mUpButton ); + + mDownButton = new QToolButton( this ); + mDownButton->setIconSet( SmallIconSet( "1downarrow" ) ); + connect( mDownButton, SIGNAL( clicked() ), SLOT( slotMoveDown() ) ); + vb2->addWidget( mDownButton ); + + vb2->addStretch(); + if (orientation == 0) + gl->addLayout( vb2, 1, 3 ); + else + gl->addLayout( vb2, 3, 1 ); + + QSize sizeHint = mUnSelectedBox->sizeHint(); + + // make sure we fill the list with all items, so that we can + // get the maxItemWidth we need to not truncate the view + slotShowFields( 0 ); + + sizeHint = sizeHint.expandedTo( mSelectedBox->sizeHint() ); + sizeHint.setWidth( mUnSelectedBox->maxItemWidth() ); + mUnSelectedBox->setMinimumSize( sizeHint ); + mSelectedBox->setMinimumSize( sizeHint ); + + gl->activate(); + + connect( mUnSelectedBox, SIGNAL( selectionChanged() ), SLOT( slotButtonsEnabled() ) ); + connect( mSelectedBox, SIGNAL( selectionChanged() ), SLOT( slotButtonsEnabled() ) ); + connect( mSelectedBox, SIGNAL( currentChanged( QListBoxItem * ) ), SLOT( slotButtonsEnabled() ) ); + + slotButtonsEnabled(); +} + + +#ifndef KAB_EMBEDDED +#include "viewconfigurefieldspage.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/viewconfigurefieldspage.h b/kaddressbook/viewconfigurefieldspage.h new file mode 100644 index 0000000..b27668c --- a/dev/null +++ b/kaddressbook/viewconfigurefieldspage.h @@ -0,0 +1,81 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef VIEWCONFIGUREFIELDSPAGE_H +#define VIEWCONFIGUREFIELDSPAGE_H + +#include <qwidget.h> + +#include <kabc/field.h> +#include <kabc/addressbook.h> + +#ifndef KAB_EMBEDDED +class KComboBox; +#else //KAB_EMBEDDED +class QComboBox; +#endif //KAB_EMBEDDED + +class QListBox; +class QListBoxItem; +class QPushButton; +class QToolButton; + +class ViewConfigureFieldsPage : public QWidget +{ + Q_OBJECT + + public: + ViewConfigureFieldsPage( KABC::AddressBook *ab, QWidget *parent = 0, + const char *name = 0 ); + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + + public slots: + void slotSelect(); + void slotUnSelect(); + void slotMoveUp(); + void slotMoveDown(); + + void slotShowFields( int ); + void slotButtonsEnabled(); + + private: + void initGUI(); + +#ifndef KAB_EMBEDDED + KComboBox *mCategoryCombo; +#else //KAB_EMBEDDED + QComboBox *mCategoryCombo; +#endif //KAB_EMBEDDED + QListBox *mSelectedBox; + QListBox *mUnSelectedBox; + QToolButton *mAddButton; + QToolButton *mRemoveButton; + QToolButton *mUpButton; + QToolButton *mDownButton; + + KABC::AddressBook *mAddressBook; +}; + +#endif diff --git a/kaddressbook/viewconfigurefilterpage.cpp b/kaddressbook/viewconfigurefilterpage.cpp new file mode 100644 index 0000000..b085a5e --- a/dev/null +++ b/kaddressbook/viewconfigurefilterpage.cpp @@ -0,0 +1,137 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KAB_EMBEDDED +#include <kcombobox.h> +#else //KAB_EMBEDDED +#include <qcombobox.h> +#endif //KAB_EMBEDDED + +#include <qbuttongroup.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qradiobutton.h> + +#include <kconfig.h> +#include <kdialog.h> +#include <klocale.h> + +#include "filter.h" + +#include "viewconfigurefilterpage.h" + +ViewConfigureFilterPage::ViewConfigureFilterPage( QWidget *parent, + const char *name ) + : QWidget( parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() ); + + mFilterGroup = new QButtonGroup(); + connect( mFilterGroup, SIGNAL( clicked( int ) ), SLOT( buttonClicked( int ) ) ); + + QLabel *label = new QLabel( i18n( "The default filter will be activated whenever" + " this view is displayed. This feature allows you to configure views that only" + " interact with certain types of information based on the filter. Once the view" + " is activated, the filter can be changed at anytime." ), this ); + label->setAlignment( Qt::AlignLeft | Qt::AlignTop | Qt::WordBreak ); + topLayout->addWidget( label ); + + QWidget *spacer = new QWidget( this ); + spacer->setMinimumHeight( 5 ); + topLayout->addWidget( spacer ); + + QRadioButton *button = new QRadioButton( i18n( "No default filter" ), this ); + mFilterGroup->insert( button ); + topLayout->addWidget( button ); + + button = new QRadioButton( i18n( "Use last active filter" ), this ); + mFilterGroup->insert( button ); + topLayout->addWidget( button ); + + QBoxLayout *comboLayout = new QHBoxLayout(); + topLayout->addLayout( comboLayout ); + button = new QRadioButton( i18n( "Use filter:" ), this ); + mFilterGroup->insert( button ); + comboLayout->addWidget( button ); + +#ifndef KAB_EMBEDDED + mFilterCombo = new KComboBox( this ); +#else //KAB_EMBEDDED + mFilterCombo = new QComboBox( this ); +#endif //KAB_EMBEDDED + + comboLayout->addWidget( mFilterCombo ); +} + +ViewConfigureFilterPage::~ViewConfigureFilterPage() +{ + delete mFilterGroup; +} + +void ViewConfigureFilterPage::restoreSettings( KConfig *config ) +{ + mFilterCombo->clear(); + +//US I had to adjust the whole method in order to work with QComboBoxes +// in case of the Platformindependent version + QString defaultfiltername = config->readEntry( "DefaultFilterName" ); + + int id = config->readNumEntry( "DefaultFilterType", 1 ); + mFilterGroup->setButton( id ); + buttonClicked( id ); + + // Load the filter combo + Filter::List list = Filter::restore( config, "Filter" ); + Filter::List::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) + { + mFilterCombo->insertItem( (*it).name() ); + + if ( id == 2 && (*it).name() == defaultfiltername) // has default filter + { + mFilterCombo->insertItem( (*it).name(), 0); + } + else + { + mFilterCombo->insertItem( (*it).name() ); + } + + } + + +} + +void ViewConfigureFilterPage::saveSettings( KConfig *config ) +{ + config->writeEntry( "DefaultFilterName", mFilterCombo->currentText() ); + config->writeEntry( "DefaultFilterType", mFilterGroup->id( mFilterGroup->selected() ) ); +} + +void ViewConfigureFilterPage::buttonClicked( int id ) +{ + mFilterCombo->setEnabled( id == 2 ); +} + +#ifndef KAB_EMBEDDED +#include "viewconfigurefilterpage.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/viewconfigurefilterpage.h b/kaddressbook/viewconfigurefilterpage.h new file mode 100644 index 0000000..3be9564 --- a/dev/null +++ b/kaddressbook/viewconfigurefilterpage.h @@ -0,0 +1,63 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef VIEWCONFIGUREFILTERPAGE +#define VIEWCONFIGUREFILTERPAGE + +#include <qwidget.h> + +class QButtonGroup; + +#ifndef KAB_EMBEDDED +class KComboBox; +#else //KAB_EMBEDDED +class QComboBox; +#endif //KAB_EMBEDDED + +class KConfig; + +class ViewConfigureFilterPage : public QWidget +{ + Q_OBJECT + + public: + ViewConfigureFilterPage( QWidget *parent, const char *name = 0 ); + ~ViewConfigureFilterPage(); + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + + protected slots: + void buttonClicked( int id ); + + private: +#ifndef KAB_EMBEDDED + KComboBox *mFilterCombo; +#else //KAB_EMBEDDED + QComboBox *mFilterCombo; +#endif //KAB_EMBEDDED + + QButtonGroup *mFilterGroup; +}; + +#endif diff --git a/kaddressbook/viewconfigurewidget.cpp b/kaddressbook/viewconfigurewidget.cpp new file mode 100644 index 0000000..666e188 --- a/dev/null +++ b/kaddressbook/viewconfigurewidget.cpp @@ -0,0 +1,159 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + + +#ifndef KAB_EMBEDDED + +#include <qvbox.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kiconloader.h> + +#include "viewmanager.h" + +#endif //KAB_EMBEDDED + + +#include <qlayout.h> + +#include <kjanuswidget.h> +#include <kglobal.h> +#include <klocale.h> + +#include "viewconfigurewidget.h" +#include "viewconfigurefieldspage.h" +#include "viewconfigurefilterpage.h" + +ViewConfigureWidget::ViewConfigureWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name ) + : ConfigureWidget( ab, parent, name ) +{ + QVBoxLayout *topLayout = new QVBoxLayout( this ); + + mMainWidget = new KJanusWidget( this, "JanusWidget", KJanusWidget::Tabbed ); + + topLayout->addWidget( mMainWidget ); + + // Add the first page, the attributes + QVBox *page = addPage( i18n( "Fields" ), QString::null, + KGlobal::iconLoader()->loadIcon( "view_detailed", + KIcon::Panel, 16 ) ); + + + // Add the select fields page + mFieldsPage = new ViewConfigureFieldsPage( addressBook(), (QWidget*)page ); + +//US mFieldsPage->setMinimumSize(300,300); + + // Add the second page, the filter selection + page = addPage( i18n( "Default Filter" ), QString::null, + KGlobal::iconLoader()->loadIcon( "filter", + KIcon::Panel, 16 ) ); + + mFilterPage = new ViewConfigureFilterPage( (QWidget*)page ); + //qDebug("+++++ViewConfigureWidget::ViewConfigureWidget "); +} + +ViewConfigureWidget::~ViewConfigureWidget() +{ + //qDebug("-----ViewConfigureWidget::~ViewConfigureWidget() "); +} + +void ViewConfigureWidget::restoreSettings( KConfig *config ) +{ + mFieldsPage->restoreSettings( config ); + mFilterPage->restoreSettings( config ); +} + +void ViewConfigureWidget::saveSettings( KConfig *config ) +{ + mFieldsPage->saveSettings( config ); + mFilterPage->saveSettings( config ); +} + +QVBox *ViewConfigureWidget::addPage( const QString &item, const QString &header, + const QPixmap &pixmap ) +{ + return mMainWidget->addVBoxPage( item, header, pixmap ); +} + +#include <qframe.h> +#include <qlabel.h> +#include <qlayout.h> +#include <stdlib.h> + +ViewConfigureDialog::ViewConfigureDialog( ViewConfigureWidget *wdg, const QString &viewName, + QWidget *parent, const char *name ) + : KDialogBase( Swallow, i18n( "Modify View: " ) + viewName, Help | Ok | Cancel, + Ok, parent, name, true, true ), mConfigWidget( wdg ) +{ +//US, I have to change the way, how to connect the ViewConfigureWidget. It looks +// like it has changed. + //QFrame *topFrame = plainPage(); + if ( mConfigWidget ) { + mConfigWidget->reparent(this, QPoint(0,0), true); + // QVBoxLayout * layout = new QVBoxLayout( this ); + //layout->addWidget(mConfigWidget ); + //mConfigWidget->reparent(topFrame, QPoint(1,1), true); + + setMainWidget( mConfigWidget ); + } + +} + +ViewConfigureDialog::~ViewConfigureDialog() +{ +} +void ViewConfigureDialog::setWidget( ViewConfigureWidget *wdg ) +{ + mConfigWidget = wdg ; + setMainWidget( mConfigWidget ); + +} + +void ViewConfigureDialog::restoreSettings( KConfig *config ) +{ + mConfigWidget->restoreSettings( config ); +} + +void ViewConfigureDialog::saveSettings( KConfig *config ) +{ + mConfigWidget->saveSettings( config ); +} + +void ViewConfigureDialog::slotHelp() +{ +#ifndef KAB_EMBEDDED + kapp->invokeHelp( "using-views" ); +#else //KAB_EMBEDDED + qDebug("ViewConfigureDialog::slotHelp not yet implemented"); +#endif //KAB_EMBEDDED +} + +#ifndef KAB_EMBEDDED +#include "viewconfigurewidget.moc" +#endif //KAB_EMBEDDED + + diff --git a/kaddressbook/viewconfigurewidget.h b/kaddressbook/viewconfigurewidget.h new file mode 100644 index 0000000..0c2b77c --- a/dev/null +++ b/kaddressbook/viewconfigurewidget.h @@ -0,0 +1,106 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can rremovePageedistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef VIEWCONFIGUREWIDGET_H +#define VIEWCONFIGUREWIDGET_H + + + +#include "configurewidget.h" + +class QVBox; + +#include <kdialogbase.h> +#include <qpixmap.h> + +class KJanusWidget; +class QString; +class ViewConfigureFieldsPage; +class ViewConfigureFilterPage; +class ViewConfigureDialog; +/** + This widget is the base class for all view configuration widgets. The + author of a view may wish to inherit from this widget and add config pages + that add custom config options. The default implementation of this widget + is to show a page with the select fields widget. For simple views this may + be sufficient. +*/ +class ViewConfigureWidget : public ConfigureWidget +{ + Q_OBJECT + + public: + ViewConfigureWidget( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + virtual ~ViewConfigureWidget(); + + /** + Reads the configuration from the config object and sets the values + in the GUI. If this method is overloaded, be sure to call the base + class's method. + + Do not change the group of the config object in this method. + */ + virtual void restoreSettings( KConfig *config ); + + /** + Writes the configuration from the GUI to the config object. If this + method is overloaded, be sure to call the base class's method. + + Do not change the group of the config object in this method. + */ + virtual void saveSettings( KConfig *config ); + + + /** + Use this method to add new pages to the widget. + */ + QVBox *addPage( const QString &item, const QString &header = QString::null, + const QPixmap &pixmap = QPixmap() ); + + private: + KJanusWidget *mMainWidget; + + ViewConfigureFieldsPage *mFieldsPage; + ViewConfigureFilterPage *mFilterPage; +}; + +class ViewConfigureDialog : public KDialogBase +{ + Q_OBJECT + + public: + ViewConfigureDialog( ViewConfigureWidget *wdg, const QString &viewName, + QWidget *parent, const char *name = 0 ); + ~ViewConfigureDialog(); + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + void setWidget( ViewConfigureWidget *wdg ); + protected slots: + void slotHelp(); + + private: + ViewConfigureWidget *mConfigWidget; +}; + +#endif diff --git a/kaddressbook/viewmanager.cpp b/kaddressbook/viewmanager.cpp new file mode 100644 index 0000000..e8c5b45 --- a/dev/null +++ b/kaddressbook/viewmanager.cpp @@ -0,0 +1,685 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + + +#ifndef KAB_EMBEDDED +#include <libkdepim/kvcarddrag.h> +#include <kabc/vcardconverter.h> +#include <kconfig.h> +#include <kdeversion.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kmultipledrag.h> +#include <ktrader.h> +#include <kurldrag.h> + +#include "addresseeutil.h" +#else //KAB_EMBEDDED +#include "views/kaddressbookiconview.h" +#include "views/kaddressbooktableview.h" +#include "views/kaddressbookcardview.h" +#include "kaddressbookview.h" + +#include <qaction.h> +#include <qmessagebox.h> +#include <qpopupmenu.h> +#include <kconfigbase.h> + +#endif //KAB_EMBEDDED + + +#include <kdebug.h> +#include <kactionclasses.h> + +#include <qlayout.h> +#include <qwidgetstack.h> + +#include <kabc/addressbook.h> +#include "filtereditdialog.h" +#include "addviewdialog.h" +#include "kabcore.h" +#include "kabprefs.h" +#include "viewmanager.h" + +ViewManager::ViewManager( KABCore *core, QWidget *parent, const char *name ) + : QWidget( parent, name ), mCore( core ), mActiveView( 0 ) +{ + initGUI(); + initActions(); + + mViewDict.setAutoDelete( true ); + + createViewFactories(); +} + +ViewManager::~ViewManager() +{ + unloadViews(); + mViewFactoryDict.clear(); +} + +void ViewManager::restoreSettings() +{ + mViewNameList = KABPrefs::instance()->mViewNames; + QString activeViewName = KABPrefs::instance()->mCurrentView; + + mActionSelectView->setItems( mViewNameList ); + + // Filter + mFilterList = Filter::restore( mCore->config(), "Filter" ); + mActionSelectFilter->setItems( filterNames() ); + mActionSelectFilter->setCurrentItem( KABPrefs::instance()->mCurrentFilter ); + + // Tell the views to reread their config, since they may have + // been modified by global settings + QString _oldgroup = mCore->config()->group(); + + QDictIterator<KAddressBookView> it( mViewDict ); + for ( it.toFirst(); it.current(); ++it ) { + KConfigGroupSaver saver( mCore->config(), it.currentKey() ); + it.current()->readConfig( mCore->config() ); + } + setActiveView( activeViewName ); + + mActionDeleteView->setEnabled( mViewNameList.count() > 1 ); +} + +void ViewManager::saveSettings() +{ + QString _oldgroup = mCore->config()->group(); + + QDictIterator<KAddressBookView> it( mViewDict ); + for ( it.toFirst(); it.current(); ++it ) { + KConfigGroupSaver saver( mCore->config(), it.currentKey() ); +#ifdef DESKTOP_VERSION + (*it)->writeConfig( mCore->config() ); +#else + (*it).writeConfig( mCore->config() ); +#endif + } + + Filter::save( mCore->config(), "Filter", mFilterList ); + KABPrefs::instance()->mCurrentFilter = mActionSelectFilter->currentItem(); + + // write the view name list + KABPrefs::instance()->mViewNames = mViewNameList; + KABPrefs::instance()->mCurrentView = mActiveView->caption(); + +} + +QStringList ViewManager::selectedUids() const +{ + if ( mActiveView ) + return mActiveView->selectedUids(); + else + return QStringList(); +} + +QStringList ViewManager::selectedEmails() const +{ + if ( mActiveView ) + return mActiveView->selectedEmails(); + else + return QStringList(); +} + +KABC::Addressee::List ViewManager::selectedAddressees() const +{ + KABC::Addressee::List list; + if ( mActiveView ) { + QStringList uids = mActiveView->selectedUids(); + QStringList::Iterator it; + for ( it = uids.begin(); it != uids.end(); ++it ) { + KABC::Addressee addr = mCore->addressBook()->findByUid( *it ); + if ( !addr.isEmpty() ) + list.append( addr ); + } + } + + return list; +} +//US added another method with no parameter, since my moc compiler does not support default parameters. +void ViewManager::setSelected() +{ + setSelected( QString::null, true ); +} + +void ViewManager::setSelected( const QString &uid, bool selected ) +{ + if ( mActiveView ) + mActiveView->setSelected( uid, selected ); +} + +void ViewManager::unloadViews() +{ + mViewDict.clear(); + mActiveView = 0; +} + +void ViewManager::setActiveView( const QString &name ) +{ + KAddressBookView *view = 0; + + // Check that this isn't the same as the current active view + if ( mActiveView && ( mActiveView->caption() == name ) ) + return; + + // At this point we know the view that should be active is not + // currently active. We will try to find the new on in the list. If + // we can't find it, it means it hasn't been instantiated, so we will + // create it on demand. + + view = mViewDict.find( name ); + + // Check if we found the view. If we didn't, then we need to create it + if ( view == 0 ) { + KConfig *config = mCore->config(); + + KConfigGroupSaver saver( config, name ); + + QString type = config->readEntry( "Type", "Table" ); + + kdDebug(5720) << "ViewManager::setActiveView: creating view - " << name << endl; + + ViewFactory *factory = mViewFactoryDict.find( type ); + if ( factory ) + view = factory->view( mCore->addressBook(), mViewWidgetStack ); + + if ( view ) { + view->setCaption( name ); + mViewDict.insert( name, view ); +//US my version needs an int as second parameter to addWidget + mViewWidgetStack->addWidget( view, -1 ); + view->readConfig( config ); + + // The manager just relays the signals + connect( view, SIGNAL( selected( const QString& ) ), + SIGNAL( selected( const QString & ) ) ); + connect( view, SIGNAL( executed( const QString& ) ), + SIGNAL( executed( const QString& ) ) ); + + connect( view, SIGNAL( deleteRequest( ) ), + SIGNAL( deleteRequest( ) ) ); + + connect( view, SIGNAL( modified() ), SIGNAL( modified() ) ); + connect( view, SIGNAL( dropped( QDropEvent* ) ), + SLOT( dropped( QDropEvent* ) ) ); + connect( view, SIGNAL( startDrag() ), SLOT( startDrag() ) ); + } + } + + // If we found or created the view, raise it and refresh it + if ( view ) { + mActiveView = view; + mViewWidgetStack->raiseWidget( view ); + // Set the proper filter in the view. By setting the combo + // box, the activated slot will be called, which will push + // the filter to the view and refresh it. + + if ( view->defaultFilterType() == KAddressBookView::None ) { + + mActionSelectFilter->setCurrentItem( 0 ); + setActiveFilter( 0 ); + } else if ( view->defaultFilterType() == KAddressBookView::Active ) { + setActiveFilter( mActionSelectFilter->currentItem() ); + } else { + uint pos = filterPosition( view->defaultFilterName() ); + mActionSelectFilter->setCurrentItem( pos ); + setActiveFilter( pos ); + } +//US qDebug("ViewManager::setActiveView 6" ); + + // Update the inc search widget to show the fields in the new active + // view. + mCore->setSearchFields( mActiveView->fields() ); + + mActiveView->refresh(); + + } + else + { + qDebug("ViewManager::setActiveView: unable to find view" ); + kdDebug(5720) << "ViewManager::setActiveView: unable to find view\n"; + } +} + +//US added another method with no parameter, since my moc compiler does not support default parameters. +void ViewManager::refreshView() +{ + refreshView( QString::null ); +} + +void ViewManager::refreshView( const QString &uid ) +{ + if ( mActiveView ) + mActiveView->refresh( uid ); +} + +void ViewManager::editView() +{ + if ( !mActiveView ) + return; + + ViewFactory *factory = mViewFactoryDict.find( mActiveView->type() ); + ViewConfigureWidget *wdg = 0; + ViewConfigureDialog* dlg = 0; + if ( factory ) { + // Save the filters so the dialog has the latest set + Filter::save( mCore->config(), "Filter", mFilterList ); + dlg = new ViewConfigureDialog( 0, mActiveView->caption(), this, "conf_dlg" ); + wdg = factory->configureWidget( mCore->addressBook(), dlg,"conf_wid" ); + } else { + qDebug("ViewManager::editView()::cannot find viewfactory "); + return; + } + if ( wdg ) { + dlg->setWidget( wdg ); + +#ifndef DESKTOP_VERSION + //dlg.setMaximumSize( 640, 480 ); + //dlg->setGeometry( 40,40, 400, 300); + dlg->showMaximized(); +#endif + + KConfigGroupSaver saver( mCore->config(), mActiveView->caption() ); + + dlg->restoreSettings( mCore->config() ); + + if ( dlg->exec() ) { + dlg->saveSettings( mCore->config() ); + mActiveView->readConfig( mCore->config() ); + + // Set the proper filter in the view. By setting the combo + // box, the activated slot will be called, which will push + // the filter to the view and refresh it. + if ( mActiveView->defaultFilterType() == KAddressBookView::None ) { + mActionSelectFilter->setCurrentItem( 0 ); + setActiveFilter( 0 ); + } else if ( mActiveView->defaultFilterType() == KAddressBookView::Active ) { + setActiveFilter( mActionSelectFilter->currentItem() ); + } else { + uint pos = filterPosition( mActiveView->defaultFilterName() ); + mActionSelectFilter->setCurrentItem( pos ); + setActiveFilter( pos ); + } + mCore->setSearchFields( mActiveView->fields() ); + mActiveView->refresh(); + } + + } + delete dlg; +} + +void ViewManager::deleteView() +{ + QString text = i18n( "<qt>Are you sure that you want to delete the view <b>%1</b>?</qt>" ) + .arg( mActiveView->caption() ); + QString caption = i18n( "Confirm Delete" ); + + + if (QMessageBox::information( this, caption, + text, + i18n("Yes!"), i18n("No"), 0, 0 ) == 0) + { + mViewNameList.remove( mActiveView->caption() ); + + // remove the view from the config file + KConfig *config = mCore->config(); + config->deleteGroup( mActiveView->caption() ); + + mViewDict.remove( mActiveView->caption() ); + mActiveView = 0; + + // we are in an invalid state now, but that should be fixed after + // we emit the signal + mActionSelectView->setItems( mViewNameList ); + if ( mViewNameList.count() > 0 ) { + mActionSelectView->setCurrentItem( 0 ); + setActiveView( mViewNameList[ 0 ] ); + } + mActionDeleteView->setEnabled( mViewNameList.count() > 1 ); + } +} + +void ViewManager::addView() +{ + AddViewDialog dialog( &mViewFactoryDict, this ); + + if ( dialog.exec() ) { + QString newName = dialog.viewName(); + QString type = dialog.viewType(); + + // Check for name conflicts + bool firstConflict = true; + int numTries = 1; + while ( mViewNameList.contains( newName ) > 0 ) { + if ( !firstConflict ) { + newName = newName.left( newName.length() - 4 ); + firstConflict = false; + } + + newName = QString( "%1 <%2>" ).arg( newName ).arg( numTries ); + numTries++; + } + + // Add the new one to the list + mViewNameList.append( newName ); + + // write the view to the config file, + KConfig *config = mCore->config(); + + config->deleteGroup( newName ); + + KConfigGroupSaver saver( config, newName ); + + config->writeEntry( "Type", type ); + + // try to set the active view + mActionSelectView->setItems( mViewNameList ); + mActionSelectView->setCurrentItem( mViewNameList.findIndex( newName ) ); + setActiveView( newName ); + + editView(); + + mActionDeleteView->setEnabled( mViewNameList.count() > 1 ); + } +} + +void ViewManager::createViewFactories() +{ +#ifndef KAB_EMBEDDED + KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/View" ); + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + if ( !(*it)->hasServiceType( "KAddressBook/View" ) ) + continue; + + KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().latin1() ); + + if ( !factory ) { + kdDebug(5720) << "ViewManager::createViewFactories(): Factory creation failed" << endl; + continue; + } + + ViewFactory *viewFactory = static_cast<ViewFactory*>( factory ); + + if ( !viewFactory ) { + kdDebug(5720) << "ViewManager::createViewFactories(): Cast failed" << endl; + continue; + } + + mViewFactoryDict.insert( viewFactory->type(), viewFactory ); + } + +#else //KAB_EMBEDDED + ViewFactory* viewFactory = new IconViewFactory(); + mViewFactoryDict.insert( viewFactory->type(), viewFactory ); +// qDebug("ViewManager::createViewFactories() Loading factory: %s", viewFactory->type().latin1()); + + viewFactory = new TableViewFactory(); + mViewFactoryDict.insert( viewFactory->type(), viewFactory ); +// qDebug("ViewManager::createViewFactories() Loading factory: %s", viewFactory->type().latin1()); + + viewFactory = new CardViewFactory(); + mViewFactoryDict.insert( viewFactory->type(), viewFactory ); +// qDebug("ViewManager::createViewFactories() Loading factory: %s", viewFactory->type().latin1()); + +#endif //KAB_EMBEDDED + +} + +void ViewManager::dropped( QDropEvent *e ) +{ + kdDebug(5720) << "ViewManager::dropped: got a drop event" << endl; + +#ifndef KAB_EMBEDDED + + QString clipText, vcards; + KURL::List urls; + + if ( KURLDrag::decode( e, urls) ) { + KURL::List::Iterator it = urls.begin(); + int c = urls.count(); + if ( c > 1 ) { + QString questionString = i18n( "Import one contact into your addressbook?", "Import %n contacts into your addressbook?", c ); + if ( KMessageBox::questionYesNo( this, questionString, i18n( "Import Contacts?" ) ) == KMessageBox::Yes ) { + for ( ; it != urls.end(); ++it ) + emit urlDropped( *it ); + } + } else if ( c == 1 ) + emit urlDropped( *it ); + } else if ( KVCardDrag::decode( e, vcards ) ) { + KABC::Addressee addr; + KABC::VCardConverter converter; + QStringList list = QStringList::split( "\r\n\r\n", vcards ); + QStringList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + if ( converter.vCardToAddressee( (*it).stripWhiteSpace(), addr ) ) { + KABC::Addressee a = mCore->addressBook()->findByUid( addr.uid() ); + if ( a.isEmpty() ) { + mCore->addressBook()->insertAddressee( addr ); + emit modified(); + } + } + } + + mActiveView->refresh(); + } +#else //KAB_EMBEDDED +qDebug("ViewManager::dropped() has to be changed!!" ); +#endif //KAB_EMBEDDED + +} + +void ViewManager::startDrag() +{ + kdDebug(5720) << "ViewManager::startDrag: starting to drag" << endl; + +#ifndef KAB_EMBEDDED + + // Get the list of all the selected addressees + KABC::Addressee::List addrList; + QStringList uidList = selectedUids(); + QStringList::Iterator iter; + for ( iter = uidList.begin(); iter != uidList.end(); ++iter ) + addrList.append( mCore->addressBook()->findByUid( *iter ) ); + + KMultipleDrag *drag = new KMultipleDrag( this ); + drag->addDragObject( new QTextDrag( AddresseeUtil::addresseesToClipboard(addrList), this ) ); + KABC::Addressee::List::Iterator it; + QStringList vcards; + for ( it = addrList.begin(); it != addrList.end(); ++it ) { + QString vcard = QString::null; + KABC::VCardConverter converter; + if ( converter.addresseeToVCard( *it, vcard ) ) + vcards.append( vcard ); + } + drag->addDragObject( new KVCardDrag( vcards.join( "\r\n" ), this ) ); + + drag->setPixmap( KGlobal::iconLoader()->loadIcon( "vcard", KIcon::Desktop ) ); + drag->dragCopy(); + +#else //KAB_EMBEDDED +qDebug("ViewManager::startDrag() has to be changed!!" ); +#endif //KAB_EMBEDDED + +} + +void ViewManager::setActiveFilter( int index ) +{ + Filter currentFilter; + + if ( ( index - 1 ) < 0 ) + currentFilter = Filter(); + else + currentFilter = mFilterList[ index - 1 ]; + + // Check if we have a view. Since the filter combo is created before + // the view, this slot could be called before there is a valid view. + if ( mActiveView ) { + mActiveView->setFilter( currentFilter ); + mActiveView->refresh(); + emit selected( QString::null ); + } +} + +void ViewManager::configureFilters() +{ + FilterDialog dlg( this ); + + dlg.setFilters( mFilterList ); + + if ( dlg.exec() ) + mFilterList = dlg.filters(); + + uint pos = mActionSelectFilter->currentItem(); + mActionSelectFilter->setItems( filterNames() ); + mActionSelectFilter->setCurrentItem( pos ); + setActiveFilter( pos ); +} + +QStringList ViewManager::filterNames() const +{ + QStringList names( i18n( "No Filter" ) ); + + Filter::List::ConstIterator it; + for ( it = mFilterList.begin(); it != mFilterList.end(); ++it ) + names.append( (*it).name() ); + + return names; +} + +int ViewManager::filterPosition( const QString &name ) const +{ + int pos = 0; + + Filter::List::ConstIterator it; + for ( it = mFilterList.begin(); it != mFilterList.end(); ++it, ++pos ) + if ( name == (*it).name() ) + return pos + 1; + + return 0; +} + +void ViewManager::initActions() +{ +//US <ActionList name="view_loadedviews"/> +//US <Separator/> + +#ifdef KAB_EMBEDDED + QPopupMenu *viewmenu = (QPopupMenu*)mCore->getViewMenu(); + QPopupMenu *settingsmenu = (QPopupMenu*)mCore->getSettingsMenu(); + QPopupMenu *filtermenu = (QPopupMenu*)mCore->getFilterMenu(); +#endif //KAB_EMBEDDED + + mActionSelectView = new KSelectAction( i18n( "Select View" ), 0, mCore->actionCollection(), "select_view" ); +#if KDE_VERSION >= 309 + mActionSelectView->setMenuAccelsEnabled( false ); +#endif + connect( mActionSelectView, SIGNAL( activated( const QString& ) ), + SLOT( setActiveView( const QString& ) ) ); + + +#ifdef KAB_EMBEDDED + mActionSelectView->plug(viewmenu); + viewmenu->insertSeparator(); +#endif //KAB_EMBEDDED + + KAction *action; + + action = new KAction( i18n( "Modify View..." ), "configure", 0, this, + SLOT( editView() ), mCore->actionCollection(), "view_modify" ); +#ifndef KAB_EMBEDDED + action->setWhatsThis( i18n( "By pressing this button a dialog opens that allows you to modify the view of the addressbook. There you can add or remove fields that you want to be shown or hidden in the addressbook like the name for example." ) ); +#else //KAB_EMBEDDED + action->plug(viewmenu); +#endif //KAB_EMBEDDED + + action = new KAction( i18n( "Add View..." ), "window_new", 0, this, + SLOT( addView() ), mCore->actionCollection(), "view_add" ); +#ifndef KAB_EMBEDDED + action->setWhatsThis( i18n( "You can add a new view by choosing one of the dialog that appears after pressing the button. You have to give the view a name, so that you can distinguish between the different views." ) ); +#else //KAB_EMBEDDED + action->plug(viewmenu); +#endif //KAB_EMBEDDED + + mActionDeleteView = new KAction( i18n( "Delete View" ), "view_remove", 0, + this, SLOT( deleteView() ), + mCore->actionCollection(), "view_delete" ); +#ifndef KAB_EMBEDDED + mActionDeleteView->setWhatsThis( i18n( "By pressing this button you can delete the actual view, which you have added before." ) ); +#else //KAB_EMBEDDED + mActionDeleteView->plug(viewmenu); + viewmenu->insertSeparator(); +#endif //KAB_EMBEDDED + +#ifndef KAB_EMBEDDED + action = new KAction( i18n( "Refresh View" ), "reload", 0, this, + SLOT( refreshView(const QString &) ), mCore->actionCollection(), + "view_refresh" ); + action->setWhatsThis( i18n( "The view will be refreshed by pressing this button." ) ); +#else //KAB_EMBEDDED + action = new KAction( i18n( "Refresh View" ), "reload", 0, this, + SLOT( refreshView()), mCore->actionCollection(), + "view_refresh" ); + action->plug(viewmenu); + viewmenu->insertSeparator(); +#endif //KAB_EMBEDDED + + action = new KAction( i18n( "Edit &Filters..." ), "filter", 0, this, + SLOT( configureFilters() ), mCore->actionCollection(), + "options_edit_filters" ); + + mActionSelectFilter = new KSelectAction( i18n( "Select Filter" ), "filter", mCore->actionCollection(), "select_filter" ); + +#if KDE_VERSION >= 309 + mActionSelectFilter->setMenuAccelsEnabled( false ); +#endif + connect( mActionSelectFilter, SIGNAL( activated( int ) ), + SLOT( setActiveFilter( int ) ) ); + +#ifdef KAB_EMBEDDED + action->plug(settingsmenu); + mActionSelectFilter->plug(viewmenu); +#endif //KAB_EMBEDDED + +} + +void ViewManager::initGUI() +{ + QHBoxLayout *layout = new QHBoxLayout( this, 0, 0 ); + mViewWidgetStack = new QWidgetStack( this ); + layout->addWidget( mViewWidgetStack ); +} + +#ifndef KAB_EMBEDDED +#include "viewmanager.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/viewmanager.h b/kaddressbook/viewmanager.h new file mode 100644 index 0000000..a18e87d --- a/dev/null +++ b/kaddressbook/viewmanager.h @@ -0,0 +1,152 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef VIEWMANAGER_H +#define VIEWMANAGER_H + +#include <qwidget.h> +#include <qstringlist.h> +#include <kaddressbookview.h> +#include <qdict.h> + +class KAction; +class KSelectAction; + +class KABCore; +class QWidgetStack; +class QDropEvent; + +namespace KABC { class AddressBook; } + +/** + The view manager manages the views and everything related to them. The + manager will load the views at startup and display a view when told to + make one active. + + The view manager will also create and manage all dialogs directly related to + views (ie: AddView, ConfigureView, DeleteView, etc). + */ +class ViewManager : public QWidget +{ + Q_OBJECT + public: + ViewManager( KABCore *core, QWidget *parent, const char *name = 0 ); + ~ViewManager(); + + void restoreSettings(); + void saveSettings(); + + void unloadViews(); + KSelectAction * getFilterAction() { return mActionSelectFilter; } + + QStringList selectedUids() const; + QStringList selectedEmails() const; + KABC::Addressee::List selectedAddressees() const; + + public slots: + +//US void setSelected( const QString &uid = QString::null, bool selected = true ); + void setSelected( const QString &uid, bool); +//US added another method with no parameter, since my moc compiler does not support default parameters. + void setSelected(); + + + +//US added another method with no parameter, since my moc compiler does not support default parameters. + void refreshView(); + void refreshView( const QString &uid); + + void editView(); + void deleteView(); + void addView(); + + protected slots: + /** + Called whenever the user drops something in the active view. + This method will try to decode what was dropped, and if it was + a valid addressee, add it to the addressbook. + */ + void dropped( QDropEvent* ); + + /** + Called whenever the user attempts to start a drag in the view. + This method will convert all the selected addressees into text (vcard) + and create a drag object. + */ + void startDrag(); + + signals: + /** + Emitted whenever the user selects an entry in the view. + */ + void selected( const QString &uid ); + void deleteRequest( ); + + /** + Emitted whenever the user activates an entry in the view. + */ + void executed( const QString &uid ); + + /** + Emitted whenever the address book is modified in some way. + */ + void modified(); + + /** + Emitted whenever a url is dragged on a view. + */ + void urlDropped( const KURL& ); + + private slots: + void setActiveView( const QString &name ); + void setActiveFilter( int index ); + void configureFilters(); + + private: + void createViewFactories(); + QStringList filterNames() const; + int filterPosition( const QString &name ) const; + QStringList viewNames() const; + int viewPosition( const QString &name ) const; + void initActions(); + void initGUI(); + + KABCore *mCore; + + Filter mCurrentFilter; + Filter::List mFilterList; + + QDict<KAddressBookView> mViewDict; + QDict<ViewFactory> mViewFactoryDict; + QStringList mViewNameList; + + QWidgetStack *mViewWidgetStack; + KAddressBookView *mActiveView; + + KAction *mActionDeleteView; + KSelectAction *mActionSelectFilter; + KSelectAction *mActionSelectView; + +}; + +#endif diff --git a/kaddressbook/views/cardview.cpp b/kaddressbook/views/cardview.cpp new file mode 100644 index 0000000..65f793c --- a/dev/null +++ b/kaddressbook/views/cardview.cpp @@ -0,0 +1,1719 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +//BEGIN Includes +#include "cardview.h" + +#include <limits.h> + +#include <qpainter.h> +#include <qtimer.h> +#include <qdatetime.h> +#include <qlabel.h> +#include <qstyle.h> +#include <qcursor.h> +#include <qtooltip.h> + +#include <kdebug.h> +#include <kglobalsettings.h> +//END includes + +#define MIN_ITEM_WIDTH 80 + +//BEGIN Helpers +////////////////////////////////////// +// CardViewTip +class CardViewTip : public QLabel { + public: + CardViewTip(QWidget *parent=0, const char *name=0) : QLabel( parent, name ) + { + setPalette( QToolTip::palette() ); + setFrameStyle( Panel|Plain ); + setMidLineWidth(0); + setIndent(1); + } + + ~CardViewTip() {}; + protected: + void leaveEvent( QEvent * ) + { + hide(); + } +}; + +////////////////////////////////////// +// CardViewItemList + + +// +// Warning: make sure you use findRef() instead of find() to find an +// item! Only the pointer value is unique in the list. +// +class CardViewItemList : public QPtrList<CardViewItem> +{ + protected: + virtual int compareItems(QPtrCollection::Item item1, + QPtrCollection::Item item2) + { + CardViewItem *cItem1 = (CardViewItem*)item1; + CardViewItem *cItem2 = (CardViewItem*)item2; + + if ( cItem1 == cItem2 ) + return 0; + + if ((cItem1 == 0) || (cItem2 == 0)) + return cItem1 ? -1 : 1; + + if (cItem1->caption() < cItem2->caption()) + return -1; + + else if (cItem1->caption() > cItem2->caption()) + return 1; + + return 0; + } + + private: + /*int find( const CardViewItem * ) + { + qDebug("DON'T USE CardViewItemList::find( item )! Use findRef( item )!"); + }*/ +}; + +////////////////////////////////////// +// CardViewSeparator +class CardViewSeparator +{ + friend class CardView; + + public: + CardViewSeparator(CardView *view) + : mView(view) + { + mRect = QRect(0, 0, view->separatorWidth(), 0); + } + + ~CardViewSeparator() {} + + void paintSeparator(QPainter *p, QColorGroup &cg) + { + p->fillRect(0, 0, mRect.width(), mRect.height(), + cg.brush(QColorGroup::Button)); + } + + void repaintSeparator() + { + mView->repaintContents(mRect); + } + + private: + CardView *mView; + QRect mRect; +}; + +//END Helpers + +//BEGIN Private Data + +class CardViewPrivate +{ + public: + CardViewPrivate() + : mSelectionMode( CardView::Multi ), + mDrawCardBorder( true ), + mDrawFieldLabels( true ), + mDrawSeparators( true), + mSepWidth( 2 ), + mShowEmptyFields( false ), + mLayoutDirty( true ), + mLastClickOnItem( false ), + mItemMargin( 0 ), + mItemSpacing( 10 ), + mItemWidth( 200 ), + mMaxFieldLines( INT_MAX ), + mCurrentItem( 0L ), + mLastClickPos( QPoint(0, 0) ), + mRubberBandAnchor( 0 ), + mCompText( QString::null ), + mResizeAnchor(0) + {}; + + CardViewItemList mItemList; + QPtrList<CardViewSeparator> mSeparatorList; + QFontMetrics *mFm; + QFontMetrics *mBFm; // bold font + QFont mHeaderFont; // custom header font + CardView::SelectionMode mSelectionMode; + bool mDrawCardBorder; + bool mDrawFieldLabels; + bool mDrawSeparators; + int mSepWidth; + bool mShowEmptyFields; + bool mLayoutDirty; + bool mLastClickOnItem; + uint mItemMargin; // internal margin in items + uint mItemSpacing; // spacing between items, column seperators and border + int mItemWidth; // width of all items + uint mMaxFieldLines; // Max lines to dispaly pr field + CardViewItem *mCurrentItem; + QPoint mLastClickPos; + QTimer *mTimer; // times out if mouse rests for more than 500 msecs + CardViewTip *mTip; // passed to the item under a resting cursor to display full text + bool mOnSeparator; // set/reset on mouse movement + // for resizing by dragging the separators + int mResizeAnchor; // uint, ulong? the mouse down separator left + int mRubberBandAnchor; // for erasing rubber bands + // data used for resizing. + // as they are beeded by each mouse move while resizing, we store them here, + // saving 8 calculations in each mouse move. + int colspace; // amount of space between items pr column + uint first; // the first col to anchor at for painting rubber bands + int firstX; // X position of first in pixel + int pressed; // the colummn that was pressed on at resizing start + int span; // pressed - first + // key completion + QString mCompText; // current completion string + QDateTime mCompUpdated; // ...was updated at this time +}; + +class CardViewItemPrivate +{ + public: + CardViewItemPrivate() : + x( 0 ), + y( 0 ), + mSelected( false ){}; + + + QString mCaption; + QPtrList< CardViewItem::Field > mFieldList; + bool mSelected; + int x; // horizontal position, set by the view + int y; // vertical position, set by the view + int maxLabelWidth; // the width of the widest label, according to the view font. + int hcache; // height cache +}; +//END Private Data + +//BEGIN CardViewItem + +CardViewItem::CardViewItem(CardView *parent, QString caption) + : d(new CardViewItemPrivate()), mView(parent) +{ + d->mCaption = caption; + + initialize(); +} + +CardViewItem::~CardViewItem() +{ + // Remove ourself from the view + if (mView != 0) + mView->takeItem(this); + + delete d; + d = 0; +} + +void CardViewItem::initialize() +{ + d->mSelected = false; + d->mFieldList.setAutoDelete(true); + d->maxLabelWidth = 0; + d->hcache=0; + + //calcRect(); + + // Add ourself to the view + if (mView != 0) + mView->insertItem(this); +} + +void CardViewItem::paintCard(QPainter *p, QColorGroup &cg) +{ + + if (!mView) + return; + + QPen pen; + QBrush brush; + QFontMetrics fm = *(mView->d->mFm); + QFontMetrics bFm = *(mView->d->mBFm); + bool drawLabels = mView->d->mDrawFieldLabels; + bool drawBorder = mView->d->mDrawCardBorder; + int mg = mView->itemMargin(); + int w = mView->itemWidth() - (mg*2); + int h = height() - (mg*2); + const int colonWidth( fm.width(":") ); + int labelXPos = 2 + mg; + int labelWidth = QMIN( w/2 - 4 - mg, d->maxLabelWidth + colonWidth + 4 ); + int valueXPos = labelWidth + 4 + mg; + int valueWidth = w - labelWidth - 4 - mg; + + p->setFont( mView->font() ); + labelWidth -= colonWidth; // extra space for the colon + + if (!drawLabels) + { + valueXPos = labelXPos; + valueWidth = w - 4; + } + + // Draw a simple box + if (isSelected()) + pen = QPen(cg.highlight(), 1); + else + pen = QPen(cg.button(), 1); + p->setPen(pen); + + // Draw the border - this is only draw if the user asks for it. + if (drawBorder) + p->drawRect( mg, mg, w, h ); + + // set the proper pen color for the caption box + if (isSelected()) + brush = cg.brush(QColorGroup::Highlight); + else + brush = cg.brush(QColorGroup::Button); + + p->fillRect(mg, mg, w, 4 + bFm.height(), brush); + + // Now paint the caption + p->save(); + QFont bFont = mView->headerFont(); + //bFont.setBold(true); + p->setFont(bFont); + if (isSelected()) + p->setPen(cg.highlightedText()); + else + p->setPen(cg.buttonText()); + p->drawText(2+mg, 2+mg + bFm.ascent()/*bFm.height()*//*-bFm.descent()*//*-bFm.leading()*/, trimString(d->mCaption, w-4, bFm)); + p->restore(); + + // Go through the fields and draw them + QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); + QString label, value; + int yPos = mg + 4 + bFm.height()/* + 1*/ + fm.height(); // why the + 1 ??? (anders) + p->setPen(cg.text()); + + int fh = fm.height(); + int cln( 0 ); + QString tmp; + int maxLines = mView->maxFieldLines(); + for (iter.toFirst(); iter.current(); ++iter) + { + value = (*iter)->second; + if ( value.isEmpty() && ! mView->d->mShowEmptyFields ) + continue; + + if (drawLabels) + { + label = trimString((*iter)->first, labelWidth, fm); + p->drawText(labelXPos, yPos, label + ":"); + } +/* US original + for (cln=0; cln <= maxLines; cln++) + { + tmp = value.section('\n',cln,cln); + if ( !tmp.isEmpty() ) p->drawText( valueXPos, yPos + cln*fh, trimString( tmp, valueWidth, fm ) ); + else break; + } +*/ + +//US new implementation + QStringList strlst = QStringList::split('\n', value, true); + + for (cln=0; cln <= maxLines && cln <= (int)strlst.count(); cln++) + { + tmp = strlst[cln]; + + if ( !tmp.isEmpty() ) + p->drawText( valueXPos, yPos + cln*fh, trimString( tmp, valueWidth, fm ) ); + else + break; + + } + + if ( cln == 0 ) cln = 1; + yPos += cln * fh + 2; + } + + // if we are the current item and the view has focus, draw focus rect + if ( mView->currentItem() == this && mView->hasFocus() ) + { +/*US + mView->style().drawPrimitive( QStyle::PE_FocusRect, p, + QRect(0, 0, mView->itemWidth(), h+(2*mg)), cg, + QStyle::Style_FocusAtBorder, + QStyleOption( isSelected() ? cg.highlight() : cg.base() ) ); +*/ + + const QColor pHighl = isSelected() ? cg.highlight() : cg.base(); + const QRect r(0, 0, mView->itemWidth(), h+(2*mg)); +#ifndef DESKTOP_VERSION + mView->style().drawFocusRect(p, r, cg, &pHighl, true); +#endif + } +} + +const QString &CardViewItem::caption() const +{ + return d->mCaption; +} + + +int CardViewItem::height( bool allowCache ) const +{ + // use cache + if ( allowCache && d->hcache ) + return d->hcache; + + // Base height: + // 2 for line width + // 2 for top caption pad + // 2 for bottom caption pad + // 2 pad for the end + // + 2 times the advised margin + int baseHeight = 8 + ( 2 * mView->itemMargin() ); + + // size of font for each field + // 2 pad for each field + + // anders: if the view does not show empty fields, check for value + bool sef = mView->showEmptyFields(); + int fh = mView->d->mFm->height();//lineSpacing(); // font height + //int sp = QMAX( 0, 2- mView->d->mFm->leading() ); // field spacing NOTE make a property + int fieldHeight = 0; + int lines; + int maxLines( mView->maxFieldLines() ); + QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); + for (iter.toFirst(); iter.current(); ++iter) + { + if ( !sef && (*iter)->second.isEmpty() ) + continue; + lines = QMIN( (*iter)->second.contains('\n') + 1, maxLines ); + fieldHeight += ( lines * fh ) + 2;//sp; + } + + // height of caption font (bold) + fieldHeight += mView->d->mBFm->height(); + d->hcache = baseHeight + fieldHeight; + return d->hcache; +} + +bool CardViewItem::isSelected() const +{ + return d->mSelected; +} + +void CardViewItem::setSelected(bool selected) +{ + d->mSelected = selected; +} + +void CardViewItem::insertField(const QString &label, const QString &value) +{ + CardViewItem::Field *f = new CardViewItem::Field(label, value); + d->mFieldList.append(f); + d->hcache=0; + + if (mView) + { + mView->setLayoutDirty(true); + d->maxLabelWidth = QMAX( mView->d->mFm->width( label ), d->maxLabelWidth ); + } +} + +void CardViewItem::removeField(const QString &label) +{ + CardViewItem::Field *f; + + QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); + for (iter.toFirst(); iter.current(); ++iter) + { + f = *iter; + if (f->first == label) + break; + } + + if (*iter) + d->mFieldList.remove(*iter); + d->hcache = 0; + + if (mView) + mView->setLayoutDirty(true); +} + +void CardViewItem::clearFields() +{ + d->mFieldList.clear(); + d->hcache = 0; + + if (mView) + mView->setLayoutDirty(true); +} + +QString CardViewItem::trimString(const QString &text, int width, + QFontMetrics &fm) +{ + if (fm.width(text) <= width) + return text; + + QString dots = "..."; + int dotWidth = fm.width(dots); + QString trimmed; + int charNum = 0; + + while (fm.width(trimmed) + dotWidth < width) + { + trimmed += text[charNum]; + charNum++; + } + + // Now trim the last char, since it put the width over the top + trimmed = trimmed.left(trimmed.length()-1); + trimmed += dots; + + return trimmed; +} + +CardViewItem *CardViewItem::nextItem() +{ + CardViewItem *item = 0; + + if (mView) + item = mView->itemAfter(this); + + return item; +} + +void CardViewItem::repaintCard() +{ + if (mView) + mView->repaintItem(this); +} + +void CardViewItem::setCaption(const QString &caption) +{ + d->mCaption = caption; + repaintCard(); +} + +QString CardViewItem::fieldValue(const QString &label) +{ + QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); + for (iter.toFirst(); iter.current(); ++iter) + if ((*iter)->first == label) + return (*iter)->second; + + return QString(); +} + + +void CardViewItem::showFullString( const QPoint &itempos, CardViewTip *tip ) +{ + bool trimmed( false ); + QString s; + int mrg = mView->itemMargin(); + int y = mView->d->mBFm->height() + 6 + mrg; + int w = mView->itemWidth() - (2*mrg); + int lw; + bool drawLabels = mView->drawFieldLabels(); + bool isLabel = drawLabels && itempos.x() < w/2 ? true : false; + + if ( itempos.y() < y ) + { + if ( itempos.y() < 8 + mrg || itempos.y() > y - 4 ) + return; + // this is the caption + s = caption(); + trimmed = mView->d->mBFm->width( s ) > w - 4; + y = 2 + mrg; + lw = 0; + isLabel=true; + } else { + // find the field + Field *f = fieldAt( itempos ); + if ( !f || ( !mView->showEmptyFields() && f->second.isEmpty() ) ) + return; + + // y position: + // header font height + 4px hader margin + 2px leading + item margin + // + actual field index * (fontheight + 2px leading) + int maxLines = mView->maxFieldLines(); + bool se = mView->showEmptyFields(); + int fh = mView->d->mFm->height(); +// { + Field *_f; + for (_f = d->mFieldList.first(); _f != f; _f = d->mFieldList.next()) + if ( se || ! _f->second.isEmpty() ) + y += ( QMIN(_f->second.contains('\n')+1, maxLines) * fh ) + 2; +// } + if ( isLabel && itempos.y() > y + fh ) + return; + // label or data? + s = isLabel ? f->first : f->second; + // trimmed? + int colonWidth = mView->d->mFm->width(":"); + lw = drawLabels ? // label width + QMIN( w/2 - 4 - mrg, d->maxLabelWidth + colonWidth + 4 ) : + 0; + int mw = isLabel ? lw - colonWidth : w - lw - (mrg*2); // max width for string + if ( isLabel ) + { + trimmed = mView->d->mFm->width( s ) > mw - colonWidth; + } else { + QRect r( mView->d->mFm->boundingRect( 0, 0, INT_MAX, INT_MAX, Qt::AlignTop|Qt::AlignLeft, s ) ); + trimmed = r.width() > mw || r.height()/fh > QMIN(s.contains('\n') + 1, maxLines); + } + } + if ( trimmed ) + { + tip->setFont( (isLabel && !lw) ? mView->headerFont() : mView->font() ); // if condition is true, a header + tip->setText( s ); + tip->adjustSize(); + // find a proper position + int lx; + lx = isLabel || !drawLabels ? mrg : lw + mrg + 2 /*-1*/; + QPoint pnt(mView->contentsToViewport( QPoint(d->x, d->y) )); + pnt += QPoint(lx, y); + if ( pnt.x() < 0 ) + pnt.setX( 0 ); + if ( pnt.x() + tip->width() > mView->visibleWidth() ) + pnt.setX( mView->visibleWidth() - tip->width() ); + if ( pnt.y() + tip->height() > mView->visibleHeight() ) + pnt.setY( QMAX( 0, mView->visibleHeight() - tip->height() ) ); + // show + tip->move( pnt ); + tip->show(); + } +} + +CardViewItem::Field *CardViewItem::fieldAt( const QPoint & itempos ) const +{ + int ypos = mView->d->mBFm->height() + 7 + mView->d->mItemMargin; + int iy = itempos.y(); + // skip below caption + if ( iy <= ypos ) + return 0; + // try find a field + bool showEmpty = mView->showEmptyFields(); + int fh = mView->d->mFm->height(); + int maxLines = mView->maxFieldLines(); + Field *f; + for ( f = d->mFieldList.first(); f; f = d->mFieldList.next() ) + { + if ( showEmpty || !f->second.isEmpty() ) + ypos += ( QMIN( f->second.contains('\n')+1, maxLines ) *fh)+2; + if ( iy <= ypos ) + break; + } + return f ? f : 0; +} +//END CardViewItem + +//BEGIN CardView + +CardView::CardView(QWidget *parent, const char *name) + : QScrollView(parent, name), + d(new CardViewPrivate()) +{ + d->mItemList.setAutoDelete(true); + d->mSeparatorList.setAutoDelete(true); + + QFont f = font(); + d->mFm = new QFontMetrics(f); + f.setBold(true); + d->mHeaderFont = f; + d->mBFm = new QFontMetrics(f); + d->mTip = ( new CardViewTip( viewport() ) ), + d->mTip->hide(); + d->mTimer = ( new QTimer(this, "mouseTimer") ), + + viewport()->setMouseTracking( true ); + viewport()->setFocusProxy(this); + viewport()->setFocusPolicy(WheelFocus); + viewport()->setBackgroundMode(PaletteBase); + + connect( d->mTimer, SIGNAL(timeout()), this, SLOT(tryShowFullText()) ); + +//US setBackgroundMode(PaletteBackground, PaletteBase); + setBackgroundMode(PaletteBackground); + + // no reason for a vertical scrollbar + setVScrollBarMode(AlwaysOff); +} + +CardView::~CardView() +{ + delete d->mFm; + delete d->mBFm; + delete d; + d = 0; +} + +void CardView::insertItem(CardViewItem *item) +{ + d->mItemList.inSort(item); + setLayoutDirty(true); +} + +void CardView::takeItem(CardViewItem *item) +{ + if ( d->mCurrentItem == item ) + d->mCurrentItem = item->nextItem(); + d->mItemList.take(d->mItemList.findRef(item)); + + setLayoutDirty(true); +} + +void CardView::clear() +{ + d->mItemList.clear(); + + setLayoutDirty(true); +} + +CardViewItem *CardView::currentItem() +{ + if ( ! d->mCurrentItem && d->mItemList.count() ) + d->mCurrentItem = d->mItemList.first(); + return d->mCurrentItem; +} + +void CardView::setCurrentItem( CardViewItem *item ) +{ + if ( !item ) + return; + else if ( item->cardView() != this ) + { + kdDebug(5720)<<"CardView::setCurrentItem: Item ("<<item<<") not owned! Backing out.."<<endl; + return; + } + else if ( item == currentItem() ) + { + return; + } + + if ( d->mSelectionMode == Single ) + { + setSelected( item, true ); + } + else + { + CardViewItem *it = d->mCurrentItem; + d->mCurrentItem = item; + if ( it ) + it->repaintCard(); + item->repaintCard(); + } + if ( ! d->mOnSeparator ) + ensureItemVisible( item ); + emit currentChanged( item ); +} + +CardViewItem *CardView::itemAt(const QPoint &viewPos) +{ + CardViewItem *item = 0; + QPtrListIterator<CardViewItem> iter(d->mItemList); + bool found = false; + for (iter.toFirst(); iter.current() && !found; ++iter) + { + item = *iter; + //if (item->d->mRect.contains(viewPos)) + if (QRect(item->d->x, item->d->y, d->mItemWidth, item->height()).contains(viewPos)) + found = true; + } + + if (found) + return item; + + return 0; +} + +QRect CardView::itemRect(const CardViewItem *item) +{ + //return item->d->mRect; + return QRect(item->d->x, item->d->y, d->mItemWidth, item->height()); +} + +void CardView::ensureItemVisible(const CardViewItem *item) +{ + ensureVisible(item->d->x , item->d->y, d->mItemSpacing, 0); + ensureVisible(item->d->x + d->mItemWidth, item->d->y, d->mItemSpacing, 0); +} + +void CardView::repaintItem(const CardViewItem *item) +{ + //repaintContents(item->d->mRect); + repaintContents( QRect(item->d->x, item->d->y, d->mItemWidth, item->height()) ); +} + +void CardView::setSelectionMode(CardView::SelectionMode mode) +{ + selectAll(false); + + d->mSelectionMode = mode; +} + +CardView::SelectionMode CardView::selectionMode() const +{ + return d->mSelectionMode; +} + +void CardView::selectAll(bool state) +{ + QPtrListIterator<CardViewItem> iter(d->mItemList); + if (!state) + { + for (iter.toFirst(); iter.current(); ++iter) + { + if ((*iter)->isSelected()) + { + (*iter)->setSelected(false); + (*iter)->repaintCard(); + } + } + //emit selectionChanged(); // WARNING FIXME + emit selectionChanged(0); + } + else if (d->mSelectionMode != CardView::Single) + { + for (iter.toFirst(); iter.current(); ++iter) + { + (*iter)->setSelected(true); + } + + if (d->mItemList.count() > 0) + { + // emit, since there must have been at least one selected + emit selectionChanged(); + //repaint();//??? + viewport()->update(); + } + } +} + +void CardView::setSelected(CardViewItem *item, bool selected) +{ + if ((item == 0) || (item->isSelected() == selected)) + return; + + if ( selected && d->mCurrentItem != item ) + { + CardViewItem *it = d->mCurrentItem; + d->mCurrentItem = item; + if ( it ) + it->repaintCard(); + } + + if (d->mSelectionMode == CardView::Single) + { + bool b = signalsBlocked(); + blockSignals(true); + selectAll(false); + blockSignals(b); + + if (selected) + { + item->setSelected(selected); + item->repaintCard(); + emit selectionChanged(); + emit selectionChanged(item); + } + else + { + emit selectionChanged(); + emit selectionChanged(0); + } + } + else if (d->mSelectionMode == CardView::Multi) + { + item->setSelected(selected); + item->repaintCard(); + emit selectionChanged(); + } + else if (d->mSelectionMode == CardView::Extended) + { + bool b = signalsBlocked(); + blockSignals(true); + selectAll(false); + blockSignals(b); + + item->setSelected(selected); + item->repaintCard(); + emit selectionChanged(); + } +} + +bool CardView::isSelected(CardViewItem *item) const +{ + return (item && item->isSelected()); +} + +CardViewItem *CardView::selectedItem() const +{ + // find the first selected item + QPtrListIterator<CardViewItem> iter(d->mItemList); + for (iter.toFirst(); iter.current(); ++iter) + { + if ((*iter)->isSelected()) + return *iter; + } + + return 0; +} + +CardViewItem *CardView::firstItem() const +{ + return d->mItemList.first(); +} + +int CardView::childCount() const +{ + return d->mItemList.count(); +} +/*US +CardViewItem *CardView::findItem(const QString &text, const QString &label, + Qt::StringComparisonMode compare) +{ + // IF the text is empty, we will return null, since empty text will + // match anything! + if (text.isEmpty()) + return 0; + + QPtrListIterator<CardViewItem> iter(d->mItemList); + if (compare & Qt::BeginsWith) + { + QString value; + for (iter.toFirst(); iter.current(); ++iter) + { + value = (*iter)->fieldValue(label).upper(); + if (value.startsWith(text.upper())) + return *iter; + } + } + else + { + kdDebug(5720) << "CardView::findItem: search method not implemented" << endl; + } + + return 0; +} +*/ + +uint CardView::columnWidth() +{ + return d->mDrawSeparators ? + d->mItemWidth + ( 2 * d->mItemSpacing ) + d->mSepWidth : + d->mItemWidth + d->mItemSpacing; +} + +void CardView::drawContents(QPainter *p, int clipx, int clipy, + int clipw, int cliph) +{ + QScrollView::drawContents(p, clipx, clipy, clipw, cliph); + + if (d->mLayoutDirty) + calcLayout(); + + //kdDebug() << "CardView::drawContents: " << clipx << ", " << clipy + // << ", " << clipw << ", " << cliph << endl; + + QColorGroup cg = viewport()->palette().active(); // allow setting costum colors in the viewport pale + + QRect clipRect(clipx, clipy, clipw, cliph); + QRect cardRect; + QRect sepRect; + CardViewItem *item; + CardViewSeparator *sep; + + // make sure the viewport is a pure background + viewport()->erase(clipRect); + + // Now tell the cards to draw, if they are in the clip region + QPtrListIterator<CardViewItem> iter(d->mItemList); + for (iter.toFirst(); iter.current(); ++iter) + { + item = *iter; + cardRect.setRect( item->d->x, item->d->y, d->mItemWidth, item->height() ); + + if (clipRect.intersects(cardRect) || clipRect.contains(cardRect)) + { + //kdDebug() << "\trepainting card at: " << cardRect.x() << ", " + // << cardRect.y() << endl; + + // Tell the card to paint + p->save(); + p->translate(cardRect.x(), cardRect.y()); + item->paintCard(p, cg); + p->restore(); + } + } + + // Followed by the separators if they are in the clip region + QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList); + for (sepIter.toFirst(); sepIter.current(); ++sepIter) + { + sep = *sepIter; + sepRect = sep->mRect; + + if (clipRect.intersects(sepRect) || clipRect.contains(sepRect)) + { + p->save(); + p->translate(sepRect.x(), sepRect.y()); + sep->paintSeparator(p, cg); + p->restore(); + } + } +} + +void CardView::resizeEvent(QResizeEvent *e) +{ + QScrollView::resizeEvent(e); + + setLayoutDirty(true); +} + +void CardView::calcLayout() +{ + //kdDebug() << "CardView::calcLayout:" << endl; + + // Start in the upper left corner and layout all the + // cars using their height and width + int maxWidth = 0; + int maxHeight = 0; + int xPos = 0; + int yPos = 0; + int cardSpacing = d->mItemSpacing; + + // delete the old separators + d->mSeparatorList.clear(); + + QPtrListIterator<CardViewItem> iter(d->mItemList); + CardViewItem *item = 0; + CardViewSeparator *sep = 0; + xPos += cardSpacing; + + for (iter.toFirst(); iter.current(); ++iter) + { + item = *iter; + + yPos += cardSpacing; + + if (yPos + item->height() + cardSpacing >= height() - horizontalScrollBar()->height()) + { + maxHeight = QMAX(maxHeight, yPos); + + // Drawing in this column would be greater than the height + // of the scroll view, so move to next column + yPos = cardSpacing; + xPos += cardSpacing + maxWidth; + if (d->mDrawSeparators) + { + // Create a separator since the user asked + sep = new CardViewSeparator(this); + sep->mRect.moveTopLeft(QPoint(xPos, yPos+d->mItemMargin)); + xPos += d->mSepWidth + cardSpacing; + d->mSeparatorList.append(sep); + } + + maxWidth = 0; + } + + item->d->x = xPos; + item->d->y = yPos; + + yPos += item->height(); + maxWidth = QMAX(maxWidth, d->mItemWidth); + } + + xPos += maxWidth; + resizeContents( xPos + cardSpacing, maxHeight ); + + // Update the height of all the separators now that we know the + // max height of a column + QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList); + for (sepIter.toFirst(); sepIter.current(); ++sepIter) + { + (*sepIter)->mRect.setHeight(maxHeight - 2*cardSpacing - 2*d->mItemMargin); + } + + d->mLayoutDirty = false; +} + +CardViewItem *CardView::itemAfter(CardViewItem *item) +{ + /*int pos = */d->mItemList.findRef(item); + return d->mItemList.next();//at(pos+1); +} + +uint CardView::itemMargin() +{ + return d->mItemMargin; +} + +void CardView::setItemMargin( uint margin ) +{ + if ( margin == d->mItemMargin ) + return; + + d->mItemMargin = margin; + setLayoutDirty( true ); +} + +uint CardView::itemSpacing() +{ + return d->mItemSpacing; +} + +void CardView::setItemSpacing( uint spacing ) +{ + if ( spacing == d->mItemSpacing ) + return; + + d->mItemSpacing = spacing; + setLayoutDirty( true ); +} + +void CardView::contentsMousePressEvent(QMouseEvent *e) +{ + QScrollView::contentsMousePressEvent(e); + + QPoint pos = e->pos(); + d->mLastClickPos = pos; + + CardViewItem *item = itemAt(pos); + + if (item == 0) + { + d->mLastClickOnItem = false; + if ( d->mOnSeparator) + { + d->mResizeAnchor = e->x()+contentsX(); + d->colspace = (2*d->mItemSpacing) /*+ (2*d->mItemMargin)*/; + int ccw = d->mItemWidth + d->colspace + d->mSepWidth; + d->first = (contentsX()+d->mSepWidth)/ccw; + d->pressed = (d->mResizeAnchor+d->mSepWidth)/ccw; + d->span = d->pressed - d->first; + d->firstX = d->first * ccw; + if ( d->firstX ) d->firstX -= d->mSepWidth; // (no sep in col 0) + } + else + { + selectAll(false); + } + return; + } + + d->mLastClickOnItem = true; + + CardViewItem *other = d->mCurrentItem; + setCurrentItem( item ); + + // Always emit the selection + emit clicked(item); + + // Check the selection type and update accordingly + if (d->mSelectionMode == CardView::Single) + { + // make sure it isn't already selected + if (item->isSelected()) + return; + + bool b = signalsBlocked(); + blockSignals(true); + selectAll(false); + blockSignals(b); + + item->setSelected(true); + item->repaintCard(); + emit selectionChanged(item); + } + + else if (d->mSelectionMode == CardView::Multi) + { + // toggle the selection + item->setSelected(!item->isSelected()); + item->repaintCard(); + emit selectionChanged(); + } + + else if (d->mSelectionMode == CardView::Extended) + { + if ((e->button() & Qt::LeftButton) && + (e->state() & Qt::ShiftButton)) + { + if ( item == other ) return; + + bool s = ! item->isSelected(); + + if ( s && ! (e->state() & ControlButton) ) + { + bool b = signalsBlocked(); + blockSignals(true); + selectAll(false); + blockSignals(b); + } + + int from, to, a, b; + a = d->mItemList.findRef( item ); + b = d->mItemList.findRef( other ); + from = a < b ? a : b; + to = a > b ? a : b; + //kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl; + CardViewItem *aItem; + for ( ; from <= to; from++ ) + { + aItem = d->mItemList.at( from ); + aItem->setSelected( s ); + repaintItem( aItem ); + } + emit selectionChanged(); + } + else if ((e->button() & Qt::LeftButton) && + (e->state() & Qt::ControlButton)) + { + item->setSelected(!item->isSelected()); + item->repaintCard(); + emit selectionChanged(); + } + + else if (e->button() & Qt::LeftButton) + { + bool b = signalsBlocked(); + blockSignals(true); + selectAll(false); + blockSignals(b); + + item->setSelected(true); + item->repaintCard(); + emit selectionChanged(); + } + } + +} + +void CardView::contentsMouseReleaseEvent(QMouseEvent *e) +{ + QScrollView::contentsMouseReleaseEvent(e); + + if ( d->mResizeAnchor ) + { + // finish the resizing: + unsetCursor(); + // hide rubber bands + int newiw = d->mItemWidth - ((d->mResizeAnchor - d->mRubberBandAnchor)/d->span); + drawRubberBands( 0 ); + // we should move to reflect the new position if we are scrolled. + if ( contentsX() ) + { + int newX = QMAX( 0, ( d->pressed * ( newiw + d->colspace + d->mSepWidth ) ) - e->x() ); + setContentsPos( newX, contentsY() ); + } + // set new item width + setItemWidth( newiw ); + // reset anchors + d->mResizeAnchor = 0; + d->mRubberBandAnchor = 0; + return; + } + + // If there are accel keys, we will not emit signals + if ((e->state() & Qt::ShiftButton) || (e->state() & Qt::ControlButton)) + return; + + // Get the item at this position + CardViewItem *item = itemAt(e->pos()); + + if (item && KGlobalSettings::singleClick()) + { + emit executed(item); + } +} + +void CardView::contentsMouseDoubleClickEvent(QMouseEvent *e) +{ + QScrollView::contentsMouseDoubleClickEvent(e); + + CardViewItem *item = itemAt(e->pos()); + + if (item) + { + d->mCurrentItem = item; + } + + if (item && !KGlobalSettings::singleClick()) + { + emit executed(item); + } + emit doubleClicked(item); +} + +void CardView::contentsMouseMoveEvent( QMouseEvent *e ) +{ + // resizing + if ( d->mResizeAnchor ) + { + int x = e->x(); + if ( x != d->mRubberBandAnchor ) + drawRubberBands( x ); + return; + } + + if (d->mLastClickOnItem && (e->state() & Qt::LeftButton) && + ((e->pos() - d->mLastClickPos).manhattanLength() > 4)) { + + startDrag(); + return; + } + + d->mTimer->start( 500 ); + + // see if we are over a separator + // only if we actually have them painted? + if ( d->mDrawSeparators ) + { + int colcontentw = d->mItemWidth + (2*d->mItemSpacing); + int colw = colcontentw + d->mSepWidth; + int m = e->x()%colw; + if ( m >= colcontentw && m > 0 ) + { + setCursor( SplitVCursor ); // Why does this fail sometimes? + d->mOnSeparator = true; + } + else + { + setCursor( ArrowCursor ); + d->mOnSeparator = false; + } + } +} + +void CardView::enterEvent( QEvent * ) +{ + d->mTimer->start( 500 ); +} + +void CardView::leaveEvent( QEvent * ) +{ + d->mTimer->stop(); + if (d->mOnSeparator) + { + d->mOnSeparator = false; + setCursor( ArrowCursor ); + } +} + +void CardView::focusInEvent( QFocusEvent * ) +{ + if (!d->mCurrentItem && d->mItemList.count() ) + { + setCurrentItem( d->mItemList.first() ); + } + else if ( d->mCurrentItem ) + { + d->mCurrentItem->repaintCard(); + } +} + +void CardView::focusOutEvent( QFocusEvent * ) +{ + if (d->mCurrentItem) + d->mCurrentItem->repaintCard(); +} + +void CardView::keyPressEvent( QKeyEvent *e ) +{ + if ( ! ( childCount() && d->mCurrentItem ) ) + { + e->ignore(); + return; + } + + uint pos = d->mItemList.findRef( d->mCurrentItem ); + CardViewItem *aItem = 0L; // item that gets the focus + CardViewItem *old = d->mCurrentItem; + + switch ( e->key() ) + { + case Key_Up: + if ( pos > 0 ) + { + aItem = d->mItemList.at( pos - 1 ); + setCurrentItem( aItem ); + } + break; + case Key_Down: + if ( pos < d->mItemList.count() - 1 ) + { + aItem = d->mItemList.at( pos + 1 ); + setCurrentItem( aItem ); + } + break; + case Key_Left: + { + // look for an item in the previous/next column, starting from + // the vertical middle of the current item. + // FIXME use nice calculatd measures!!! + QPoint aPoint( d->mCurrentItem->d->x, d->mCurrentItem->d->y ); + aPoint -= QPoint( 30,-(d->mCurrentItem->height()/2) ); + aItem = itemAt( aPoint ); + // maybe we hit some space below an item + while ( !aItem && aPoint.y() > 27 ) + { + aPoint -= QPoint( 0, 16 ); + aItem = itemAt( aPoint ); + } + if ( aItem ) + setCurrentItem( aItem ); + } + break; + case Key_Right: + { + // FIXME use nice calculated measures!!! + QPoint aPoint( d->mCurrentItem->d->x + d->mItemWidth, d->mCurrentItem->d->y ); + aPoint += QPoint( 30,(d->mCurrentItem->height()/2) ); + aItem = itemAt( aPoint ); + while ( !aItem && aPoint.y() > 27 ) + { + aPoint -= QPoint( 0, 16 ); + aItem = itemAt( aPoint ); + } + if ( aItem ) + setCurrentItem( aItem ); + } + break; + case Key_Home: + aItem = d->mItemList.first(); + setCurrentItem( aItem ); + break; + case Key_End: + aItem = d->mItemList.last(); + setCurrentItem( aItem ); + break; + case Key_Prior: // PageUp + { + // QListView: "Make the item above the top visible and current" + // TODO if contentsY(), pick the top item of the leftmost visible column + if ( contentsX() <= 0 ) + return; + int cw = columnWidth(); + int theCol = ( QMAX( 0, ( contentsX()/cw) * cw ) ) + d->mItemSpacing; + aItem = itemAt( QPoint( theCol + 1, d->mItemSpacing + 1 ) ); + if ( aItem ) + setCurrentItem( aItem ); + } + break; + case Key_Next: // PageDown + { + // QListView: "Make the item below the bottom visible and current" + // find the first not fully visible column. + // TODO: consider if a partly visible (or even hidden) item at the + // bottom of the rightmost column exists + int cw = columnWidth(); + int theCol = ( (( contentsX() + visibleWidth() )/cw) * cw ) + d->mItemSpacing + 1; + // if separators are on, we may need to we may be one column further right if only the spacing/sep is hidden + if ( d->mDrawSeparators && cw - (( contentsX() + visibleWidth() )%cw) <= int( d->mItemSpacing + d->mSepWidth ) ) + theCol += cw; + + // make sure this is not too far right + while ( theCol > contentsWidth() ) + theCol -= columnWidth(); + + aItem = itemAt( QPoint( theCol, d->mItemSpacing + 1 ) ); + + if ( aItem ) + setCurrentItem( aItem ); + } + break; + case Key_Space: + setSelected( d->mCurrentItem, !d->mCurrentItem->isSelected() ); + emit selectionChanged(); + break; + case Key_Return: + case Key_Enter: + emit returnPressed( d->mCurrentItem ); + emit executed( d->mCurrentItem ); + break; + default: + if ( (e->state() & ControlButton) && e->key() == Key_A ) + { + // select all + selectAll( true ); + break; + } + // if we have a string, do autosearch + else if ( ! e->text().isEmpty() && e->text()[0].isPrint() ) + { + + } + break; + } + // handle selection + if ( aItem ) + { + if ( d->mSelectionMode == CardView::Extended ) + { + if ( (e->state() & ShiftButton) ) + { + // shift button: toggle range + // if control button is pressed, leave all items + // and toggle selection current->old current + // otherwise, ?????? + bool s = ! aItem->isSelected(); + int from, to, a, b; + a = d->mItemList.findRef( aItem ); + b = d->mItemList.findRef( old ); + from = a < b ? a : b; + to = a > b ? a : b; + + if ( to - from > 1 ) + { + bool b = signalsBlocked(); + blockSignals(true); + selectAll(false); + blockSignals(b); + } + + //kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl; + CardViewItem *item; + for ( ; from <= to; from++ ) + { + item = d->mItemList.at( from ); + item->setSelected( s ); + repaintItem( item ); + } + emit selectionChanged(); + } + else if ( (e->state() & ControlButton) ) + { + // control button: do nothing + } + else + { + // no button: move selection to this item + bool b = signalsBlocked(); + blockSignals(true); + selectAll(false); + blockSignals(b); + + setSelected( aItem, true ); + emit selectionChanged(); + } + } + } +} + +void CardView::contentsWheelEvent( QWheelEvent * e ) +{ + scrollBy(2*e->delta()/-3, 0); +} + +void CardView::setLayoutDirty(bool dirty) +{ + if (d->mLayoutDirty != dirty) + { + d->mLayoutDirty = dirty; + repaint(); + } +} + +void CardView::setDrawCardBorder(bool enabled) +{ + if (enabled != d->mDrawCardBorder) + { + d->mDrawCardBorder = enabled; + repaint(); + } +} + +bool CardView::drawCardBorder() const +{ + return d->mDrawCardBorder; +} + +void CardView::setDrawColSeparators(bool enabled) +{ + if (enabled != d->mDrawSeparators) + { + d->mDrawSeparators = enabled; + setLayoutDirty(true); + } +} + +bool CardView::drawColSeparators() const +{ + return d->mDrawSeparators; +} + +void CardView::setDrawFieldLabels(bool enabled) +{ + if (enabled != d->mDrawFieldLabels) + { + d->mDrawFieldLabels = enabled; + repaint(); + } +} + +bool CardView::drawFieldLabels() const +{ + return d->mDrawFieldLabels; +} + +void CardView::setShowEmptyFields(bool show) +{ + if (show != d->mShowEmptyFields) + { + d->mShowEmptyFields = show; + setLayoutDirty(true); + } +} + +bool CardView::showEmptyFields() const +{ + return d->mShowEmptyFields; +} + +void CardView::startDrag() +{ + // The default implementation is a no-op. It must be + // reimplemented in a subclass to be useful +} +void CardView::tryShowFullText() +{ + d->mTimer->stop(); + // if we have an item + QPoint cpos = viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ); + CardViewItem *item = itemAt( cpos ); + if ( item ) + { + // query it for a value to display + //QString s = item ? item->caption() : "(no item)"; + //kdDebug()<<"MOUSE REST: "<<s<<endl; + QPoint ipos = cpos - itemRect( item ).topLeft(); + item->showFullString( ipos, d->mTip ); + } +} + +void CardView::drawRubberBands( int pos ) +{ + if ( pos && ((pos-d->firstX)/d->span) - d->colspace - d->mSepWidth < MIN_ITEM_WIDTH ) return; + + int tmpcw = (d->mRubberBandAnchor-d->firstX)/d->span; + int x = d->firstX + tmpcw - d->mSepWidth - contentsX(); + int h = visibleHeight(); + + QPainter p( viewport() ); + p.setRasterOp( XorROP ); + p.setPen( gray ); + p.setBrush( gray ); + uint n = d->first; + // erase + if ( d->mRubberBandAnchor ) + do { + p.drawRect( x, 0, 2, h ); + x += tmpcw; + n++; + } while ( x < visibleWidth() && n < d->mSeparatorList.count() ); + // paint new + if ( ! pos ) return; + tmpcw = (pos - d->firstX)/d->span; + n = d->first; + x = d->firstX + tmpcw - d->mSepWidth - contentsX(); + do { + p.drawRect( x, 0, 2, h ); + x += tmpcw; + n++; + } while ( x < visibleWidth() && n < d->mSeparatorList.count() ); + d->mRubberBandAnchor = pos; +} + + +int CardView::itemWidth() const +{ + return d->mItemWidth; +} + +void CardView::setItemWidth( int w ) +{ + if ( w == d->mItemWidth ) + return; + if ( w < MIN_ITEM_WIDTH ) + w = MIN_ITEM_WIDTH; + d->mItemWidth = w; + setLayoutDirty( true ); +#ifndef KAB_EMBEDDED + updateContents(); +#else //KAB_EMBEDDED +//US updateContents( d->contentsX(), d->contentsY(), visibleWidth(), visibleHeight() ); +qDebug("CardView::setItemWidth has to be verified"); + updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); +#endif //KAB_EMBEDDED +} + +void CardView::setHeaderFont( const QFont &fnt ) +{ + d->mHeaderFont = fnt; + delete d->mBFm; + d->mBFm = new QFontMetrics( fnt ); +} + +QFont CardView::headerFont() const +{ + return d->mHeaderFont; +} + +void CardView::setFont( const QFont &fnt ) +{ + QScrollView::setFont( fnt ); + delete d->mFm; + d->mFm = new QFontMetrics( fnt ); +} + +int CardView::separatorWidth() +{ + return d->mSepWidth; +} + +void CardView::setSeparatorWidth( int width ) +{ + d->mSepWidth = width; + setLayoutDirty( true ); // hmm, actually I could just adjust the x'es... +} + +int CardView::maxFieldLines() const +{ + return d->mMaxFieldLines; +} + +void CardView::setMaxFieldLines( int howmany ) +{ + d->mMaxFieldLines = howmany ? howmany : INT_MAX; + // FIXME update, forcing the items to recalc height!! +} +//END Cardview + +#ifndef KAB_EMBEDDED +#include "cardview.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/views/cardview.desktop b/kaddressbook/views/cardview.desktop new file mode 100644 index 0000000..8507360 --- a/dev/null +++ b/kaddressbook/views/cardview.desktop @@ -0,0 +1,18 @@ +[Desktop Entry] +Encoding=UTF-8 +X-KDE-Library=libkaddrbk_cardview +Name=Card View +Name[be]=У выглÑдзе картак +Name[ca]=Vista de targeta +Name[da]=Kort-visning +Name[el]=Î Ïοβολή καÏτών +Name[es]=Vista de tarjeta +Name[hu]=Kártyanézet +Name[pt_BR]=Visualização de Cartão +Name[ru]=Карточка +Name[sk]=Prezeranie karty +Name[sv]=Kortvy +Name[tr]=Kart Görünümü +Name[zh_CN]=å¡ç‰‡è§†å›¾ +Type=Service +ServiceTypes=KAddressBook/View diff --git a/kaddressbook/views/cardview.h b/kaddressbook/views/cardview.h new file mode 100644 index 0000000..37dddb6 --- a/dev/null +++ b/kaddressbook/views/cardview.h @@ -0,0 +1,473 @@ +#ifndef CARDVIEW_H +#define CARDVIEW_H + +#include <qscrollview.h> +#include <qptrlist.h> +#include <qstring.h> +#include <qrect.h> +#include <qpair.h> +#include <qpoint.h> + +class QLabel; +class QPainter; +class QResizeEvent; +class QMouseEvent; +class CardView; +class CardViewPrivate; +class CardViewItemPrivate; +class CardViewTip; + +/** Represents a single card (item) in the card view. A card has a caption +* and a list of fields. A Field is a label<->value pair. The labels in a +* card should be unique, since they will be used to index the values. +*/ +class CardViewItem +{ + friend class CardView; + + public: + /** A single field in the card view. The first item is the label + * and the second item is the value. + */ + typedef QPair<QString, QString> Field; + + /** Constructor. + * + * @param parent The CardView that this card should be displayed on. + * @param caption The caption of the card. This is the text that will + * appear at the top of the card. This is also the string that will + * be used to sort the cards in the view. + */ + CardViewItem(CardView *parent, QString caption = QString::null); + virtual ~CardViewItem(); + + /** @return The caption of the card, or QString::null if none was ever + * set. + */ + const QString &caption() const; + + /** Sets the caption of the card. This is the text that will + * appear at the top of the card. This is also the string that will + * be used to sort the cards in the view. + */ + void setCaption(const QString &caption); + + /** Paints the card using the given painter and color group. The + * card will handle painting itself selected if it is selected. + */ + virtual void paintCard(QPainter *p, QColorGroup &cg); + + /** Repaints the card. This is done by sending a repaint event to the + * view with the clip rect defined as this card. + */ + virtual void repaintCard(); + + /** Adds a field to the card. + * + * @param label The label of the field. The field labels must be unique + * within a card. + * @param The value of the field. + */ + void insertField(const QString &label, const QString &value); + + /** Removes the field with label <i>label</i> from the card. + */ + void removeField(const QString &label); + + /** @return The value of the field with label <i>label</i>. + */ + QString fieldValue(const QString &label); + + /** Removes all the fields from this card. + */ + void clearFields(); + + /** @return The next card item. The order of the items will be the same + * as the display order in the view. 0 will be returned if this is the + * last card. + */ + CardViewItem *nextItem(); + + /** @return True if this card is currently selected, false otherwise. + */ + bool isSelected() const; + + /** Called by the parent card view when the mouse has been resting for + * a certain amount of time. If the label or value at pos is obscured + * (trimmed) make the label display the full text. + */ + void showFullString( const QPoint &pos, CardViewTip *tip ); + + /** @return a pointer to the Field at the position itempos + * in this item. 0 is returned if itempos is in the caption. + * @param itempos the position in item coordinates + */ + Field *fieldAt( const QPoint &itempos ) const; + + CardView *cardView() { return mView; }; + + /** @return The height of this item as rendered, in pixels. + + if @p allowCache is true, the item may use an internally + cached value rather than recalculating from scratch. The + argument is mainly to allow the cardView to change global settings (like + maxFieldLines) that might influence the items heights + */ + int height( bool allowCache=true ) const; + + protected: + /** Sets the card as selected. This is usually only called from the + * card view. + */ + void setSelected(bool selected); + + private: + /** Sets the default values. + */ + void initialize(); + + /** Trims a string to the width <i>width</i> using the font metrics + * to determine the width of each char. If the string is longer than + * <i>width</i>, then the string will be trimmed and a '...' will + * be appended. + */ + QString trimString(const QString &text, int width, QFontMetrics &fm); + + CardViewItemPrivate *d; + CardView *mView; +}; + +/** The CardView is a method of displaying data in cards. This idea is +* similar to the idea of a rolodex or business cards. Each card has a +* caption and a list of fields, which are label<->value pairs. The CardView +* displays multiple cards in a grid. The Cards are sorted based on their +* caption. +* +* The CardView class is designed to mirror the API of the QListView or +* QIconView. The CardView is also completely independant of KAddressBook and +* can be used elsewhere. With the exception of a few simple config checks, +* the CardView is also 100% independant of KDE. +*/ +class CardView : public QScrollView +{ + friend class CardViewItem; + + Q_OBJECT + + public: + /** Constructor. + */ + CardView(QWidget *parent, const char *name); + virtual ~CardView(); + + /** Inserts the item into the card view. This method does not have + * to be called if you created the item with a proper parent. Once + * inserted, the CardView takes ownership of the item. + */ + void insertItem(CardViewItem *item); + + /** Takes the item from the view. The item will not be deleted and + * ownership of the item is returned to the caller. + */ + void takeItem(CardViewItem *item); + + /** Clears the view and deletes all card view items + */ + void clear(); + + /** @return The current item, the item that has the focus. + * Whenever the view has focus, this item has a focus rectangle painted + * at it's border. + * @sa setCurrentItem() + */ + CardViewItem *currentItem(); + + /** Sets the CardViewItem @p item to the current item in the view. + */ + void setCurrentItem( CardViewItem *item ); + + /** @return The item found at the given point, or 0 if there is no item + * at that point. + */ + CardViewItem *itemAt(const QPoint &viewPos); + + /** @return The bounding rect of the given item. + */ + QRect itemRect(const CardViewItem *item); + + /** Ensures that the given item is in the viewable area of the widget + */ + void ensureItemVisible(const CardViewItem *item); + + /** Repaints the given item. + */ + void repaintItem(const CardViewItem *item); + + enum SelectionMode { Single, Multi, Extended, NoSelection }; + + /** Sets the selection mode. + * + * @see QListView + */ + void setSelectionMode(SelectionMode mode); + + /** @return The current selection mode. + */ + SelectionMode selectionMode() const; + + /** Selects or deselects the given item. This method honors the current + * selection mode, so if other items are selected, they may be unselected. + */ + void setSelected(CardViewItem *item, bool selected); + + /** Selects or deselects all items. + */ + void selectAll(bool state); + + /** @return True if the given item is selected, false otherwise. + */ + bool isSelected(CardViewItem *item) const; + + /** @return The first selected item. In single select mode, this will be + * the only selected item, in other modes this will be the first selected + * item, but others may exist. 0 if no item is selected. + */ + CardViewItem *selectedItem() const; + + /** @return The first item in the view. This may be 0 if no items have + * been inserted. This method combined with CardViewItem::nextItem() + * can be used to iterator through the list of items. + */ + CardViewItem *firstItem() const; + + /** @return The item after the given item or 0 if the item is the last + * item. + */ + CardViewItem *itemAfter(CardViewItem *item); + + /** @return The number of items in the view. + */ + int childCount() const; + + /** Attempts to find the first item matching the params. + * + * @param text The text to match. + * @param label The label of the field to match against. + * @param compare The compare method to use in doing the search. + * + * @return The first matching item, or 0 if no items match. + */ +/*US + CardViewItem *findItem(const QString &text, const QString &label, + Qt::StringComparisonMode compare = Qt::BeginsWith); +*/ + + /** Returns the amounts of pixels required for one column. + * This depends on wheather drawSeparators is enabled: + * If so, it is itemWidth + 2*itemSpacing + separatorWidth + * If not, it is itemWidth + itemSpacing + * @see itemWidth(), setItemWidth(), itemSpacing() and setItemSpacing() + */ + uint columnWidth(); + + /** Sets if the border around a card should be draw. The border is a thing + * (1 or 2 pixel) line that bounds the card. When drawn, it shows when + * a card is highlighted and when it isn't. + */ + void setDrawCardBorder(bool enabled); + + /** @return True if borders are drawn, false otherwise. + */ + bool drawCardBorder() const; + + /** Sets if the column separator should be drawn. The column separator + * is a thin verticle line (1 or 2 pixels) that is used to separate the + * columns in the list view. The separator is just for esthetics and it + * does not serve a functional purpose. + */ + void setDrawColSeparators(bool enabled); + + /** @return True if column separators are drawn, false otherwise. + */ + bool drawColSeparators() const; + + /** Sets if the field labels should be drawn. The field labels are the + * unique strings used to identify the fields. Sometimes drawing these + * labels makes sense as a source of clarity for the user, othertimes they + * waste too much space and do not assist the user. + */ + void setDrawFieldLabels(bool enabled); + + /** @return True if the field labels are drawn, false otherwise. + */ + bool drawFieldLabels() const; + + /** Sets if fields with no value should be drawn (of cause the label only, + * but it allows for embedded editing sometimes...) + */ + void setShowEmptyFields(bool show); + + /** @return Wheather empty fields should be shown + */ + bool showEmptyFields() const; + + /** @return the advisory internal margin in items. Setting a value above 1 means + * a space between the item contents and the focus recttangle drawn around + * the current item. The default value is 0. + * The value should be used by CardViewItem and derived classes. + * Note that this should not be greater than half of the minimal item width, + * which is 80. It is currently not checked, so setting a value greater than 40 + * will probably mean a crash in the items painting routine. + * @private Note: I looked for a value in QStyle::PixelMetric to use, but I could + * not see a usefull one. One may turn up in a future version of Qt. + */ + uint itemMargin(); + + /** Sets the internal item margin. @see itemMargin(). + */ + void setItemMargin( uint margin ); + + /** @return the item spacing. + * The item spacing is the space (in pixels) between each item in a + * column, between the items and column separators if drawn, and between + * the items and the borders of the widget. The default value is set to + * 10. + * @private Note: There is no usefull QStyle::PixelMetric to use for this atm. + * An option would be using KDialog::spacingHint(). + */ + uint itemSpacing(); + + /** Sets the item spacing. + * @see itemSpacing() + */ + void setItemSpacing( uint spacing ); + + /** @return the width made available to the card items. */ + int itemWidth() const; + + /** Sets the width made available to card items. */ + void setItemWidth( int width ); + + /** Sets the header font */ + void setHeaderFont( const QFont &fnt ); + + /** @return the header font */ + QFont headerFont() const; + + /** @reimp */ + void setFont( const QFont &fnt ); + + /** Sets the column separator width */ + void setSeparatorWidth( int width ); + + /** @return the column separator width */ + int separatorWidth(); + + /** Sets the maximum number of lines to display pr field. + If set to 0 (the default) all lines will be displayed. + */ + void setMaxFieldLines( int howmany ); + + /** @return the maximum number of lines pr field */ + int maxFieldLines() const; + + signals: + /** Emitted whenever the selection changes. This means a user highlighted + * a new item or unhighlighted a currently selected item. + */ + void selectionChanged(); + + /** Same as above method, only it carries the item that was selected. This + * method will only be emitted in single select mode, since it defineds + * which item was selected. + */ + void selectionChanged(CardViewItem *); + + /** This method is emitted whenever an item is clicked. + */ + void clicked(CardViewItem *); + + /** Emitted whenever the user 'executes' an item. This is dependant on + * the KDE global config. This could be a single click or a doubleclick. + * Also emitted when the return key is pressed on an item. + */ + void executed(CardViewItem *); + + /** Emitted whenever the user double clicks on an item. + */ + void doubleClicked(CardViewItem *); + + /** Emitted when the current item changes + */ + void currentChanged( CardViewItem * ); + + /** Emitted when the return key is pressed in an item. + */ + void returnPressed( CardViewItem * ); + + protected: + /** Determines which cards intersect that region and tells them to paint + * themselves. + */ + void drawContents(QPainter *p, int clipx, int clipy, int clipw, int cliph); + + /** Sets the layout to dirty and repaints. + */ + void resizeEvent(QResizeEvent *e); + + /** Changes the direction the canvas scolls. + */ + void contentsWheelEvent(QWheelEvent *e); + + /** Sets the layout to dirty and calls for a repaint. + */ + void setLayoutDirty(bool dirty); + + /** Does the math based on the bounding rect of the cards to properly + * lay the cards out on the screen. This is only done if the layout is + * marked as dirty. + */ + void calcLayout(); + +// virtual void mousePressEvent(QMouseEvent *e); +// virtual void mouseReleaseEvent(QMouseEvent *e); +// virtual void mouseMoveEvent(QMouseEvent *e); + + virtual void contentsMousePressEvent(QMouseEvent *e); + virtual void contentsMouseMoveEvent(QMouseEvent *e); + virtual void contentsMouseReleaseEvent(QMouseEvent *e); + virtual void contentsMouseDoubleClickEvent(QMouseEvent *e); + + virtual void enterEvent( QEvent * ); + virtual void leaveEvent( QEvent * ); + + virtual void focusInEvent( QFocusEvent * ); + virtual void focusOutEvent( QFocusEvent * ); + + virtual void keyPressEvent( QKeyEvent * ); + + /** Overload this method to be told when a drag should be started. + * In most cases you will want to start a drag event with the currently + * selected item. + */ + virtual void startDrag(); + + private slots: + /** Called by a timer to display a label with truncated text. + * Pop up a label, if there is a field with obscured text or + * label at the cursor position. + */ + void tryShowFullText(); + + private: + /** draws and erases the rubber bands while columns are resized. + * @p pos is the horizontal position inside the viewport to use as + * the anchor. + * If pos is 0, only erase is done. + */ + void drawRubberBands( int pos ); + + CardViewPrivate *d; +}; + +#endif diff --git a/kaddressbook/views/colorlistbox.cpp b/kaddressbook/views/colorlistbox.cpp new file mode 100644 index 0000000..c243fa0 --- a/dev/null +++ b/kaddressbook/views/colorlistbox.cpp @@ -0,0 +1,230 @@ +/* + * kmail: KDE mail client + * This file: Copyright (C) 2000 Espen Sand, espen@kde.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <qpainter.h> + +#include <kcolordialog.h> + +#ifndef KAB_EMBEDDED +#include <kcolordrag.h> +#endif //KAB_EMBEDDED + +#include "colorlistbox.h" + +ColorListBox::ColorListBox( QWidget *parent, const char *name, WFlags f ) + :KListBox( parent, name, f ), mCurrentOnDragEnter(-1) +{ + connect( this, SIGNAL(selected(int)), this, SLOT(newColor(int)) ); + setAcceptDrops( true); +} + + +void ColorListBox::setEnabled( bool state ) +{ + if( state == isEnabled() ) + { + return; + } + + QListBox::setEnabled( state ); + for( uint i=0; i<count(); i++ ) + { + updateItem( i ); + } +} + + +void ColorListBox::setColor( uint index, const QColor &color ) +{ + if( index < count() ) + { + ColorListItem *colorItem = (ColorListItem*)item(index); + colorItem->setColor(color); + updateItem( colorItem ); + } +} + + +QColor ColorListBox::color( uint index ) const +{ + if( index < count() ) + { + ColorListItem *colorItem = (ColorListItem*)item(index); + return( colorItem->color() ); + } + else + { + return( black ); + } +} + + +void ColorListBox::newColor( int index ) +{ + if( isEnabled() == false ) + { + return; + } + + if( (uint)index < count() ) + { + QColor c = color( index ); +#ifndef KAB_EMBEDDED + if( KColorDialog::getColor( c, this ) != QDialog::Rejected ) + { + setColor( index, c ); + } +#else //KAB_EMBEDDED + KColorDialog* k = new KColorDialog( this ); + k->setColor( c ); + int res = k->exec(); + if ( res ) { + setColor( index, k->getColor() ); + } + delete k; +#endif //KAB_EMBEDDED + + } +} + + +void ColorListBox::dragEnterEvent( QDragEnterEvent *e ) +{ +#ifndef KAB_EMBEDDED + if( KColorDrag::canDecode(e) && isEnabled() ) + { + mCurrentOnDragEnter = currentItem(); + e->accept( true ); + } + else + { + mCurrentOnDragEnter = -1; + e->accept( false ); + } +#else //KAB_EMBEDDED +qDebug("ColorListBox::dragEnterEvent drag&drop currently not supported"); +#endif //KAB_EMBEDDED + +} + + +void ColorListBox::dragLeaveEvent( QDragLeaveEvent * ) +{ +#ifndef KAB_EMBEDDED + + if( mCurrentOnDragEnter != -1 ) + { + setCurrentItem( mCurrentOnDragEnter ); + mCurrentOnDragEnter = -1; + } +#else //KAB_EMBEDDED +qDebug("ColorListBox::dragLeaveEvent drag&drop currently not supported"); +#endif //KAB_EMBEDDED +} + + +void ColorListBox::dragMoveEvent( QDragMoveEvent *e ) +{ +#ifndef KAB_EMBEDDED + if( KColorDrag::canDecode(e) && isEnabled() ) + { + ColorListItem *item = (ColorListItem*)itemAt( e->pos() ); + if( item != 0 ) + { + setCurrentItem ( item ); + } + } +#else //KAB_EMBEDDED +qDebug("ColorListBox::dragMoveEvent drag&drop currently not supported"); +#endif //KAB_EMBEDDED + +} + + +void ColorListBox::dropEvent( QDropEvent *e ) +{ +#ifndef KAB_EMBEDDED + QColor color; + if( KColorDrag::decode( e, color ) ) + { + int index = currentItem(); + if( index != -1 ) + { + ColorListItem *colorItem = (ColorListItem*)item(index); + colorItem->setColor(color); + triggerUpdate( false ); // Redraw item + } + mCurrentOnDragEnter = -1; + } + +#else //KAB_EMBEDDED +qDebug("ColorListBox::dropEvent drag&drop currently not supported"); +#endif //KAB_EMBEDDED + +} + + + +ColorListItem::ColorListItem( const QString &text, const QColor &color ) + : QListBoxItem(), mColor( color ), mBoxWidth( 30 ) +{ + setText( text ); +} + + +const QColor &ColorListItem::color( void ) +{ + return( mColor ); +} + + +void ColorListItem::setColor( const QColor &color ) +{ + mColor = color; +} + + +void ColorListItem::paint( QPainter *p ) +{ + QFontMetrics fm = p->fontMetrics(); + int h = fm.height(); + + p->drawText( mBoxWidth+3*2, fm.ascent() + fm.leading()/2, text() ); + + p->setPen( Qt::black ); + p->drawRect( 3, 1, mBoxWidth, h-1 ); + p->fillRect( 4, 2, mBoxWidth-2, h-3, mColor ); +} + + +int ColorListItem::height(const QListBox *lb ) const +{ + return( lb->fontMetrics().lineSpacing()+1 ); +} + + +int ColorListItem::width(const QListBox *lb ) const +{ + return( mBoxWidth + lb->fontMetrics().width( text() ) + 6 ); +} + +#ifndef KAB_EMBEDDED +#include "colorlistbox.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/views/colorlistbox.h b/kaddressbook/views/colorlistbox.h new file mode 100644 index 0000000..4a0e705 --- a/dev/null +++ b/kaddressbook/views/colorlistbox.h @@ -0,0 +1,76 @@ +/* + * kmail: KDE mail client + * This file: Copyright (C) 2000 Espen Sand, espen@kde.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _COLOR_LISTBOX_H_ +#define _COLOR_LISTBOX_H_ + +#include <klistbox.h> + +class QDragEnterEvent; +class QDragLeaveEvent; +class QDragMoveEvent; +class QDropEvent; + +class ColorListBox : public KListBox +{ + Q_OBJECT + + public: + ColorListBox( QWidget *parent=0, const char * name=0, WFlags f=0 ); + void setColor( uint index, const QColor &color ); + QColor color( uint index ) const; + + public slots: + virtual void setEnabled( bool state ); + + protected: + void dragEnterEvent( QDragEnterEvent *e ); + void dragLeaveEvent( QDragLeaveEvent *e ); + void dragMoveEvent( QDragMoveEvent *e ); + void dropEvent( QDropEvent *e ); + + private slots: + void newColor( int index ); + + private: + int mCurrentOnDragEnter; + +}; + + +class ColorListItem : public QListBoxItem +{ + public: + ColorListItem( const QString &text, const QColor &color=Qt::black ); + const QColor &color( void ); + void setColor( const QColor &color ); + + protected: + virtual void paint( QPainter * ); + virtual int height( const QListBox * ) const; + virtual int width( const QListBox * ) const; + + private: + QColor mColor; + int mBoxWidth; +}; + +#endif + diff --git a/kaddressbook/views/configurecardviewdialog.cpp b/kaddressbook/views/configurecardviewdialog.cpp new file mode 100644 index 0000000..d518cf7 --- a/dev/null +++ b/kaddressbook/views/configurecardviewdialog.cpp @@ -0,0 +1,364 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qstring.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qvbox.h> +#include <qgroupbox.h> +#include <qspinbox.h> +#include <qtabwidget.h> +#include <qwhatsthis.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kconfig.h> +#include <kfontdialog.h> + +#ifndef KAB_EMBEDDED +#include <kpushbutton.h> +#else //KAB_EMBEDDED +#include <qpushbutton.h> +#endif //KAB_EMBEDDED + +#include "colorlistbox.h" + +#include "configurecardviewdialog.h" + +///////////////////////////////// +// ConfigureCardViewDialog + +ConfigureCardViewWidget::ConfigureCardViewWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name ) + : ViewConfigureWidget( ab, parent, name ) +{ +#ifndef KAB_EMBEDDED + QWidget *page = addPage( i18n( "Look & Feel" ), QString::null, + DesktopIcon( "looknfeel" ) ); +#else //KAB_EMBEDDED + QWidget *page = addPage( i18n( "Look & Feel" ), QString::null, + KGlobal::iconLoader()->loadIcon( "looknfeel", + KIcon::Panel ) ); +#endif //KAB_EMBEDDED + + mAdvancedPage = new CardViewLookNFeelPage( page ); +} + +ConfigureCardViewWidget::~ConfigureCardViewWidget() +{ +} + +void ConfigureCardViewWidget::restoreSettings( KConfig *config ) +{ + ViewConfigureWidget::restoreSettings( config ); + + mAdvancedPage->restoreSettings( config ); +} + +void ConfigureCardViewWidget::saveSettings( KConfig *config ) +{ + ViewConfigureWidget::saveSettings( config ); + + mAdvancedPage->saveSettings( config ); +} + +//////////////////////// +// CardViewLookNFeelPage +CardViewLookNFeelPage::CardViewLookNFeelPage( QWidget *parent, const char *name ) + : QVBox( parent, name ) +{ + initGUI(); +} + +CardViewLookNFeelPage::~CardViewLookNFeelPage() +{ +} + +void CardViewLookNFeelPage::restoreSettings( KConfig *config ) +{ + // colors + cbEnableCustomColors->setChecked( config->readBoolEntry( "EnableCustomColors", false ) ); + QColor c; +qDebug("CardViewLookNFeelPage::restoreSettings make base color configurable"); + +#ifndef KAB_EMBEDDED + c = KGlobalSettings::baseColor(); +#else //KAB_EMBEDDED + c = QColor(0,0,0); +#endif //KAB_EMBEDDED + + lbColors->insertItem( new ColorListItem( i18n("Background Color"), + config->readColorEntry( "BackgroundColor", &c ) ) ); + c = colorGroup().foreground(); + lbColors->insertItem( new ColorListItem( i18n("Text Color"), + config->readColorEntry( "TextColor", &c ) ) ); + c = colorGroup().button(); + lbColors->insertItem( new ColorListItem( i18n("Header, Border and Separator Color"), + config->readColorEntry( "HeaderColor", &c ) ) ); + c = colorGroup().buttonText(); + lbColors->insertItem( new ColorListItem( i18n("Header Text Color"), + config->readColorEntry( "HeaderTextColor", &c ) ) ); + c = colorGroup().highlight(); + lbColors->insertItem( new ColorListItem( i18n("Highlight Color"), + config->readColorEntry( "HighlightColor", &c ) ) ); + c = colorGroup().highlightedText(); + lbColors->insertItem( new ColorListItem( i18n("Highlighted Text Color"), + config->readColorEntry( "HighlightedTextColor", &c ) ) ); + + enableColors(); + + // fonts + QFont fnt = font(); + updateFontLabel( config->readFontEntry( "TextFont", &fnt ), (QLabel*)lTextFont ); + fnt.setBold( true ); + updateFontLabel( config->readFontEntry( "HeaderFont", &fnt ), (QLabel*)lHeaderFont ); + cbEnableCustomFonts->setChecked( config->readBoolEntry( "EnableCustomFonts", false ) ); + enableFonts(); + + // layout + sbMargin->setValue( config->readNumEntry( "ItemMargin", 0 ) ); + sbSpacing->setValue( config->readNumEntry( "ItemSpacing", 10 ) ); + sbSepWidth->setValue( config->readNumEntry( "SeparatorWidth", 2 ) ); + cbDrawSeps->setChecked( config->readBoolEntry( "DrawSeparators", true ) ); + cbDrawBorders->setChecked( config->readBoolEntry( "DrawBorder", true ) ); + + // behaviour + cbShowFieldLabels->setChecked( config->readBoolEntry( "DrawFieldLabels", false ) ); + cbShowEmptyFields->setChecked( config->readBoolEntry( "ShowEmptyFields", false ) ); +} + +void CardViewLookNFeelPage::saveSettings( KConfig *config ) +{ + // colors + config->writeEntry( "EnableCustomColors", cbEnableCustomColors->isChecked() ); + if ( cbEnableCustomColors->isChecked() ) // ?? - Hmmm. + { + config->writeEntry( "BackgroundColor", lbColors->color( 0 ) ); + config->writeEntry( "TextColor", lbColors->color( 1 ) ); + config->writeEntry( "HeaderColor", lbColors->color( 2 ) ); + config->writeEntry( "HeaderTextColor", lbColors->color( 3 ) ); + config->writeEntry( "HighlightColor", lbColors->color( 4 ) ); + config->writeEntry( "HighlightedTextColor", lbColors->color( 5 ) ); + } + // fonts + config->writeEntry( "EnableCustomFonts", cbEnableCustomFonts->isChecked() ); + if ( cbEnableCustomFonts->isChecked() ) + { + config->writeEntry( "TextFont", lTextFont->font() ); + config->writeEntry( "HeaderFont", lHeaderFont->font() ); + } + // layout + config->writeEntry( "ItemMargin", sbMargin->value() ); + config->writeEntry( "ItemSpacing", sbSpacing->value() ); + config->writeEntry( "SeparatorWidth", sbSepWidth->value() ); + config->writeEntry("DrawBorder", cbDrawBorders->isChecked()); + config->writeEntry("DrawSeparators", cbDrawSeps->isChecked()); + + // behaviour + config->writeEntry("DrawFieldLabels", cbShowFieldLabels->isChecked()); + config->writeEntry("ShowEmptyFields", cbShowEmptyFields->isChecked()); +} + +void CardViewLookNFeelPage::setTextFont() +{ + QFont f( lTextFont->font() ); +#ifndef KAB_EMBEDDED + if ( KFontDialog::getFont( f, false, this ) == QDialog::Accepted ) + updateFontLabel( f, lTextFont ); +#else //KAB_EMBEDDED + bool ok; + QFont fout = KFontDialog::getFont( f, ok); + if ( ok ) + updateFontLabel( fout, lTextFont ); +#endif //KAB_EMBEDDED +} + +void CardViewLookNFeelPage::setHeaderFont() +{ + QFont f( lHeaderFont->font() ); +#ifndef KAB_EMBEDDED + if ( KFontDialog::getFont( f,false, this ) == QDialog::Accepted ) + updateFontLabel( f, lHeaderFont ); +#else //KAB_EMBEDDED + bool ok; + QFont fout = KFontDialog::getFont( f, ok); + if ( ok ) + updateFontLabel( fout, lHeaderFont ); +#endif //KAB_EMBEDDED +} + +void CardViewLookNFeelPage::enableFonts() +{ + vbFonts->setEnabled( cbEnableCustomFonts->isChecked() ); +} + +void CardViewLookNFeelPage::enableColors() +{ + lbColors->setEnabled( cbEnableCustomColors->isChecked() ); +} + +void CardViewLookNFeelPage::initGUI() +{ + int spacing = KDialog::spacingHint(); + int margin = KDialog::marginHint(); + + QTabWidget *tabs = new QTabWidget( this ); + + // Layout + QVBox *loTab = new QVBox( this, "layouttab" ); + + loTab->setSpacing( spacing ); + loTab->setMargin( margin ); + + QGroupBox *gbGeneral = new QGroupBox( 1, Qt::Horizontal, i18n("General"), loTab ); + + cbDrawSeps = new QCheckBox( i18n("Draw &separators"), gbGeneral ); + + QHBox *hbSW = new QHBox( gbGeneral ); + QLabel *lSW = new QLabel( i18n("Separator &width:"), hbSW ); + sbSepWidth = new QSpinBox( 1, 50, 1, hbSW ); + lSW->setBuddy( sbSepWidth); + + QHBox *hbPadding = new QHBox( gbGeneral ); + QLabel *lSpacing = new QLabel( i18n("&Padding:"), hbPadding ); + sbSpacing = new QSpinBox( 0, 100, 1, hbPadding ); + lSpacing->setBuddy( sbSpacing ); + + QGroupBox *gbCards = new QGroupBox( 1, Qt::Horizontal, i18n("Cards"), loTab ); + + QHBox *hbMargin = new QHBox( gbCards ); + QLabel *lMargin = new QLabel( i18n("&Margin:"), hbMargin ); + sbMargin = new QSpinBox( 0, 100, 1, hbMargin ); + lMargin->setBuddy( sbMargin ); + + cbDrawBorders = new QCheckBox( i18n("Draw &borders"), gbCards ); + + loTab->setStretchFactor( new QWidget( loTab ), 1 ); + + QWhatsThis::add( sbMargin, i18n( + "The item margin is the distance (in pixels) between the item edge and the item data. Most noticeably, " + "incrementing the item margin will add space between the focus rectangle and the item data." + ) ); + QWhatsThis::add( lMargin, QWhatsThis::textFor( sbMargin ) ); + QWhatsThis::add( sbSpacing, i18n( + "The Item Spacing decides the distance (in pixels) between the items and anything else: the view " + "borders, other items or column separators." + ) ); + QWhatsThis::add( lSpacing, QWhatsThis::textFor( sbSpacing ) ); + QWhatsThis::add( sbSepWidth, i18n("Sets the width of column separators") ); + QWhatsThis::add( lSW, QWhatsThis::textFor( sbSepWidth ) ); + + tabs->addTab( loTab, i18n("&Layout") ); + + // Colors + QVBox *colorTab = new QVBox( this, "colortab" ); + colorTab->setSpacing( spacing ); + colorTab->setMargin( spacing ); + cbEnableCustomColors = new QCheckBox( i18n("&Enable custom Colors"), colorTab ); + connect( cbEnableCustomColors, SIGNAL(clicked()), this, SLOT(enableColors()) ); + lbColors = new ColorListBox( colorTab ); + tabs->addTab( colorTab, i18n("&Colors") ); + + QWhatsThis::add( cbEnableCustomColors, i18n( + "If custom colors are enabled, you may choose the colors for the view below. " + "Otherwise colors from your current KDE color scheme are used." + ) ); + QWhatsThis::add( lbColors, i18n( + "Double click or press RETURN on a item to select a color for the related strings in the view." + ) ); + + // Fonts + QVBox *fntTab = new QVBox( this, "fonttab" ); + + fntTab->setSpacing( spacing ); + fntTab->setMargin( spacing ); + + cbEnableCustomFonts = new QCheckBox( i18n("&Enable custom fonts"), fntTab ); + connect( cbEnableCustomFonts, SIGNAL(clicked()), this, SLOT(enableFonts()) ); + + vbFonts = new QWidget( fntTab ); + QGridLayout *gFnts = new QGridLayout( vbFonts, 2, 3 ); + gFnts->setSpacing( spacing ); + gFnts->setAutoAdd( true ); + gFnts->setColStretch( 1, 1 ); + QLabel *lTFnt = new QLabel( i18n("&Text font:"), vbFonts ); + lTextFont = new QLabel( vbFonts ); + lTextFont->setFrameStyle( QFrame::Panel|QFrame::Sunken ); +#ifndef KAB_EMBEDDED + btnFont = new KPushButton( i18n("Choose..."), vbFonts ); +#else //KAB_EMBEDDED + btnFont = new QPushButton( i18n("Choose..."), vbFonts ); +#endif //KAB_EMBEDDED + + lTFnt->setBuddy( btnFont ); + + connect( btnFont, SIGNAL(clicked()), this, SLOT(setTextFont()) ); + + QLabel *lHFnt = new QLabel( i18n("&Header font:"), vbFonts ); + lHeaderFont = new QLabel( vbFonts ); + lHeaderFont->setFrameStyle( QFrame::Panel|QFrame::Sunken ); +#ifndef KAB_EMBEDDED + btnHeaderFont = new KPushButton( i18n("Choose..."), vbFonts ); +#else //KAB_EMBEDDED + btnHeaderFont = new QPushButton( i18n("Choose..."), vbFonts ); +#endif //KAB_EMBEDDED + lHFnt->setBuddy( btnHeaderFont ); + connect( btnHeaderFont, SIGNAL(clicked()), this, SLOT(setHeaderFont()) ); + + fntTab->setStretchFactor( new QWidget( fntTab ), 1 ); + + QWhatsThis::add( cbEnableCustomFonts, i18n( + "If custom fonts are enabled, you may choose which fonts to use for this view below. " + "Otherwise the default KDE font will be used, in bold style for the header and " + "normal style for the data." + ) ); + + tabs->addTab( fntTab, i18n("&Fonts") ); + + // Behaviour + QVBox *behaviourTab = new QVBox( this ); + behaviourTab->setMargin( margin ); + behaviourTab->setSpacing( spacing ); + + cbShowEmptyFields = new QCheckBox( i18n("Show &empty fields"), behaviourTab ); + cbShowFieldLabels = new QCheckBox( i18n("Show field &labels"), behaviourTab ); + + behaviourTab->setStretchFactor( new QWidget( behaviourTab ), 1 ); + + tabs->addTab( behaviourTab, i18n("Be&havior") ); + +} + +void CardViewLookNFeelPage::updateFontLabel( QFont fnt, QLabel *l ) +{ + l->setFont( fnt ); + l->setText( QString( fnt.family() + " %1" ).arg( fnt.pointSize() ) ); +} + +#ifndef KAB_EMBEDDED +#include "configurecardviewdialog.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/views/configurecardviewdialog.h b/kaddressbook/views/configurecardviewdialog.h new file mode 100644 index 0000000..7a62226 --- a/dev/null +++ b/kaddressbook/views/configurecardviewdialog.h @@ -0,0 +1,117 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef CONFIGURECARDVIEWDIALOG_H +#define CONFIGURECARDVIEWDIALOG_H + +#include "viewconfigurewidget.h" + +#include <qvbox.h> +#include <qwidget.h> +#include <qfont.h> + +class QString; +class QWidget; +class QCheckBox; +class QLabel; +class KConfig; + +namespace KABC { class AddressBook; } + +class CardViewLookAndFeelPage; + +/** + Configure dialog for the card view. This dialog inherits from the + standard view dialog in order to add a custom page for the card + view. + */ +class ConfigureCardViewWidget : public ViewConfigureWidget +{ + public: + ConfigureCardViewWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ); + virtual ~ConfigureCardViewWidget(); + + virtual void restoreSettings( KConfig* ); + virtual void saveSettings( KConfig* ); + + private: + class CardViewLookNFeelPage *mAdvancedPage; +}; + +/** + Card View Advanced LookNFeel settings widget: + this is a tabbed widget with 3 tabs: + Fonts + * text font + * header font + + Colors + * background color + * text color + * highlight color + * title/sep text color + * title/sep bg color + + Layout + * item margin + * item spacing +*/ + +class CardViewLookNFeelPage : public QVBox { + + Q_OBJECT + + public: + CardViewLookNFeelPage( QWidget *parent=0, const char *name=0 ); + ~CardViewLookNFeelPage(); + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + + private slots: + void setTextFont(); + void setHeaderFont(); + void enableFonts(); + void enableColors(); + + private: + void initGUI(); + void updateFontLabel( QFont, QLabel * ); + + QCheckBox *cbEnableCustomFonts, + *cbEnableCustomColors, + *cbDrawSeps, *cbDrawBorders, + *cbShowFieldLabels, *cbShowEmptyFields; + class ColorListBox *lbColors; + QLabel *lTextFont, *lHeaderFont; +#ifndef KAB_EMBEDDED + class KPushButton *btnFont, *btnHeaderFont; +#else //KAB_EMBEDDED + class QPushButton *btnFont, *btnHeaderFont; +#endif //KAB_EMBEDDED + class QSpinBox *sbMargin, *sbSpacing, *sbSepWidth; + + class QWidget *vbFonts; +}; + +#endif diff --git a/kaddressbook/views/configuretableviewdialog.cpp b/kaddressbook/views/configuretableviewdialog.cpp new file mode 100644 index 0000000..e1cc63e --- a/dev/null +++ b/kaddressbook/views/configuretableviewdialog.cpp @@ -0,0 +1,155 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qstring.h> +#include <qwidget.h> +#include <qlayout.h> +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qvbox.h> +#include <qbuttongroup.h> + +#include <kglobal.h> +#include <klocale.h> +#include <klineedit.h> +#include <kurlrequester.h> +#include <kiconloader.h> + +#ifndef KAB_EMBEDDED +#include <kimageio.h> +#else //KAB_EMBEDDED +#endif //KAB_EMBEDDED + +#include <kconfig.h> + +#include "configuretableviewdialog.h" + +ConfigureTableViewWidget::ConfigureTableViewWidget( KABC::AddressBook *ab, + QWidget *parent, + const char *name ) + : ViewConfigureWidget( ab, parent, name ) +{ + QWidget *page = addPage( i18n( "Look & Feel" ), QString::null, + KGlobal::iconLoader()->loadIcon( "looknfeel", + KIcon::Panel ) ); + + mPage = new LookAndFeelPage( page ); +} + +ConfigureTableViewWidget::~ConfigureTableViewWidget() +{ +} + +void ConfigureTableViewWidget::restoreSettings( KConfig *config ) +{ + ViewConfigureWidget::restoreSettings( config ); + + mPage->restoreSettings( config ); +} + +void ConfigureTableViewWidget::saveSettings( KConfig *config ) +{ + ViewConfigureWidget::saveSettings( config ); + + mPage->saveSettings( config ); +} + + + +LookAndFeelPage::LookAndFeelPage(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + initGUI(); + + // Set initial state + enableBackgroundToggled(mBackgroundBox->isChecked()); +} + +void LookAndFeelPage::restoreSettings( KConfig *config ) +{ + mAlternateButton->setChecked(config->readBoolEntry("ABackground", true)); + mLineButton->setChecked(config->readBoolEntry("SingleLine", false)); + mToolTipBox->setChecked(config->readBoolEntry("ToolTips", true)); + + if (!mAlternateButton->isChecked() & !mLineButton->isChecked()) + mNoneButton->setChecked(true); + + mBackgroundBox->setChecked(config->readBoolEntry("Background", false)); + mBackgroundName->lineEdit()->setText(config->readEntry("BackgroundName")); +} + +void LookAndFeelPage::saveSettings( KConfig *config ) +{ + config->writeEntry("ABackground", mAlternateButton->isChecked()); + config->writeEntry("SingleLine", mLineButton->isChecked()); + config->writeEntry("ToolTips", mToolTipBox->isChecked()); + config->writeEntry("Background", mBackgroundBox->isChecked()); + config->writeEntry("BackgroundName", mBackgroundName->lineEdit()->text()); +} + +void LookAndFeelPage::initGUI() +{ + QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialogBase::spacingHint()); + + QButtonGroup *group = new QButtonGroup(1, Qt::Horizontal, + i18n("Row Separator"), this); + layout->addWidget(group); + + mAlternateButton = new QRadioButton(i18n("Alternating backgrounds"), + group, "mAlternateButton"); + mLineButton = new QRadioButton(i18n("Single line"), group, "mLineButton"); + mNoneButton = new QRadioButton(i18n("None"), group, "mNoneButton"); + + // Background Checkbox/Selector + QHBoxLayout *backgroundLayout = new QHBoxLayout(); + layout->addLayout(backgroundLayout); + + mBackgroundBox = new QCheckBox(i18n("Enable background image:"), this, + "mBackgroundBox"); + connect(mBackgroundBox, SIGNAL(toggled(bool)), + SLOT(enableBackgroundToggled(bool))); + backgroundLayout->addWidget(mBackgroundBox); + + mBackgroundName = new KURLRequester(this, "mBackgroundName"); +#ifndef KAB_EMBEDDED + mBackgroundName->setMode(KFile::File | KFile::ExistingOnly | + KFile::LocalOnly); + mBackgroundName->setFilter(KImageIO::pattern(KImageIO::Reading)); +#endif //KAB_EMBEDDED + + backgroundLayout->addWidget(mBackgroundName); + + // ToolTip Checkbox + mToolTipBox = new QCheckBox(i18n("Enable contact tooltips"), this, + "mToolTipBox"); + layout->addWidget(mToolTipBox); +} + +void LookAndFeelPage::enableBackgroundToggled(bool enabled) +{ + mBackgroundName->setEnabled(enabled); +} + +#ifndef KAB_EMBEDDED +#include "configuretableviewdialog.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/views/configuretableviewdialog.h b/kaddressbook/views/configuretableviewdialog.h new file mode 100644 index 0000000..8392710 --- a/dev/null +++ b/kaddressbook/views/configuretableviewdialog.h @@ -0,0 +1,88 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef CONFIGURETABLEVIEWDIALOG_H +#define CONFIGURETABLEVIEWDIALOG_H + +#include "viewconfigurewidget.h" + +class QString; +class QWidget; +class QRadioButton; +class QCheckBox; +class KURLRequester; +class KConfig; + +namespace KABC { class AddressBook; } + +class LookAndFeelPage; + +/** + Configure dialog for the table view. This dialog inherits from the + standard view dialog in order to add a custom page for the table + view. + */ +class ConfigureTableViewWidget : public ViewConfigureWidget +{ + public: + ConfigureTableViewWidget( KABC::AddressBook *ab, QWidget *parent, const char *name ); + virtual ~ConfigureTableViewWidget(); + + virtual void restoreSettings( KConfig* ); + virtual void saveSettings( KConfig* ); + + private: + void initGUI(); + + LookAndFeelPage *mPage; +}; + +/** + Internal class. It is only defined here for moc +*/ +class LookAndFeelPage : public QWidget +{ + Q_OBJECT + + public: + LookAndFeelPage( QWidget *parent, const char *name = 0 ); + ~LookAndFeelPage() {} + + void restoreSettings( KConfig* ); + void saveSettings( KConfig* ); + + protected slots: + void enableBackgroundToggled( bool ); + + private: + void initGUI(); + + QRadioButton *mAlternateButton; + QRadioButton *mLineButton; + QRadioButton *mNoneButton; + QCheckBox *mToolTipBox; + KURLRequester *mBackgroundName; + QCheckBox *mBackgroundBox; +}; + +#endif diff --git a/kaddressbook/views/contactlistview.cpp b/kaddressbook/views/contactlistview.cpp new file mode 100644 index 0000000..98b2fb2 --- a/dev/null +++ b/kaddressbook/views/contactlistview.cpp @@ -0,0 +1,340 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qheader.h> +#include <qiconset.h> +#include <qimage.h> +#include <qdragobject.h> +#include <qcombobox.h> +#include <qpainter.h> +#include <qbrush.h> +#include <qevent.h> + +#include <klocale.h> +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kapplication.h> +#include <kurl.h> + +#include "kaddressbooktableview.h" + +#include "contactlistview.h" + +///////////////////////////////// +// DynamicTip Methods + +DynamicTip::DynamicTip( ContactListView *parent) + : QToolTip( parent ) +{ +} + +void DynamicTip::maybeTip( const QPoint &pos ) +{ + static bool ishidden = true; + if (!parentWidget()->inherits( "ContactListView" )) + return; + + ContactListView *plv = (ContactListView*)parentWidget(); + if (!plv->tooltips()) + return; + + QPoint posVp = plv->viewport()->pos(); + + QListViewItem *lvi = plv->itemAt( pos - posVp ); + if (!lvi) + return; + +#ifndef KAB_EMBEDDED + ContactListViewItem *plvi = dynamic_cast< ContactListViewItem* >(lvi); +#else //KAB_EMBEDDED + ContactListViewItem *plvi = (ContactListViewItem*)(lvi); +#endif //KAB_EMBEDDED + + if (!plvi) + return; + + if (ishidden) { + QString s; + QRect r = plv->itemRect( lvi ); + r.moveBy( posVp.x(), posVp.y() ); + + //kdDebug() << "Tip rec: " << r.x() << "," << r.y() << "," << r.width() + // << "," << r.height() << endl; + + KABC::Addressee a = plvi->addressee(); + if (a.isEmpty()) + return; + + s += i18n("label: value", "%1: %2").arg(a.formattedNameLabel()) + .arg(a.formattedName()); + + s += '\n'; + s += i18n("label: value", "%1: %2").arg(a.organizationLabel()) + .arg(a.organization()); + + QString notes = a.note().stripWhiteSpace(); + if ( !notes.isEmpty() ) { + notes += '\n'; + s += '\n' + i18n("label: value", "%1: \n").arg(a.noteLabel()); + QFontMetrics fm( font() ); + + // Begin word wrap code based on QMultiLineEdit code + int i = 0; + bool doBreak = false; + int linew = 0; + int lastSpace = -1; + int a = 0; + int lastw = 0; + + while ( i < int(notes.length()) ) { + doBreak = FALSE; + if ( notes[i] != '\n' ) + linew += fm.width( notes[i] ); + + if ( lastSpace >= a && notes[i] != '\n' ) + if (linew >= parentWidget()->width()) { + doBreak = TRUE; + if ( lastSpace > a ) { + i = lastSpace; + linew = lastw; + } + else + i = QMAX( a, i-1 ); + } + + if ( notes[i] == '\n' || doBreak ) { + s += notes.mid( a, i - a + (doBreak?1:0) ) +"\n"; + + a = i + 1; + lastSpace = a; + linew = 0; + } + + if ( notes[i].isSpace() ) { + lastSpace = i; + lastw = linew; + } + + if ( lastSpace <= a ) { + lastw = linew; + } + + ++i; + } + } + + tip( r, s ); + } + else + hide(); + ishidden = !ishidden; + +} + +/////////////////////////// +// ContactListViewItem Methods + +ContactListViewItem::ContactListViewItem(const KABC::Addressee &a, + ContactListView *parent, + KABC::AddressBook *doc, + const KABC::Field::List &fields ) + : KListViewItem(parent), mAddressee(a), mFields( fields ), + parentListView( parent ), mDocument(doc) +{ + refresh(); +} + +QString ContactListViewItem::key(int column, bool ascending) const +{ + return QListViewItem::key(column, ascending).lower(); +} + +void ContactListViewItem::paintCell(QPainter * p, + const QColorGroup & cg, + int column, + int width, + int align) +{ + KListViewItem::paintCell(p, cg, column, width, align); + + if ( !p ) + return; + + if (parentListView->singleLine()) { + p->setPen( parentListView->alternateColor() ); + p->drawLine( 0, height() - 1, width, height() - 1 ); + } +} + + +ContactListView *ContactListViewItem::parent() +{ + return parentListView; +} + + +void ContactListViewItem::refresh() +{ + // Update our addressee, since it may have changed else were + mAddressee = mDocument->findByUid(mAddressee.uid()); + if (mAddressee.isEmpty()) + return; + + int i = 0; + KABC::Field::List::ConstIterator it; + for( it = mFields.begin(); it != mFields.end(); ++it ) { + setText( i++, (*it)->value( mAddressee ) ); + } +} + +/////////////////////////////// +// ContactListView + +ContactListView::ContactListView(KAddressBookTableView *view, + KABC::AddressBook* /* doc */, + QWidget *parent, + const char *name ) + : KListView( parent, name ), + pabWidget( view ), + oldColumn( 0 ) +{ + mABackground = true; + mSingleLine = false; + mToolTips = true; +#ifndef KAB_EMBEDDED + mAlternateColor = KGlobalSettings::alternateBackgroundColor(); +#else //KAB_EMBEDDED + mAlternateColor = QColor(240, 240, 240); +#endif //KAB_EMBEDDED + + setAlternateBackgroundEnabled(mABackground); + setAcceptDrops( true ); + viewport()->setAcceptDrops( true ); + setAllColumnsShowFocus( true ); + setShowSortIndicator(true); + + setSelectionModeExt( KListView::Extended ); + setDropVisualizer(false); + // setFrameStyle(QFrame::NoFrame); + setLineWidth ( 0 ); + setMidLineWidth ( 0 ); + setMargin ( 0 ); +#ifndef KAB_EMBEDDED + connect(this, SIGNAL(dropped(QDropEvent*)), + this, SLOT(itemDropped(QDropEvent*))); +#endif //KAB_EMBEDDED + + + new DynamicTip( this ); +} + +void ContactListView::paintEmptyArea( QPainter * p, const QRect & rect ) +{ + QBrush b = palette().brush(QPalette::Active, QColorGroup::Base); + + // Get the brush, which will have the background pixmap if there is one. + if (b.pixmap()) + { + p->drawTiledPixmap( rect.left(), rect.top(), rect.width(), rect.height(), + *(b.pixmap()), + rect.left() + contentsX(), + rect.top() + contentsY() ); + } + + else + { + // Do a normal paint + KListView::paintEmptyArea(p, rect); + } +} + +void ContactListView::contentsMousePressEvent(QMouseEvent* e) +{ + presspos = e->pos(); + KListView::contentsMousePressEvent(e); +} + + +// To initiate a drag operation +void ContactListView::contentsMouseMoveEvent( QMouseEvent *e ) +{ + if ((e->state() & LeftButton) && (e->pos() - presspos).manhattanLength() > 4 ) { + emit startAddresseeDrag(); + } + else + KListView::contentsMouseMoveEvent( e ); +} + +bool ContactListView::acceptDrag(QDropEvent *e) const +{ +#ifndef KAB_EMBEDDED + return QTextDrag::canDecode(e); +#else //KAB_EMBEDDED +qDebug("ContactListView::acceptDrag has to be fixed"); + return false; +#endif //KAB_EMBEDDED +} + +void ContactListView::itemDropped(QDropEvent *e) +{ + contentsDropEvent(e); +} + +void ContactListView::contentsDropEvent( QDropEvent *e ) +{ + emit addresseeDropped(e); +} + +void ContactListView::setAlternateBackgroundEnabled(bool enabled) +{ + mABackground = enabled; + + if (mABackground) + { + setAlternateBackground(mAlternateColor); + } + else + { + setAlternateBackground(QColor()); + } +} + +void ContactListView::setBackgroundPixmap(const QString &filename) +{ + if (filename.isEmpty()) + { + unsetPalette(); + } + else + { + qDebug("ContactListView::setBackgroundPixmap has to be verified"); +//US setPaletteBackgroundPixmap(QPixmap(filename)); + KListView::setBackgroundPixmap((const QPixmap&)QPixmap(filename)); + } + +} +#ifndef KAB_EMBEDDED +#include "contactlistview.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/views/contactlistview.h b/kaddressbook/views/contactlistview.h new file mode 100644 index 0000000..ae9c994 --- a/dev/null +++ b/kaddressbook/views/contactlistview.h @@ -0,0 +1,128 @@ +#ifndef CONTACTLISTVIEW_H +#define CONTACTLISTVIEW_H + +#include <qcolor.h> +#include <qpixmap.h> +#include <qtooltip.h> +#include <qstring.h> + +#include <klistview.h> + +#include <kabc/field.h> +#include <kabc/addressee.h> +#include <kabc/addressbook.h> + + +class QDropEvent; +class KAddressBookTableView; +class ContactListView; + +/** The whole tooltip design needs a lot of work. Currently it is +* hacked together to function. +*/ +class DynamicTip : public QToolTip +{ + public: + DynamicTip( ContactListView * parent ); + + protected: + void maybeTip( const QPoint & ); + + private: +}; + +class ContactListViewItem : public KListViewItem +{ + +public: + ContactListViewItem(const KABC::Addressee &a, ContactListView* parent, + KABC::AddressBook *doc, const KABC::Field::List &fields ); + const KABC::Addressee &addressee() const { return mAddressee; } + virtual void refresh(); + virtual ContactListView* parent(); + virtual QString key ( int, bool ) const; + + /** Adds the border around the cell if the user wants it. + * This is how the single line config option is implemented. + */ + virtual void paintCell(QPainter * p, const QColorGroup & cg, + int column, int width, int align ); + +private: + KABC::Addressee mAddressee; + KABC::Field::List mFields; + ContactListView *parentListView; + KABC::AddressBook *mDocument; +}; + + +///////////////////////////////////////////// +// ContactListView + +class ContactListView : public KListView +{ + Q_OBJECT + +public: + ContactListView(KAddressBookTableView *view, + KABC::AddressBook *doc, + QWidget *parent, + const char *name = 0L ); + virtual ~ContactListView() {} + //void resort(); + + /** Returns true if tooltips should be displayed, false otherwise + */ + bool tooltips() const { return mToolTips; } + void setToolTipsEnabled(bool enabled) { mToolTips = enabled; } + + bool alternateBackground() const { return mABackground; } + void setAlternateBackgroundEnabled(bool enabled); + + bool singleLine() const { return mSingleLine; } + void setSingleLineEnabled(bool enabled) { mSingleLine = enabled; } + + const QColor &alternateColor() const { return mAlternateColor; } + + /** Sets the background pixmap to <i>filename</i>. If the + * QString is empty (QString::isEmpty()), then the background + * pixmap will be disabled. + */ + void setBackgroundPixmap(const QString &filename); + +protected: + /** Paints the background pixmap in the empty area. This method is needed + * since Qt::FixedPixmap will not scroll with the list view. + */ + virtual void paintEmptyArea( QPainter * p, const QRect & rect ); + virtual void contentsMousePressEvent(QMouseEvent*); + void contentsMouseMoveEvent( QMouseEvent *e ); + void contentsDropEvent( QDropEvent *e ); + virtual bool acceptDrag(QDropEvent *e) const; + +protected slots: + void itemDropped(QDropEvent *e); + +public slots: + +signals: + void startAddresseeDrag(); + void addresseeDropped(QDropEvent *); + +private: + KAddressBookTableView *pabWidget; + int oldColumn; + int column; + bool ascending; + + bool mABackground; + bool mSingleLine; + bool mToolTips; + + QColor mAlternateColor; + + QPoint presspos; +}; + + +#endif diff --git a/kaddressbook/views/kaddressbookcardview.cpp b/kaddressbook/views/kaddressbookcardview.cpp new file mode 100644 index 0000000..239429f --- a/dev/null +++ b/kaddressbook/views/kaddressbookcardview.cpp @@ -0,0 +1,394 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qdragobject.h> +#include <qevent.h> +#include <qiconview.h> +#include <qlayout.h> +#include <qstringlist.h> + +#include <kabc/addressbook.h> +#include <kabc/addressee.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> + +#include "kabprefs.h" +#include "viewmanager.h" + +#include "kaddressbookcardview.h" + +#ifndef KAB_EMBEDDED +extern "C" { + void *init_libkaddrbk_cardview() + { + return ( new CardViewFactory ); + } +} +#endif //KAB_EMBEDDED + +//////////////////////////////// +// AddresseeCardViewItem (internal class) +class AddresseeCardViewItem : public CardViewItem +{ + public: + AddresseeCardViewItem(const KABC::Field::List &fields, + bool showEmptyFields, + KABC::AddressBook *doc, const KABC::Addressee &a, + CardView *parent) + : CardViewItem(parent, a.formattedName()), + mFields( fields ), mShowEmptyFields(showEmptyFields), + mDocument(doc), mAddressee(a) + { + if ( mFields.isEmpty() ) { + mFields = KABC::Field::defaultFields(); + } + refresh(); + } + + const KABC::Addressee &addressee() const { return mAddressee; } + + void refresh() + { + // Update our addressee, since it may have changed elsewhere + mAddressee = mDocument->findByUid(mAddressee.uid()); + + if (!mAddressee.isEmpty()) + { + clearFields(); + + // Try all the selected fields until we find one with text. + // This will limit the number of unlabeled icons in the view + KABC::Field::List::Iterator iter; + for (iter = mFields.begin(); iter != mFields.end(); ++iter) + { + // insert empty fields or not? not doing so saves a bit of memory and CPU + // (during geometry calculations), but prevents having equally + // wide label columns in all cards, unless CardViewItem/CardView search + // globally for the widest label. (anders) + //if (mShowEmptyFields || !(*iter)->value( mAddressee ).isEmpty()) + insertField((*iter)->label(), (*iter)->value( mAddressee )); + } + + // We might want to make this the first field. hmm... -mpilone + setCaption( mAddressee.realName() ); + } + } + + private: + KABC::Field::List mFields; + bool mShowEmptyFields; + KABC::AddressBook *mDocument; + KABC::Addressee mAddressee; +}; + +/////////////////////////////// +// AddresseeCardView + +AddresseeCardView::AddresseeCardView(QWidget *parent, const char *name) + : CardView(parent, name) +{ + setAcceptDrops(true); +} + +AddresseeCardView::~AddresseeCardView() +{ +} + +void AddresseeCardView::dragEnterEvent(QDragEnterEvent *e) +{ +#ifndef KAB_EMBEDDED + if (QTextDrag::canDecode(e)) + e->accept(); +#else //KAB_EMBEDDED +qDebug("AddresseeCardView::dragEnterEvent drag&drop is not implemented"); +#endif //KAB_EMBEDDED +} + +void AddresseeCardView::dropEvent(QDropEvent *e) +{ + emit addresseeDropped(e); +} + +void AddresseeCardView::startDrag() +{ + emit startAddresseeDrag(); +} + + +/////////////////////////////// +// KAddressBookCardView + +KAddressBookCardView::KAddressBookCardView( KABC::AddressBook *ab, + QWidget *parent, const char *name ) + : KAddressBookView( ab, parent, name ) +{ + mShowEmptyFields = false; + + // Init the GUI + QVBoxLayout *layout = new QVBoxLayout(viewWidget()); + + mCardView = new AddresseeCardView(viewWidget(), "mCardView"); + mCardView->setSelectionMode(CardView::Extended); + layout->addWidget(mCardView); + + // Connect up the signals + connect(mCardView, SIGNAL(executed(CardViewItem *)), + this, SLOT(addresseeExecuted(CardViewItem *))); + connect(mCardView, SIGNAL(selectionChanged()), + this, SLOT(addresseeSelected())); + connect(mCardView, SIGNAL(addresseeDropped(QDropEvent*)), + this, SIGNAL(dropped(QDropEvent*))); + connect(mCardView, SIGNAL(startAddresseeDrag()), + this, SIGNAL(startDrag())); +} + +KAddressBookCardView::~KAddressBookCardView() +{ +} + +void KAddressBookCardView::readConfig(KConfig *config) +{ + KAddressBookView::readConfig(config); + + // costum colors? + if ( config->readBoolEntry( "EnableCustomColors", false ) ) + { + QPalette p( mCardView->palette() ); + QColor c = p.color(QPalette::Normal, QColorGroup::Base ); + p.setColor( QPalette::Normal, QColorGroup::Base, config->readColorEntry( "BackgroundColor", &c ) ); + c = p.color(QPalette::Normal, QColorGroup::Text ); + p.setColor( QPalette::Normal, QColorGroup::Text, config->readColorEntry( "TextColor", &c ) ); + c = p.color(QPalette::Normal, QColorGroup::Button ); + p.setColor( QPalette::Normal, QColorGroup::Button, config->readColorEntry( "HeaderColor", &c ) ); + c = p.color(QPalette::Normal, QColorGroup::ButtonText ); + p.setColor( QPalette::Normal, QColorGroup::ButtonText, config->readColorEntry( "HeaderTextColor", &c ) ); + c = p.color(QPalette::Normal, QColorGroup::Highlight ); + p.setColor( QPalette::Normal, QColorGroup::Highlight, config->readColorEntry( "HighlightColor", &c ) ); + c = p.color(QPalette::Normal, QColorGroup::HighlightedText ); + p.setColor( QPalette::Normal, QColorGroup::HighlightedText, config->readColorEntry( "HighlightedTextColor", &c ) ); + mCardView->viewport()->setPalette( p ); + } + else + { + // needed if turned off during a session. + mCardView->viewport()->setPalette( mCardView->palette() ); + } + + //custom fonts? + QFont f( font() ); + if ( config->readBoolEntry( "EnableCustomFonts", false ) ) + { + mCardView->setFont( config->readFontEntry( "TextFont", &f) ); + f.setBold( true ); + mCardView->setHeaderFont( config->readFontEntry( "HeaderFont", &f ) ); + } + else + { + mCardView->setFont( f ); + f.setBold( true ); + mCardView->setHeaderFont( f ); + } + + mCardView->setDrawCardBorder(config->readBoolEntry("DrawBorder", true)); + mCardView->setDrawColSeparators(config->readBoolEntry("DrawSeparators", + true)); + mCardView->setDrawFieldLabels(config->readBoolEntry("DrawFieldLabels",false)); + mShowEmptyFields = config->readBoolEntry("ShowEmptyFields", false); + + mCardView->setShowEmptyFields( mShowEmptyFields ); + + mCardView->setItemWidth( config->readNumEntry( "ItemWidth", 200 ) ); + mCardView->setItemMargin( config->readNumEntry( "ItemMargin", 0 ) ); + mCardView->setItemSpacing( config->readNumEntry( "ItemSpacing", 10 ) ); + mCardView->setSeparatorWidth( config->readNumEntry( "SeparatorWidth", 2 ) ); + + disconnect(mCardView, SIGNAL(executed(CardViewItem *)), + this, SLOT(addresseeExecuted(CardViewItem *))); + + if (KABPrefs::instance()->mHonorSingleClick) + connect(mCardView, SIGNAL(executed(CardViewItem *)), + this, SLOT(addresseeExecuted(CardViewItem *))); + else + connect(mCardView, SIGNAL(doubleClicked(CardViewItem *)), + this, SLOT(addresseeExecuted(CardViewItem *))); + +} + +void KAddressBookCardView::writeConfig( KConfig *config ) +{ + config->writeEntry( "ItemWidth", mCardView->itemWidth() ); + KAddressBookView::writeConfig( config ); +} + +QStringList KAddressBookCardView::selectedUids() +{ + QStringList uidList; + CardViewItem *item; + AddresseeCardViewItem *aItem; + + for (item = mCardView->firstItem(); item; item = item->nextItem()) + { + if (item->isSelected()) + { +#ifndef KAB_EMBEDDED + aItem = dynamic_cast<AddresseeCardViewItem*>(item); +#else //KAB_EMBEDDED + aItem = (AddresseeCardViewItem*)(item); +#endif //KAB_EMBEDDED + if (aItem) + uidList << aItem->addressee().uid(); + } + } + + return uidList; +} + +void KAddressBookCardView::refresh(QString uid) +{ + CardViewItem *item; + AddresseeCardViewItem *aItem; + + if (uid.isNull()) + { + // Rebuild the view + mCardView->viewport()->setUpdatesEnabled( false ); + mCardView->clear(); + + KABC::Addressee::List addresseeList = addressees(); + KABC::Addressee::List::Iterator iter; + for (iter = addresseeList.begin(); iter != addresseeList.end(); ++iter) + { + aItem = new AddresseeCardViewItem(fields(), mShowEmptyFields, + addressBook(), *iter, mCardView); + } + mCardView->viewport()->setUpdatesEnabled( true ); + mCardView->viewport()->update(); + + // by default nothing is selected + emit selected(QString::null); + } + else + { + // Try to find the one to refresh + bool found = false; + for (item = mCardView->firstItem(); item && !found; + item = item->nextItem()) + { +#ifndef KAB_EMBEDDED + aItem = dynamic_cast<AddresseeCardViewItem*>(item); +#else //KAB_EMBEDDED + aItem = (AddresseeCardViewItem*)(item); +#endif //KAB_EMBEDDED + + if ((aItem) && (aItem->addressee().uid() == uid)) + { + aItem->refresh(); + found = true; + } + } + } +} + +void KAddressBookCardView::setSelected(QString uid, bool selected) +{ + CardViewItem *item; + AddresseeCardViewItem *aItem; + + if (uid.isNull()) + { + mCardView->selectAll(selected); + } + else + { + bool found = false; + for (item = mCardView->firstItem(); item && !found; + item = item->nextItem()) + { +#ifndef KAB_EMBEDDED + aItem = dynamic_cast<AddresseeCardViewItem*>(item); +#else //KAB_EMBEDDED + aItem = (AddresseeCardViewItem*)(item); +#endif //KAB_EMBEDDED + + if ((aItem) && (aItem->addressee().uid() == uid)) + { + mCardView->setSelected(aItem, selected); + mCardView->ensureItemVisible(item); + found = true; + } + } + } +} + +//US added an additional method without parameter +void KAddressBookCardView::setSelected() +{ + setSelected(QString::null, true); +} + +void KAddressBookCardView::addresseeExecuted(CardViewItem *item) +{ +#ifndef KAB_EMBEDDED + AddresseeCardViewItem *aItem = dynamic_cast<AddresseeCardViewItem*>(item); +#else //KAB_EMBEDDED + AddresseeCardViewItem *aItem = (AddresseeCardViewItem*)(item); +#endif //KAB_EMBEDDED + if (aItem) + { + //kdDebug()<<"... even has a valid item:)"<<endl; + emit executed(aItem->addressee().uid()); + } +} + +void KAddressBookCardView::addresseeSelected() +{ + CardViewItem *item; + AddresseeCardViewItem *aItem; + + bool found = false; + for (item = mCardView->firstItem(); item && !found; + item = item->nextItem()) + { + if (item->isSelected()) + { +#ifndef KAB_EMBEDDED + aItem = dynamic_cast<AddresseeCardViewItem*>(item); +#else //KAB_EMBEDDED + aItem = (AddresseeCardViewItem*)(item); +#endif //KAB_EMBEDDED + if ( aItem ) + { + emit selected(aItem->addressee().uid()); + found = true; + } + } + } + + if (!found) + emit selected(QString::null); + +} +#ifndef KAB_EMBEDDED +#include "kaddressbookcardview.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/views/kaddressbookcardview.h b/kaddressbook/views/kaddressbookcardview.h new file mode 100644 index 0000000..cd70371 --- a/dev/null +++ b/kaddressbook/views/kaddressbookcardview.h @@ -0,0 +1,117 @@ +#ifndef KADDRESSBOOKCARDVIEW_H +#define KADDRESSBOOKCARDVIEW_H + +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qstring.h> +#ifndef KAB_EMBEDDED +#include <kiconview.h> +#else //KAB_EMBEDDED +#include <klocale.h> +#endif //KAB_EMBEDDED + +#include "cardview.h" +#include "kaddressbookview.h" +#include "configurecardviewdialog.h" + +class QDragEnterEvent; +class QDragEntryEvent; +class QDropEvent; +class KConfig; +class AddresseeCardView; + +/** + This view uses the CardView class to create a card view. At some + point in the future I think this will be the default view of + KAddressBook. + */ +class KAddressBookCardView : public KAddressBookView +{ + Q_OBJECT + + public: + KAddressBookCardView( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ); + virtual ~KAddressBookCardView(); + + virtual QStringList selectedUids(); + virtual QString type() const { return "Card"; } + + virtual void readConfig(KConfig *config); + virtual void writeConfig(KConfig *); + + public slots: + void refresh(QString uid = QString::null); + void setSelected(QString uid/*US = QString::null*/, bool selected/*US = true*/); +//US added an additional method without parameter + void setSelected(); + + protected slots: + void addresseeExecuted(CardViewItem *item); + void addresseeSelected(); + + private: + AddresseeCardView *mCardView; + bool mShowEmptyFields; +}; + +class AddresseeCardView : public CardView +{ + Q_OBJECT + public: + AddresseeCardView(QWidget *parent, const char *name = 0); + ~AddresseeCardView(); + + signals: + void startAddresseeDrag(); + void addresseeDropped(QDropEvent *); + + protected: + virtual void dragEnterEvent(QDragEnterEvent *); + virtual void dropEvent(QDropEvent *); + virtual void startDrag(); +}; + + +class CardViewFactory : public ViewFactory +{ + public: + KAddressBookView *view( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new KAddressBookCardView( ab, parent, name ); + } + + QString type() const { return "Card"; } + + QString description() const { return i18n( "Rolodex style cards represent contacts." ); } + + ViewConfigureWidget *configureWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ) + { + return new ConfigureCardViewWidget( ab, parent, name ); + } +}; + + +#endif diff --git a/kaddressbook/views/kaddressbookiconview.cpp b/kaddressbook/views/kaddressbookiconview.cpp new file mode 100644 index 0000000..50ff285 --- a/dev/null +++ b/kaddressbook/views/kaddressbookiconview.cpp @@ -0,0 +1,378 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KAB_EMBEDDED +#include <qiconview.h> +#include <qstringlist.h> + +#include <kabc/addressee.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> + +#else //KAB_EMBEDDED +#endif //KAB_EMBEDDED + +#include <kabc/addressbook.h> +#include "kabprefs.h" +#include "viewmanager.h" +#include "kaddressbookiconview.h" +#include <qlayout.h> +#include <kglobal.h> +/*US transfered to the headerfile +class IconViewFactory : public ViewFactory +{ + public: + KAddressBookView *view( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new KAddressBookIconView( ab, parent, name ); + } + + QString type() const { return "Icon"; } + + QString description() const { return i18n( "Icons represent contacts. Very simple view." ); } +}; + +*/ + +extern "C" { + void *init_libkaddrbk_iconview() + { + return ( new IconViewFactory ); + } +} + +//////////////////////////////// +// AddresseeIconView (internal class) +#ifndef KAB_EMBEDDED +AddresseeIconView::AddresseeIconView(QWidget *parent, const char *name) + : KIconView(parent, name) +#else //KAB_EMBEDDED +AddresseeIconView::AddresseeIconView(QWidget *parent, const char *name) + : QIconView(parent, name) +#endif //KAB_EMBEDDED + +{ + setSelectionMode( QIconView::Extended ); + setResizeMode( QIconView::Adjust ); + setWordWrapIconText( true ); + setGridX( 100 ); + setItemsMovable(false); + setSorting(true, true); + + +//US ??? setMode( KIconView::Select ); + +#ifndef KAB_EMBEDDED + + connect(this, SIGNAL(dropped(QDropEvent*, const QValueList<QIconDragItem>&)), + this, SLOT(itemDropped(QDropEvent*, const QValueList<QIconDragItem>&))); +#endif //KAB_EMBEDDED +} + +AddresseeIconView::~AddresseeIconView() +{ +} + +void AddresseeIconView::itemDropped(QDropEvent *e, + const QValueList<QIconDragItem> &) +{ + emit addresseeDropped(e); +} + +QDragObject *AddresseeIconView::dragObject() +{ + emit startAddresseeDrag(); + + // We never want IconView to start the drag + return 0; +} +//////////////////////////////// +// AddresseeIconViewItem (internal class) +#ifndef KAB_EMBEDDED +class AddresseeIconViewItem : public KIconViewItem +#else //KAB_EMBEDDED +class AddresseeIconViewItem : public QIconViewItem +#endif //KAB_EMBEDDED +{ + public: +#ifndef KAB_EMBEDDED + AddresseeIconViewItem(const KABC::Field::List &fields, + KABC::AddressBook *doc, const KABC::Addressee &a, + QIconView *parent) + : KIconViewItem(parent), mFields( fields ), mDocument(doc), mAddressee(a) +#else //KAB_EMBEDDED + AddresseeIconViewItem(const KABC::Field::List &fields, + KABC::AddressBook *doc, const KABC::Addressee &a, + QIconView *parent) + : QIconViewItem(parent), mFields( fields ), mDocument(doc), mAddressee(a) +#endif //KAB_EMBEDDED + { + if ( mFields.isEmpty() ) { + mFields = KABC::Field::defaultFields(); + } + refresh(); + } + + const KABC::Addressee &addressee() const { return mAddressee; } + + void refresh() + { + // Update our addressee, since it may have changed elsewhere + mAddressee = mDocument->findByUid(mAddressee.uid()); + + if (!mAddressee.isEmpty()) + setText( mAddressee.givenName() + " " + mAddressee.familyName() ); + + QPixmap icon; + QPixmap defaultIcon( KGlobal::iconLoader()->loadIcon( "vcard", KIcon::Desktop, 128 ) ); + KABC::Picture pic = mAddressee.photo(); + if ( pic.data().isNull() ) + pic = mAddressee.logo(); + + if ( pic.isIntern() && !pic.data().isNull() ) { + QImage img = pic.data(); +#ifndef KAB_EMBEDDED + if ( img.width() > img.height() ) + icon = img.scaleWidth( 32 ); + else + icon = img.scaleHeight( 32 ); +#else //KAB_EMBEDDED + qDebug("AddresseeIconViewItem::refresh - scale here dependend of the displaysize and the right factor"); + icon.convertFromImage(img.smoothScale(32, 32)); +#endif //KAB_EMBEDDED + + } else + icon = defaultIcon; + + setPixmap( icon ); + } + + private: + KABC::Field::List mFields; + KABC::AddressBook *mDocument; + KABC::Addressee mAddressee; +}; + +/////////////////////////////// +// KAddressBookView + +KAddressBookIconView::KAddressBookIconView( KABC::AddressBook *ab, + QWidget *parent, const char *name) + : KAddressBookView( ab, parent, name ) +{ + // Init the GUI + QVBoxLayout *layout = new QVBoxLayout(viewWidget()); + + mIconView = new AddresseeIconView(viewWidget(), "mIconView"); + layout->addWidget(mIconView); + + // Connect up the signals + +//US method executed is part of KIconView +//US connect(mIconView, SIGNAL(executed(QIconViewItem *)), +//US this, SLOT(addresseeExecuted(QIconViewItem *))); + connect(mIconView, SIGNAL(selectionChanged(QIconViewItem *)), + this, SLOT(addresseeExecuted(QIconViewItem *))); + + connect(mIconView, SIGNAL(selectionChanged()), + this, SLOT(addresseeSelected())); + connect(mIconView, SIGNAL(addresseeDropped(QDropEvent*)), + this, SIGNAL(dropped(QDropEvent*))); + connect(mIconView, SIGNAL(startAddresseeDrag()), + this, SIGNAL(startDrag())); +} + +KAddressBookIconView::~KAddressBookIconView() +{ +} + +void KAddressBookIconView::readConfig(KConfig *config) +{ + KAddressBookView::readConfig(config); + +//US method executed is part of KIconView +//US disconnect(mIconView, SIGNAL(executed(QIconViewItem *)), +//US this, SLOT(addresseeExecuted(QIconViewItem *))); + disconnect(mIconView, SIGNAL(selectionChanged(QIconViewItem *)), + this, SLOT(addresseeExecuted(QIconViewItem *))); + +//US method executed is part of KIconView. Use selectionChanged instead +/*US + if (KABPrefs::instance()->mHonorSingleClick) + connect(mIconView, SIGNAL(executed(QIconViewItem *)), + this, SLOT(addresseeExecuted(QIconViewItem *))); + else + connect(mIconView, SIGNAL(doubleClicked(QIconViewItem *)), + this, SLOT(addresseeExecuted(QIconViewItem *))); +*/ + connect(mIconView, SIGNAL(selectionChanged(QIconViewItem *)), + this, SLOT(addresseeExecuted(QIconViewItem *))); + +} + +QStringList KAddressBookIconView::selectedUids() +{ + QStringList uidList; + QIconViewItem *item; + AddresseeIconViewItem *aItem; + + for (item = mIconView->firstItem(); item; item = item->nextItem()) + { + if (item->isSelected()) + { +#ifndef KAB_EMBEDDED + aItem = dynamic_cast<AddresseeIconViewItem*>(item); +#else //KAB_EMBEDDED + aItem = (AddresseeIconViewItem*)(item); +#endif //KAB_EMBEDDED + if (aItem) + uidList << aItem->addressee().uid(); + } + } + + return uidList; +} + +void KAddressBookIconView::refresh(QString uid) +{ + QIconViewItem *item; + AddresseeIconViewItem *aItem; + + if ( uid.isNull() ) { + // Rebuild the view + mIconView->clear(); + mIconList.clear(); + + KABC::Addressee::List addresseeList = addressees(); + KABC::Addressee::List::Iterator iter; + for ( iter = addresseeList.begin(); iter != addresseeList.end(); ++iter ) + aItem = new AddresseeIconViewItem( fields(), addressBook(), *iter, mIconView ); + + mIconView->arrangeItemsInGrid( true ); + + for ( item = mIconView->firstItem(); item; item = item->nextItem() ) + { +#ifndef KAB_EMBEDDED + AddresseeIconViewItem* aivi = dynamic_cast<AddresseeIconViewItem*>( item ); +#else //KAB_EMBEDDED + AddresseeIconViewItem* aivi = (AddresseeIconViewItem*)( item ); +#endif //KAB_EMBEDDED + mIconList.append( aivi ); + } + + } else { + // Try to find the one to refresh + for ( item = mIconView->firstItem(); item; item = item->nextItem() ) { +#ifndef KAB_EMBEDDED + aItem = dynamic_cast<AddresseeIconViewItem*>(item); +#else //KAB_EMBEDDED + aItem = (AddresseeIconViewItem*)(item); +#endif //KAB_EMBEDDED + if ((aItem) && (aItem->addressee().uid() == uid)) { + aItem->refresh(); + mIconView->arrangeItemsInGrid( true ); + return; + } + } + refresh( QString::null ); + } +} + +void KAddressBookIconView::setSelected(QString uid, bool selected) +{ + QIconViewItem *item; + AddresseeIconViewItem *aItem; + + if (uid.isNull()) + { + mIconView->selectAll(selected); + } + else + { + bool found = false; + for (item = mIconView->firstItem(); item && !found; + item = item->nextItem()) + { +#ifndef KAB_EMBEDDED + aItem = dynamic_cast<AddresseeIconViewItem*>(item); +#else //KAB_EMBEDDED + aItem = (AddresseeIconViewItem*)(item); +#endif //KAB_EMBEDDED + + if ((aItem) && (aItem->addressee().uid() == uid)) + { + mIconView->setSelected(aItem, selected); + mIconView->ensureItemVisible( aItem ); + found = true; + } + } + } +} + +void KAddressBookIconView::addresseeExecuted(QIconViewItem *item) +{ +#ifndef KAB_EMBEDDED + AddresseeIconViewItem *aItem = dynamic_cast<AddresseeIconViewItem*>(item); +#else //KAB_EMBEDDED + AddresseeIconViewItem *aItem = (AddresseeIconViewItem*)(item); +#endif //KAB_EMBEDDED + + if (aItem) { + emit executed(aItem->addressee().uid()); + } +} + +void KAddressBookIconView::addresseeSelected() +{ + QIconViewItem *item; + AddresseeIconViewItem *aItem; + + bool found = false; + for (item = mIconView->firstItem(); item && !found; + item = item->nextItem()) + { + if (item->isSelected()) + { +#ifndef KAB_EMBEDDED + aItem = dynamic_cast<AddresseeIconViewItem*>(item); +#else //KAB_EMBEDDED + aItem = (AddresseeIconViewItem*)(item); +#endif //KAB_EMBEDDED + if (aItem) + { + emit selected(aItem->addressee().uid()); + found = true; + } + } + } + + if (!found) + emit selected(QString::null); +} + +#ifndef KAB_EMBEDDED +#include "kaddressbookiconview.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/views/kaddressbookiconview.h b/kaddressbook/views/kaddressbookiconview.h new file mode 100644 index 0000000..3afada3 --- a/dev/null +++ b/kaddressbook/views/kaddressbookiconview.h @@ -0,0 +1,130 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Mike Pilone <mpilone@slac.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KADDRESSBOOKICONVIEW_H +#define KADDRESSBOOKICONVIEW_H + +#include <qstring.h> +#ifndef KAB_EMBEDDED +#include <kiconview.h> +#else //KAB_EMBEDDED +#include <qiconview.h> +#include <qptrlist.h> +#include <klocale.h> +#endif //KAB_EMBEDDED +#include "kaddressbookview.h" + +class QIconViewItem; +class KConfig; +class AddresseeIconView; +class AddresseeIconViewItem; +class QIconDragItem; +class KAddressBookIconView; + +namespace KABC { class AddressBook; } + +/** This is an example kaddressbook view that is implemented using +* KIconView. This view is not the most useful view, but it displays +* how simple implementing a new view can be. +*/ +class KAddressBookIconView : public KAddressBookView +{ + Q_OBJECT + + public: + KAddressBookIconView( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ); + virtual ~KAddressBookIconView(); + + virtual QStringList selectedUids(); + virtual QString type() const { return "Icon"; } + + virtual void readConfig(KConfig *config); + + public slots: + void refresh(QString uid = QString::null); +#ifndef KAB_EMBEDDED +//MOC_SKIP_BEGIN + void setSelected(QString uid = QString::null, bool selected = true); +//MOC_SKIP_END +#else //KAB_EMBEDDED +//US my MOC do not like default parameters ??? + void setSelected(QString uid, bool selected); +#endif //KAB_EMBEDDED + + protected slots: + void addresseeExecuted(QIconViewItem *item); + void addresseeSelected(); + + private: + AddresseeIconView *mIconView; + QPtrList<AddresseeIconViewItem> mIconList; +}; + + +#ifndef KAB_EMBEDDED +//MOC_SKIP_BEGIN +class AddresseeIconView : public KIconView +//MOC_SKIP_END +#else //KAB_EMBEDDED +class AddresseeIconView : public QIconView +#endif //KAB_EMBEDDED +{ + Q_OBJECT + + public: + AddresseeIconView(QWidget *parent, const char *name); + ~AddresseeIconView(); + + signals: + void addresseeDropped(QDropEvent *); + void startAddresseeDrag(); + + protected: + virtual QDragObject *dragObject(); + + protected slots: + void itemDropped(QDropEvent *, const QValueList<QIconDragItem> &); +}; + +class IconViewFactory : public ViewFactory +{ + public: + KAddressBookView *view( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new KAddressBookIconView( ab, parent, name ); + } + + QString type() const { return "Icon"; } + + QString description() const { return i18n( "Icons represent contacts. Very simple view." ); } +}; +/* +extern "C" { + void *init_libkaddrbk_iconview() + { + return ( new IconViewFactory ); + } +} +*/ +#endif diff --git a/kaddressbook/views/kaddressbooktableview.cpp b/kaddressbook/views/kaddressbooktableview.cpp new file mode 100644 index 0000000..ee2fcf8 --- a/dev/null +++ b/kaddressbook/views/kaddressbooktableview.cpp @@ -0,0 +1,337 @@ +// $Id$ + +#include <qvbox.h> +#include <qlistbox.h> +#include <qwidget.h> +#include <qfile.h> +#include <qimage.h> +#include <qcombobox.h> +#include <qapplication.h> +#include <qdragobject.h> +#include <qevent.h> +#include <qurl.h> +#include <qpixmap.h> + +#include <kabc/addressbook.h> +#include <kapplication.h> +#include <kconfig.h> +#include <kcolorbutton.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kurl.h> +#include <kurlrequester.h> + +//US#include "configuretableviewdialog.h" +#include "contactlistview.h" +#include "kabprefs.h" +#include "undocmds.h" +#include "viewmanager.h" + +#include <qlayout.h> + + +#include "kaddressbooktableview.h" + + +KAddressBookTableView::KAddressBookTableView( KABC::AddressBook *ab, + QWidget *parent, const char *name ) + : KAddressBookView( ab, parent, name ) +{ + mainLayout = new QVBoxLayout( viewWidget(), 2 ); + + // The list view will be created when the config is read. + mListView = 0; +} + +KAddressBookTableView::~KAddressBookTableView() +{ +} + +void KAddressBookTableView::reconstructListView() +{ + if (mListView) + { + disconnect(mListView, SIGNAL(selectionChanged()), + this, SLOT(addresseeSelected())); + disconnect(mListView, SIGNAL(executed(QListViewItem*)), + this, SLOT(addresseeExecuted(QListViewItem*))); + disconnect(mListView, SIGNAL(doubleClicked(QListViewItem*)), + this, SLOT(addresseeExecuted(QListViewItem*))); + disconnect(mListView, SIGNAL(startAddresseeDrag()), this, + SIGNAL(startDrag())); + disconnect(mListView, SIGNAL(returnPressed(QListViewItem*)), + this, SLOT(addresseeExecuted(QListViewItem*))); + + disconnect(mListView, SIGNAL(addresseeDropped(QDropEvent*)), this, + SIGNAL(dropped(QDropEvent*))); + delete mListView; + } + + mListView = new ContactListView( this, addressBook(), viewWidget() ); + + // Add the columns + KABC::Field::List fieldList = fields(); + KABC::Field::List::ConstIterator it; + + int c = 0; + for( it = fieldList.begin(); it != fieldList.end(); ++it ) { + mListView->addColumn( (*it)->label() ); + mListView->setColumnWidthMode(c++, QListView::Manual); +//US + // qDebug("KAddressBookTableView::reconstructListView: field %s", (*it)->label().latin1()); + } + + connect(mListView, SIGNAL(selectionChanged()), + this, SLOT(addresseeSelected())); + connect(mListView, SIGNAL(startAddresseeDrag()), this, + SIGNAL(startDrag())); + connect(mListView, SIGNAL(addresseeDropped(QDropEvent*)), this, + SIGNAL(dropped(QDropEvent*))); + + if (KABPrefs::instance()->mHonorSingleClick) + connect(mListView, SIGNAL(executed(QListViewItem*)), + this, SLOT(addresseeExecuted(QListViewItem*))); + else + connect(mListView, SIGNAL(doubleClicked(QListViewItem*)), + this, SLOT(addresseeExecuted(QListViewItem*))); + connect(mListView, SIGNAL(returnPressed(QListViewItem*)), + this, SLOT(addresseeExecuted(QListViewItem*))); + connect(mListView, SIGNAL(signalDelete()), + this, SLOT(addresseeDeleted())); + + refresh(); + + mListView->setSorting( 0, true ); + mainLayout->addWidget( mListView ); + mainLayout->activate(); + mListView->show(); +} + +void KAddressBookTableView::writeConfig(KConfig *config) +{ + KAddressBookView::writeConfig(config); + + mListView->saveLayout(config, config->group()); +} + +void KAddressBookTableView::readConfig(KConfig *config) +{ + KAddressBookView::readConfig( config ); + + // The config could have changed the fields, so we need to reconstruct + // the listview. + reconstructListView(); + + // Set the list view options + mListView->setAlternateBackgroundEnabled(config->readBoolEntry("ABackground", + true)); + mListView->setSingleLineEnabled(config->readBoolEntry("SingleLine", false)); + mListView->setToolTipsEnabled(config->readBoolEntry("ToolTips", true)); + + if (config->readBoolEntry("Background", false)) + mListView->setBackgroundPixmap(config->readEntry("BackgroundName")); + + // Restore the layout of the listview + mListView->restoreLayout(config, config->group()); +} + +void KAddressBookTableView::refresh(QString uid) +{ + // For now just repopulate. In reality this method should + // check the value of uid, and if valid iterate through + // the listview to find the entry, then tell it to refresh. + + if (uid.isNull()) { + // Clear the list view + QString currentUID, nextUID; +#ifndef KAB_EMBEDDED + ContactListViewItem *currentItem = dynamic_cast<ContactListViewItem*>( mListView->currentItem() ); +#else //KAB_EMBEDDED + ContactListViewItem *currentItem = (ContactListViewItem*)( mListView->currentItem() ); +#endif //KAB_EMBEDDED + + if ( currentItem ) { +#ifndef KAB_EMBEDDED + ContactListViewItem *nextItem = dynamic_cast<ContactListViewItem*>( currentItem->itemBelow() ); +#else //KAB_EMBEDDED + ContactListViewItem *nextItem = (ContactListViewItem*)( currentItem->itemBelow() ); +#endif //KAB_EMBEDDED + if ( nextItem ) + nextUID = nextItem->addressee().uid(); + currentUID = currentItem->addressee().uid(); + } + + mListView->clear(); + + currentItem = 0; + KABC::Addressee::List addresseeList = addressees(); + KABC::Addressee::List::Iterator it; + for (it = addresseeList.begin(); it != addresseeList.end(); ++it ) { + ContactListViewItem *item = new ContactListViewItem(*it, mListView, addressBook(), fields()); + if ( (*it).uid() == currentUID ) + currentItem = item; + else if ( (*it).uid() == nextUID && !currentItem ) + currentItem = item; + } + + // Sometimes the background pixmap gets messed up when we add lots + // of items. + mListView->repaint(); + + if ( currentItem ) { + mListView->setCurrentItem( currentItem ); + mListView->ensureItemVisible( currentItem ); + } + } else { + // Only need to update on entry. Iterate through and try to find it + ContactListViewItem *ceItem; + QListViewItemIterator it( mListView ); + while ( it.current() ) { +#ifndef KAB_EMBEDDED + ceItem = dynamic_cast<ContactListViewItem*>( it.current() ); +#else //KAB_EMBEDDED + ceItem = (ContactListViewItem*)( it.current() ); +#endif //KAB_EMBEDDED + + if ( ceItem && ceItem->addressee().uid() == uid ) { + ceItem->refresh(); + return; + } + ++it; + } + + refresh( QString::null ); + } +} + +QStringList KAddressBookTableView::selectedUids() +{ + QStringList uidList; + QListViewItem *item; + ContactListViewItem *ceItem; + + for(item = mListView->firstChild(); item; item = item->itemBelow()) + { + if (mListView->isSelected( item )) + { +#ifndef KAB_EMBEDDED + ceItem = dynamic_cast<ContactListViewItem*>(item); +#else //KAB_EMBEDDED + ceItem = (ContactListViewItem*)(item); +#endif //KAB_EMBEDDED + + if (ceItem != 0L) + uidList << ceItem->addressee().uid(); + } + } + if ( uidList.count() == 0 ) + if ( mListView->currentItem() ) { + ceItem = (ContactListViewItem*)(mListView->currentItem()) ; + uidList << ceItem->addressee().uid(); + } + + return uidList; +} + +void KAddressBookTableView::setSelected(QString uid, bool selected) +{ + QListViewItem *item; + ContactListViewItem *ceItem; + + if (uid.isNull()) + { + mListView->selectAll(selected); + } + else + { + for(item = mListView->firstChild(); item; item = item->itemBelow()) + { +#ifndef KAB_EMBEDDED + ceItem = dynamic_cast<ContactListViewItem*>(item); +#else //KAB_EMBEDDED + ceItem = (ContactListViewItem*)(item); +#endif //KAB_EMBEDDED + + + if ((ceItem != 0L) && (ceItem->addressee().uid() == uid)) + { + mListView->setSelected(item, selected); + + if (selected) + mListView->ensureItemVisible(item); + } + } + } +} + +void KAddressBookTableView::addresseeSelected() +{ + // We need to try to find the first selected item. This might not be the + // last selected item, but when QListView is in multiselection mode, + // there is no way to figure out which one was + // selected last. + QListViewItem *item; + bool found =false; + for (item = mListView->firstChild(); item && !found; + item = item->nextSibling()) + { + if (item->isSelected()) + { + found = true; +#ifndef KAB_EMBEDDED + ContactListViewItem *ceItem + = dynamic_cast<ContactListViewItem*>(item); +#else //KAB_EMBEDDED + ContactListViewItem *ceItem + = (ContactListViewItem*)(item); +#endif //KAB_EMBEDDED + + if ( ceItem ) emit selected(ceItem->addressee().uid()); + } + } + + if (!found) + emit selected(QString::null); +} + +void KAddressBookTableView::addresseeExecuted(QListViewItem *item) +{ + if (item) + { +#ifndef KAB_EMBEDDED + ContactListViewItem *ceItem + = dynamic_cast<ContactListViewItem*>(item); +#else //KAB_EMBEDDED + ContactListViewItem *ceItem + = (ContactListViewItem*)(item); +#endif //KAB_EMBEDDED + + if (ceItem) + { + emit executed(ceItem->addressee().uid()); + } + } + else + { + emit executed(QString::null); + } +} + +void KAddressBookTableView::addresseeDeleted() +{ + + emit deleteRequest(); + +} + + + + + +#ifndef KAB_EMBEDDED +#include "kaddressbooktableview.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/views/kaddressbooktableview.h b/kaddressbook/views/kaddressbooktableview.h new file mode 100644 index 0000000..bb991bc --- a/dev/null +++ b/kaddressbook/views/kaddressbooktableview.h @@ -0,0 +1,114 @@ +#ifndef KADDRESSBOOKTABLEVIEW_H +#define KADDRESSBOOKTABLEVIEW_H + + +#ifndef KAB_EMBEDDED + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qwidget.h> +#include <qlistview.h> +#include <qstring.h> +#include <qdialog.h> +#include <qtabdialog.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +#include "undo.h" + +#else //KAB_EMBEDDED +#include "views/configuretableviewdialog.h" +#endif //KAB_EMBEDDED + +#include "klocale.h" +#include "kaddressbookview.h" + +class QListViewItem; +class QListBox; +class QVBoxLayout; +class KConfig; + +class ContactListViewItem; +class ContactListView; + + +namespace KABC { class AddressBook; } + +/** + * This class is the table view for kaddressbook. This view is a KListView + * with multiple columns for the selected fields. + * + * @short Table View + * @author Don Sanders <dsanders@kde.org> + * @version 0.1 + */ +class KAddressBookTableView : public KAddressBookView +{ +friend class ContactListView; + + Q_OBJECT + + public: + KAddressBookTableView( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ); + virtual ~KAddressBookTableView(); + + virtual void refresh(QString uid = QString::null); + virtual QStringList selectedUids(); + virtual void setSelected(QString uid = QString::null, bool selected = false); + virtual void readConfig(KConfig *config); + virtual void writeConfig(KConfig *config); + virtual QString type() const { return "Table"; } + + public slots: + virtual void reconstructListView(); + + protected slots: + /** Called whenever the user selects an addressee in the list view. + */ + void addresseeSelected(); + void addresseeDeleted(); + + /** Called whenever the user executes an addressee. In terms of the + * list view, this is probably a double click + */ + void addresseeExecuted(QListViewItem*); + + private: + QVBoxLayout *mainLayout; + ContactListView *mListView; +}; + + +class TableViewFactory : public ViewFactory +{ + public: + KAddressBookView *view( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new KAddressBookTableView( ab, parent, name ); + } + + QString type() const { return "Table"; } + + QString description() const { return i18n( "A listing of contacts in a table. Each cell of " + "the table holds a field of the contact." ); } + + ViewConfigureWidget *configureWidget( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ) + { + return new ConfigureTableViewWidget( ab, parent, name ); + } +}; +/*US +extern "C" { + void *init_libkaddrbk_tableview() + { + return ( new TableViewFactory ); + } +} +*/ + +#endif diff --git a/kaddressbook/xxport/csv_xxport.cpp b/kaddressbook/xxport/csv_xxport.cpp new file mode 100644 index 0000000..ce35053 --- a/dev/null +++ b/kaddressbook/xxport/csv_xxport.cpp @@ -0,0 +1,187 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qfile.h> +#include <qregexp.h> +#include <qtextstream.h> + +#include <kfiledialog.h> +#ifndef KAB_EMBEDDED +#include <kio/netaccess.h> +#endif //KAB_EMBEDDED + +#include <klocale.h> +#include <kmessagebox.h> +#include <ktempfile.h> +#include <kurl.h> + +#include "csvimportdialog.h" + +#include "csv_xxport.h" + + +#ifndef KAB_EMBEDDED + +class CSVXXPortFactory : public XXPortFactory +{ + public: + XXPortObject *xxportObject( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new CSVXXPort( ab, parent, name ); + } +}; + + +extern "C" +{ + void *init_libkaddrbk_csv_xxport() + { + return ( new CSVXXPortFactory() ); + } +} +#endif //KAB_EMBEDDED + + +CSVXXPort::CSVXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name ) + : XXPortObject( ab, parent, name ) +{ + createImportAction( i18n( "Import CSV List..." ) ); + createExportAction( i18n( "Export CSV List..." ) ); +} + +bool CSVXXPort::exportContacts( const KABC::AddresseeList &list, const QString& ) +{ +#ifndef KAB_EMBEDDED + KURL url = KFileDialog::getSaveURL( "addressbook.csv" ); + if ( url.isEmpty() ) + return true; + + if ( !url.isLocalFile() ) { + KTempFile tmpFile; + if ( tmpFile.status() != 0 ) { + QString txt = i18n( "<qt>Unable to open file <b>%1</b>.%2.</qt>" ); + KMessageBox::error( parentWidget(), txt.arg( url.url() ) + .arg( strerror( tmpFile.status() ) ) ); + return false; + } + + doExport( tmpFile.file(), list ); + tmpFile.close(); + + return KIO::NetAccess::upload( tmpFile.name(), url, parentWidget() ); + } else { + QFile file( url.path() ); + if ( !file.open( IO_WriteOnly ) ) { + QString txt = i18n( "<qt>Unable to open file <b>%1</b>.</qt>" ); + KMessageBox::error( parentWidget(), txt.arg( url.path() ) ); + return false; + } + + doExport( &file, list ); + file.close(); + + return true; + } + +#else //KAB_EMBEDDED + + QString fileName = KFileDialog::getSaveFileName( "addressbook.csv", i18n("Save file"), parentWidget() ); + + if ( fileName.isEmpty() ) + return true; + + QFile file( fileName ); + if ( !file.open( IO_WriteOnly ) ) { + QString txt = i18n( "<qt>Unable to open file <b>%1</b>.</qt>" ); + KMessageBox::error( parentWidget(), txt.arg( fileName ) ); + return false; + } + + doExport( &file, list ); + file.close(); + + return true; + + +#endif //KAB_EMBEDDED + +} + +KABC::AddresseeList CSVXXPort::importContacts( const QString& ) const +{ + CSVImportDialog dlg( addressBook(), parentWidget() ); + if ( dlg.exec() ) + return dlg.contacts(); + else + return KABC::AddresseeList(); +} + +void CSVXXPort::doExport( QFile *fp, const KABC::AddresseeList &list ) +{ + QTextStream t( fp ); + + KABC::AddresseeList::ConstIterator iter; + KABC::Field::List fields = addressBook()->fields(); + KABC::Field::List::Iterator fieldIter; + bool first = true; + + // First output the column headings + for ( fieldIter = fields.begin(); fieldIter != fields.end(); ++fieldIter ) { + if ( !first ) + t << ","; + + t << "\"" << (*fieldIter)->label() << "\""; + first = false; + } + t << "\n"; + + // Then all the addressee objects + KABC::Addressee addr; + for ( iter = list.begin(); iter != list.end(); ++iter ) { + addr = *iter; + first = true; + + for ( fieldIter = fields.begin(); fieldIter != fields.end(); ++fieldIter ) { + if ( !first ) + t << ","; + + t << "\"" << (*fieldIter)->value( addr ).replace( QRegExp("\n"), "\\n" ) << "\""; + first = false; + } + + t << "\n"; + } +} + +#ifndef KAB_EMBEDDED +#include "csv_xxport.moc" +#endif //KAB_EMBEDDED + + diff --git a/kaddressbook/xxport/csv_xxport.h b/kaddressbook/xxport/csv_xxport.h new file mode 100644 index 0000000..fe6b3c6 --- a/dev/null +++ b/kaddressbook/xxport/csv_xxport.h @@ -0,0 +1,68 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef CSV_XXPORT_H +#define CSV_XXPORT_H + +#include <xxportobject.h> + +class QFile; + + +class CSVXXPort : public XXPortObject +{ + Q_OBJECT + + public: + CSVXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + + QString identifier() const { return "csv"; } + + public slots: + bool exportContacts( const KABC::AddresseeList &list, const QString &data ); + KABC::AddresseeList importContacts( const QString &data ) const; + + private: + void doExport( QFile *fp, const KABC::AddresseeList &list ); +}; + +#ifdef KAB_EMBEDDED +class CSVXXPortFactory : public XXPortFactory +{ + public: + XXPortObject *xxportObject( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new CSVXXPort( ab, parent, name ); + } +}; +#endif //KAB_EMBEDDED + + +#endif diff --git a/kaddressbook/xxport/csvimportdialog.cpp b/kaddressbook/xxport/csvimportdialog.cpp new file mode 100644 index 0000000..1093f9c --- a/dev/null +++ b/kaddressbook/xxport/csvimportdialog.cpp @@ -0,0 +1,922 @@ +/* + This file is part of KAddressBook. + Copyright (C) 2003 Tobias Koenig <tokoe@kde.org> + based on the code of KSpread's CSV Import Dialog + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + + +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qinputdialog.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qtable.h> +#include <qlayout.h> +#include <qtextstream.h> +#include <qfile.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <kfiledialog.h> +#include <klineedit.h> +#include <klocale.h> +#include <kglobal.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <kurlrequester.h> + +#ifdef DESKTOP_VERSION +#include "qtable.h" +#else +#include "qcombotableitem.h" +#endif +#include "csvimportdialog.h" + +CSVImportDialog::CSVImportDialog( KABC::AddressBook *ab, QWidget *parent, + const char * name ) + : KDialogBase( Plain, i18n ( "CSV Import Dialog" ), Ok | Cancel | User1 | + User2, Ok, parent, name, true, true ), + mAdjustRows( false ), + mStartLine( 0 ), + mTextQuote( '"' ), + mDelimiter( "," ), + mAddressBook( ab ) +{ + initGUI(); + + mTypeMap.insert( i18n( "Undefined" ), Undefined ); + mTypeMap.insert( KABC::Addressee::formattedNameLabel(), FormattedName ); + mTypeMap.insert( KABC::Addressee::familyNameLabel(), FamilyName ); + mTypeMap.insert( KABC::Addressee::givenNameLabel(), GivenName ); + mTypeMap.insert( KABC::Addressee::additionalNameLabel(), AdditionalName ); + mTypeMap.insert( KABC::Addressee::prefixLabel(), Prefix ); + mTypeMap.insert( KABC::Addressee::suffixLabel(), Suffix ); + mTypeMap.insert( KABC::Addressee::nickNameLabel(), NickName ); + mTypeMap.insert( KABC::Addressee::birthdayLabel(), Birthday ); + + mTypeMap.insert( KABC::Addressee::homeAddressStreetLabel(), HomeAddressStreet ); + mTypeMap.insert( KABC::Addressee::homeAddressLocalityLabel(), + HomeAddressLocality ); + mTypeMap.insert( KABC::Addressee::homeAddressRegionLabel(), HomeAddressRegion ); + mTypeMap.insert( KABC::Addressee::homeAddressPostalCodeLabel(), + HomeAddressPostalCode ); + mTypeMap.insert( KABC::Addressee::homeAddressCountryLabel(), + HomeAddressCountry ); + mTypeMap.insert( KABC::Addressee::homeAddressLabelLabel(), HomeAddressLabel ); + + mTypeMap.insert( KABC::Addressee::businessAddressStreetLabel(), + BusinessAddressStreet ); + mTypeMap.insert( KABC::Addressee::businessAddressLocalityLabel(), + BusinessAddressLocality ); + mTypeMap.insert( KABC::Addressee::businessAddressRegionLabel(), + BusinessAddressRegion ); + mTypeMap.insert( KABC::Addressee::businessAddressPostalCodeLabel(), + BusinessAddressPostalCode ); + mTypeMap.insert( KABC::Addressee::businessAddressCountryLabel(), + BusinessAddressCountry ); + mTypeMap.insert( KABC::Addressee::businessAddressLabelLabel(), + BusinessAddressLabel ); + + mTypeMap.insert( KABC::Addressee::homePhoneLabel(), HomePhone ); + mTypeMap.insert( KABC::Addressee::businessPhoneLabel(), BusinessPhone ); + mTypeMap.insert( KABC::Addressee::mobilePhoneLabel(), MobilePhone ); + mTypeMap.insert( KABC::Addressee::homeFaxLabel(), HomeFax ); + mTypeMap.insert( KABC::Addressee::businessFaxLabel(), BusinessFax ); + mTypeMap.insert( KABC::Addressee::carPhoneLabel(), CarPhone ); + mTypeMap.insert( KABC::Addressee::isdnLabel(), Isdn ); + mTypeMap.insert( KABC::Addressee::pagerLabel(), Pager ); + mTypeMap.insert( KABC::Addressee::emailLabel(), Email ); + mTypeMap.insert( KABC::Addressee::mailerLabel(), Mailer ); + mTypeMap.insert( KABC::Addressee::titleLabel(), Title ); + mTypeMap.insert( KABC::Addressee::roleLabel(), Role ); + mTypeMap.insert( KABC::Addressee::organizationLabel(), Organization ); + mTypeMap.insert( KABC::Addressee::noteLabel(), Note ); + mTypeMap.insert( KABC::Addressee::urlLabel(), URL ); + + mCustomCounter = mTypeMap.count(); + int count = mCustomCounter; + + KABC::Field::List fields = mAddressBook->fields( KABC::Field::CustomCategory ); + KABC::Field::List::Iterator it; + for ( it = fields.begin(); it != fields.end(); ++it, ++count ) + mTypeMap.insert( (*it)->label(), count ); + + connect( mDelimiterBox, SIGNAL( clicked( int ) ), + this, SLOT( delimiterClicked( int ) ) ); + connect( mDelimiterEdit, SIGNAL( returnPressed() ), + this, SLOT( returnPressed() ) ); + connect( mDelimiterEdit, SIGNAL( textChanged ( const QString& ) ), + this, SLOT( textChanged ( const QString& ) ) ); + connect( mComboLine, SIGNAL( activated( const QString& ) ), + this, SLOT( lineSelected( const QString& ) ) ); + connect( mComboQuote, SIGNAL( activated( const QString& ) ), + this, SLOT( textquoteSelected( const QString& ) ) ); + connect( mIgnoreDuplicates, SIGNAL( stateChanged( int ) ), + this, SLOT( ignoreDuplicatesChanged( int ) ) ); + + connect( mUrlRequester, SIGNAL( returnPressed( const QString& ) ), + this, SLOT( setFile( const QString& ) ) ); + connect( mUrlRequester, SIGNAL( urlSelected( const QString& ) ), + this, SLOT( setFile( const QString& ) ) ); + connect( mUrlRequester->lineEdit(), SIGNAL( textChanged ( const QString& ) ), + this, SLOT( urlChanged( const QString& ) ) ); + + connect( this, SIGNAL( user1Clicked() ), + this, SLOT( applyTemplate() ) ); + + connect( this, SIGNAL( user2Clicked() ), + this, SLOT( saveTemplate() ) ); + + // if ( QApplication::desktop()->width() < 321 ) + QIconSet icon = SmallIcon("filesave"); + + findButton( User2 )->setIconSet (icon ) ; + icon = SmallIcon("fileopen"); + findButton( User1 )->setIconSet (icon ) ; + int wid = findButton( User2 )->sizeHint().height(); + findButton( User2 )->setMaximumWidth( wid+4 ); + findButton( User1 )->setMaximumWidth( wid+4 ); +} + +CSVImportDialog::~CSVImportDialog() +{ +} + +KABC::AddresseeList CSVImportDialog::contacts() const +{ + KABC::AddresseeList contacts; + + for ( int row = 1; row < mTable->numRows(); ++row ) { + KABC::Addressee a; + bool emptyRow = true; + KABC::Address addrHome( KABC::Address::Home ); + KABC::Address addrWork( KABC::Address::Work ); + for ( int col = 0; col < mTable->numCols(); ++col ) { + + QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, col ) ); + + if ( !item ) { + qDebug( "ERROR: item cast failed" ); + continue; + } + + QString value = mTable->text( row, col ); + if ( !value.isEmpty() ) + emptyRow = false; + + switch ( posToType( item->currentItem() ) ) + { + case Undefined: + continue; + break; + case FormattedName: + a.setFormattedName( value ); + break; + case GivenName: + a.setGivenName( value ); + break; + case FamilyName: + a.setFamilyName( value ); + break; + case AdditionalName: + a.setAdditionalName( value ); + break; + case Prefix: + a.setPrefix( value ); + break; + case Suffix: + a.setSuffix( value ); + break; + case NickName: + a.setNickName( value ); + break; + case Birthday: +//US +//the generated code had the following format: a.setBirthday( QDate::fromString( value, Qt::ISODate ) ); +// But Qt::IsoDate and QDate::fromString was not specified. Do I have the wrong QT version ? + { + QDate dt = KGlobal::locale()->readDate( value, "%Y-%m-%d"); // = Qt::ISODate + a.setBirthday(dt); + } + break; + case Email: + if ( !value.isEmpty() ) + a.insertEmail( value, true ); + break; + case Role: + a.setRole( value ); + break; + case Title: + a.setTitle( value ); + break; + case Mailer: + a.setMailer( value ); + break; + case URL: + a.setUrl( value ); + break; + case Organization: + a.setOrganization( value ); + break; + case Note: + a.setNote( value ); + break; + + case HomePhone: + if ( !value.isEmpty() ) { + KABC::PhoneNumber number( value, KABC::PhoneNumber::Home ); + a.insertPhoneNumber( number ); + } + break; + case BusinessPhone: + if ( !value.isEmpty() ) { + KABC::PhoneNumber number( value, KABC::PhoneNumber::Work ); + a.insertPhoneNumber( number ); + } + break; + case MobilePhone: + if ( !value.isEmpty() ) { + KABC::PhoneNumber number( value, KABC::PhoneNumber::Cell ); + a.insertPhoneNumber( number ); + } + break; + case HomeFax: + if ( !value.isEmpty() ) { + KABC::PhoneNumber number( value, KABC::PhoneNumber::Home | + KABC::PhoneNumber::Fax ); + a.insertPhoneNumber( number ); + } + break; + case BusinessFax: + if ( !value.isEmpty() ) { + KABC::PhoneNumber number( value, KABC::PhoneNumber::Work | + KABC::PhoneNumber::Fax ); + a.insertPhoneNumber( number ); + } + break; + case CarPhone: + if ( !value.isEmpty() ) { + KABC::PhoneNumber number( value, KABC::PhoneNumber::Car ); + a.insertPhoneNumber( number ); + } + break; + case Isdn: + if ( !value.isEmpty() ) { + KABC::PhoneNumber number( value, KABC::PhoneNumber::Isdn ); + a.insertPhoneNumber( number ); + } + break; + case Pager: + if ( !value.isEmpty() ) { + KABC::PhoneNumber number( value, KABC::PhoneNumber::Pager ); + a.insertPhoneNumber( number ); + } + break; + + case HomeAddressStreet: + addrHome.setStreet( value ); + break; + case HomeAddressLocality: + addrHome.setLocality( value ); + break; + case HomeAddressRegion: + addrHome.setRegion( value ); + break; + case HomeAddressPostalCode: + addrHome.setPostalCode( value ); + break; + case HomeAddressCountry: + addrHome.setCountry( value ); + break; + case HomeAddressLabel: + addrHome.setLabel( value ); + break; + + case BusinessAddressStreet: + addrWork.setStreet( value ); + break; + case BusinessAddressLocality: + addrWork.setLocality( value ); + break; + case BusinessAddressRegion: + addrWork.setRegion( value ); + break; + case BusinessAddressPostalCode: + addrWork.setPostalCode( value ); + break; + case BusinessAddressCountry: + addrWork.setCountry( value ); + break; + case BusinessAddressLabel: + addrWork.setLabel( value ); + break; + default: + KABC::Field::List fields = mAddressBook->fields( KABC::Field::CustomCategory ); + KABC::Field::List::Iterator it; + + int counter = 0; + for ( it = fields.begin(); it != fields.end(); ++it ) { + if ( counter == (int)( posToType( item->currentItem() ) - mCustomCounter ) ) + { + (*it)->setValue( a, value ); + continue; + } + ++counter; + } + break; + } + } + + if ( !addrHome.isEmpty() ) + a.insertAddress( addrHome ); + if ( !addrWork.isEmpty() ) + a.insertAddress( addrWork ); + + if ( !emptyRow && !a.isEmpty() ) + contacts.append( a ); + } + + return contacts; +} + +void CSVImportDialog::initGUI() +{ + QWidget* page = plainPage(); + + QGridLayout *layout = new QGridLayout( page, 1, 1, marginHintSmall(), + spacingHintSmall() ); + QHBoxLayout *hbox = new QHBoxLayout(); + hbox->setSpacing( spacingHint() ); + + QLabel *label = new QLabel( i18n( "File to import:" ), page ); + hbox->addWidget( label ); + + mUrlRequester = new KURLRequester( page ); + mUrlRequester->setFilter( "*.csv" ); + hbox->addWidget( mUrlRequester ); + + layout->addMultiCellLayout( hbox, 0, 0, 0, 1 ); + + // Delimiter: comma, semicolon, tab, space, other + mDelimiterBox = new QButtonGroup( i18n( "Delimiter" ), page ); + mDelimiterBox->setColumnLayout( 0, Qt::Vertical ); + mDelimiterBox->layout()->setSpacing( spacingHint() ); + mDelimiterBox->layout()->setMargin( marginHint() ); + QGridLayout *delimiterLayout = new QGridLayout( mDelimiterBox->layout() ); + delimiterLayout->setAlignment( Qt::AlignTop ); + layout->addMultiCellWidget( mDelimiterBox, 1, 1, 0, 1 ); + + mRadioComma = new QRadioButton( i18n( "Comma" ), mDelimiterBox ); + mRadioComma->setChecked( true ); + delimiterLayout->addWidget( mRadioComma, 0, 0 ); + + mRadioSemicolon = new QRadioButton( i18n( "Semicolon" ), mDelimiterBox ); + delimiterLayout->addWidget( mRadioSemicolon, 0, 1 ); + + mRadioTab = new QRadioButton( i18n( "Tabulator" ), mDelimiterBox ); + delimiterLayout->addWidget( mRadioTab, 1, 0 ); + + mRadioSpace = new QRadioButton( i18n( "Space" ), mDelimiterBox ); + delimiterLayout->addWidget( mRadioSpace, 1, 1 ); + + mRadioOther = new QRadioButton( i18n( "Other" ), mDelimiterBox ); + delimiterLayout->addWidget( mRadioOther, 0, 2 ); + + mDelimiterEdit = new QLineEdit( mDelimiterBox ); + delimiterLayout->addWidget( mDelimiterEdit, 1, 2 ); + + mComboLine = new QComboBox( false, page ); + mComboLine->insertItem( i18n( "1" ) ); + layout->addWidget( mComboLine, 3, 1 ); + + mComboQuote = new QComboBox( false, page ); + mComboQuote->insertItem( i18n( "\"" ), 0 ); + mComboQuote->insertItem( i18n( "'" ), 1 ); + mComboQuote->insertItem( i18n( "None" ), 2 ); + layout->addWidget( mComboQuote, 3, 0 ); + + label = new QLabel( i18n( "Start at line:" ), page ); + layout->addWidget( label, 2, 1 ); + + label = new QLabel( i18n( "Textquote:" ), page ); + layout->addWidget( label, 2, 0 ); + + mIgnoreDuplicates = new QCheckBox( page ); + mIgnoreDuplicates->setText( i18n( "Ignore duplicate delimiters" ) ); + layout->addMultiCellWidget( mIgnoreDuplicates, 4, 4, 0, 1 ); + + mTable = new QTable( 0, 0, page ); + mTable->setSelectionMode( QTable::NoSelection ); + //mTable->horizontalHeader()->hide(); + layout->addMultiCellWidget( mTable, 5, 5, 0, 1 ); +/*US + setButtonText( User1, i18n( "Apply Template" ) ); + setButtonText( User2, i18n( "Save Template" ) ); +*/ + + enableButtonOK( false ); + + findButton( User1 )->setEnabled( false ); + findButton( User2 )->setEnabled( false ); + +#ifdef DESKTOP_VERSION + resize( 500, 300 ); +#else + showMaximized(); +#endif +} + +void CSVImportDialog::fillTable() +{ + int row, column; + bool lastCharDelimiter = false; + bool ignoreDups = mIgnoreDuplicates->isChecked(); + enum { S_START, S_QUOTED_FIELD, S_MAYBE_END_OF_QUOTED_FIELD, S_END_OF_QUOTED_FIELD, + S_MAYBE_NORMAL_FIELD, S_NORMAL_FIELD } state = S_START; + + QChar x; + QString field = ""; + + // store previous assignment + QValueList<int> mTypeOld = mTypeStore; + + mTypeStore.clear(); + for ( column = 0; column < mTable->numCols(); ++column ) { + QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, column ) ); + + if ( !item || mClearTypeStore ) + mTypeStore.append( typeToPos( Undefined ) ); + else if ( item ) + mTypeStore.append( item->currentItem() ); + } + + clearTable(); + + row = column = 1; + mData = QString( mFileArray ); + + QTextStream inputStream( mData, IO_ReadOnly ); + inputStream.setEncoding( QTextStream::Locale ); + + int maxColumn = 0; + while ( !inputStream.atEnd() ) { + inputStream >> x; // read one char + + if ( x == '\r' ) inputStream >> x; // eat '\r', to handle DOS/LOSEDOWS files correctly + + switch ( state ) { + case S_START : + if ( x == mTextQuote ) { + state = S_QUOTED_FIELD; + } else if ( x == mDelimiter ) { + if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) + ++column; + lastCharDelimiter = true; + } else if ( x == '\n' ) { + ++row; + column = 1; + } else { + field += x; + state = S_MAYBE_NORMAL_FIELD; + } + break; + case S_QUOTED_FIELD : + if ( x == mTextQuote ) { + state = S_MAYBE_END_OF_QUOTED_FIELD; + } else if ( x == '\n' ) { + setText( row - mStartLine + 1, column, field ); + field = ""; + if ( x == '\n' ) { + ++row; + column = 1; + } else { + if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } else { + field += x; + } + break; + case S_MAYBE_END_OF_QUOTED_FIELD : + if ( x == mTextQuote ) { + field += x; + state = S_QUOTED_FIELD; + } else if ( x == mDelimiter || x == '\n' ) { + setText( row - mStartLine + 1, column, field ); + field = ""; + if ( x == '\n' ) { + ++row; + column = 1; + } else { + if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } else { + state = S_END_OF_QUOTED_FIELD; + } + break; + case S_END_OF_QUOTED_FIELD : + if ( x == mDelimiter || x == '\n' ) { + setText( row - mStartLine + 1, column, field ); + field = ""; + if ( x == '\n' ) { + ++row; + column = 1; + } else { + if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } else { + state = S_END_OF_QUOTED_FIELD; + } + break; + case S_MAYBE_NORMAL_FIELD : + if ( x == mTextQuote ) { + field = ""; + state = S_QUOTED_FIELD; + break; + } + case S_NORMAL_FIELD : + if ( x == mDelimiter || x == '\n' ) { + setText( row - mStartLine + 1, column, field ); + field = ""; + if ( x == '\n' ) { + ++row; + column = 1; + } else { + if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } else { + field += x; + } + } + if ( x != mDelimiter ) + lastCharDelimiter = false; + + if ( column > maxColumn ) + maxColumn = column; + } + + // file with only one line without '\n' + if ( field.length() > 0 ) { + setText( row - mStartLine + 1, column, field ); + ++row; + field = ""; + } + + adjustRows( row - mStartLine ); + mTable->setNumCols( maxColumn ); + +//US begin + QStringList keys; + QMap<QString, uint>::ConstIterator it; + for ( it = mTypeMap.begin(); it != mTypeMap.end(); ++it) + keys << it.key(); +//US end + + for ( column = 0; column < mTable->numCols(); ++column ) { + +//US QComboTableItem *item = new QComboTableItem( mTable, mTypeMap.keys() ); + QComboTableItem *item = new QComboTableItem( mTable, keys ); + mTable->setItem( 0, column, item ); + if ( column < mTypeStore.count() ) + item->setCurrentItem( mTypeStore[ column ] ); + else + item->setCurrentItem( typeToPos( Undefined ) ); + + mTable->adjustColumn( column ); + } +} + +void CSVImportDialog::clearTable() +{ + for ( int row = 0; row < mTable->numRows(); ++row ) + for ( int column = 0; column < mTable->numCols(); ++column ) + mTable->clearCell( row, column ); +} + +void CSVImportDialog::fillComboBox() +{ + mComboLine->clear(); + for ( int row = 1; row < mTable->numRows() + 1; ++row ) + mComboLine->insertItem( QString::number( row ), row - 1 ); +} + +void CSVImportDialog::setText( int row, int col, const QString& text ) +{ + if ( row < 1 ) // skipped by the user + return; + + if ( mTable->numRows() < row ) { + mTable->setNumRows( row + 5000 ); // We add 5000 at a time to limit recalculations + mAdjustRows = true; + } + + if ( mTable->numCols() < col ) + mTable->setNumCols( col + 50 ); // We add 50 at a time to limit recalculation + + mTable->setText( row - 1, col - 1, text ); +} + +/* + * Called after the first fillTable() when number of rows are unknown. + */ +void CSVImportDialog::adjustRows( int rows ) +{ + if ( mAdjustRows ) { + mTable->setNumRows( rows ); + mAdjustRows = false; + } +} + +void CSVImportDialog::returnPressed() +{ + if ( mDelimiterBox->id( mDelimiterBox->selected() ) != 4 ) + return; + + mDelimiter = mDelimiterEdit->text(); + fillTable(); +} + +void CSVImportDialog::textChanged ( const QString& ) +{ + mRadioOther->setChecked ( true ); + delimiterClicked( 4 ); // other +} + +void CSVImportDialog::delimiterClicked( int id ) +{ + switch ( id ) { + case 0: // comma + mDelimiter = ","; + break; + case 4: // other + mDelimiter = mDelimiterEdit->text(); + break; + case 2: // tab + mDelimiter = "\t"; + break; + case 3: // space + mDelimiter = " "; + break; + case 1: // semicolon + mDelimiter = ";"; + break; + } + + fillTable(); +} + +void CSVImportDialog::textquoteSelected( const QString& mark ) +{ + if ( mComboQuote->currentItem() == 2 ) + mTextQuote = 0; + else + mTextQuote = mark[ 0 ]; + + fillTable(); +} + +void CSVImportDialog::lineSelected( const QString& line ) +{ + mStartLine = line.toInt() - 1; + fillTable(); +} + +void CSVImportDialog::slotOk() +{ + bool assigned = false; + + for ( int column = 0; column < mTable->numCols(); ++column ) { + QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, + column ) ); + if ( item && posToType( item->currentItem() ) != Undefined ) + assigned = true; + } + + if ( assigned ) + KDialogBase::slotOk(); + else + KMessageBox::sorry( this, i18n( "You have to assign at least one column." ) ); +} + +void CSVImportDialog::applyTemplate() +{ + QMap<uint,int> columnMap; + QMap<QString, QString> fileMap; + QStringList templates; + + // load all template files +/*US QStringList list = KGlobal::dirs()->findAllResources( "data" , QString( kapp->name() ) + + "/csv-templates/*.desktop", true, true ); +*/ + QStringList list = KGlobal::dirs()->findAllResources( "data" , KGlobal::getAppName() + + "/csv-templates/*.desktop", true, true ); + + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + { + qDebug("for "); +//US KSimpleConfig config( *it, true ); + KConfig config( *it ); + + if ( !config.hasGroup( "csv column map" ) ) + continue; + + config.setGroup( "Misc" ); + templates.append( config.readEntry( "Name" ) ); + fileMap.insert( config.readEntry( "Name" ), *it ); + } + qDebug("weiter "); + // let the user chose, what to take + bool ok = false; + QString tmp; + tmp = QInputDialog::getItem( i18n( "Template Selection" ), + i18n( "Please select a template, that matches the CSV file." ), + templates, 0, false, &ok, this ); + + if ( !ok ) + return; + +//US KSimpleConfig config( fileMap[ tmp ], true ); + KConfig config( fileMap[ tmp ] ); + config.setGroup( "General" ); +//US uint numColumns = config.readUnsignedNumEntry( "Columns" ); + uint numColumns = (uint)config.readNumEntry( "Columns" ); + + mDelimiterEdit->setText( config.readEntry( "DelimiterOther" ) ); + mDelimiterBox->setButton( config.readNumEntry( "DelimiterType" ) ); + delimiterClicked( config.readNumEntry( "DelimiterType" ) ); + int quoteType = config.readNumEntry( "QuoteType" ); + mComboQuote->setCurrentItem( quoteType ); + textquoteSelected( mComboQuote->currentText() ); + + // create the column map + config.setGroup( "csv column map" ); + for ( uint i = 0; i < numColumns; ++i ) { + int col = config.readNumEntry( QString::number( i ) ); + columnMap.insert( i, col ); + } + + // apply the column map + for ( uint column = 0; column < columnMap.count(); ++column ) { + int type = columnMap[ column ]; + QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, + column ) ); + if ( item ) + item->setCurrentItem( typeToPos( type ) ); + } +} + +void CSVImportDialog::saveTemplate() +{ +/*US + QString fileName = KFileDialog::getSaveFileName( + locateLocal( "data", QString( kapp->name() ) + "/csv-templates/" ), + "*.desktop", this ); +*/ + QString fileName = KFileDialog::getSaveFileName( + locateLocal( "data", KGlobal::getAppName() + "/csv-templates/" )+ + "*.desktop",i18n("Save file name") , this ); + + if ( fileName.isEmpty() ) + return; + + if ( !fileName.contains( ".desktop" ) ) + fileName += ".desktop"; + + QString name = QInputDialog::getText( i18n( "Template name" ), i18n( "Please enter a name for the template" ) ); + + if ( name.isEmpty() ) + return; + + KConfig config( fileName ); + config.setGroup( "General" ); + config.writeEntry( "Columns", mTable->numCols() ); + config.writeEntry( "DelimiterType", mDelimiterBox->id( mDelimiterBox->selected() ) ); + config.writeEntry( "DelimiterOther", mDelimiterEdit->text() ); + config.writeEntry( "QuoteType", mComboQuote->currentItem() ); + + config.setGroup( "Misc" ); + config.writeEntry( "Name", name ); + + config.setGroup( "csv column map" ); + + for ( uint column = 0; column < mTable->numCols(); ++column ) { + QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, + column ) ); + if ( item ) + config.writeEntry( QString::number( column ), posToType( + item->currentItem() ) ); + else + config.writeEntry( QString::number( column ), 0 ); + } + + config.sync(); +} + +QString CSVImportDialog::getText( int row, int col ) +{ + return mTable->text( row, col ); +} + +uint CSVImportDialog::posToType( int pos ) const +{ + uint counter = 0; + QMap<QString, uint>::ConstIterator it; + for ( it = mTypeMap.begin(); it != mTypeMap.end(); ++it, ++counter ) + if ( counter == (uint)pos ) + return it.data(); + + return 0; +} + +int CSVImportDialog::typeToPos( uint type ) const +{ + uint counter = 0; + QMap<QString, uint>::ConstIterator it; + for ( it = mTypeMap.begin(); it != mTypeMap.end(); ++it, ++counter ) + if ( it.data() == type ) + return counter; + + return -1; +} + +void CSVImportDialog::ignoreDuplicatesChanged( int ) +{ + fillTable(); +} + +void CSVImportDialog::setFile( const QString &fileName ) +{ + if ( fileName.isEmpty() ) + return; + + QFile file( fileName ); + if ( !file.open( IO_ReadOnly ) ) { + KMessageBox::sorry( this, i18n( "Cannot open input file!" ) ); + file.close(); + return; + } + + mFileArray = file.readAll(); + file.close(); + + mClearTypeStore = true; + clearTable(); + mTable->setNumCols( 0 ); + mTable->setNumRows( 0 ); + fillTable(); + mClearTypeStore = false; + + fillComboBox(); +} + +void CSVImportDialog::urlChanged( const QString &file ) +{ + bool state = !file.isEmpty(); + + enableButtonOK( state ); + + findButton( User1 )->setEnabled( state ); + findButton( User2 )->setEnabled( state ); + +} + +#ifndef KAB_EMBEDDED +#include <csvimportdialog.moc> +#endif //KAB_EMBEDDED diff --git a/kaddressbook/xxport/csvimportdialog.h b/kaddressbook/xxport/csvimportdialog.h new file mode 100644 index 0000000..545b5f9 --- a/dev/null +++ b/kaddressbook/xxport/csvimportdialog.h @@ -0,0 +1,124 @@ +/* + This file is part of KAddressBook. + Copyright (C) 2003 Tobias Koenig <tokoe@kde.org> + based on the code of KSpread's CSV Import Dialog + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef CSV_IMPORT_DLG_H +#define CSV_IMPORT_DLG_H + +#include <kabc/addressbook.h> +#include <kabc/addresseelist.h> +#include <kdialogbase.h> + +#include <qvaluelist.h> + +class KURLRequester; + +class QButtonGroup; +class QComboBox; +class QCheckBox; +class QLineEdit; +class QPushButton; +class QRadioButton; +class QTable; + +class CSVImportDialog : public KDialogBase +{ + Q_OBJECT + + public: + CSVImportDialog( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ); + ~CSVImportDialog(); + + KABC::AddresseeList contacts() const; + + protected slots: + virtual void slotOk(); + + private slots: + void returnPressed(); + void delimiterClicked( int id ); + void lineSelected( const QString& line ); + void textquoteSelected( const QString& mark ); + void textChanged ( const QString & ); + void ignoreDuplicatesChanged( int ); + void setFile( const QString& ); + void urlChanged( const QString& ); + + void applyTemplate(); + void saveTemplate(); + + private: + enum { Undefined, FormattedName, FamilyName, GivenName, AdditionalName, + Prefix, Suffix, NickName, Birthday, + HomeAddressStreet, HomeAddressLocality, HomeAddressRegion, + HomeAddressPostalCode, HomeAddressCountry, HomeAddressLabel, + BusinessAddressStreet, BusinessAddressLocality, BusinessAddressRegion, + BusinessAddressPostalCode, BusinessAddressCountry, + BusinessAddressLabel, + HomePhone, BusinessPhone, MobilePhone, HomeFax, BusinessFax, CarPhone, + Isdn, Pager, Email, Mailer, Title, Role, Organization, Note, URL + }; + + QTable* mTable; + QButtonGroup* mDelimiterBox; + QRadioButton* mRadioComma; + QRadioButton* mRadioSemicolon; + QRadioButton* mRadioTab; + QRadioButton* mRadioSpace; + QRadioButton* mRadioOther; + QLineEdit* mDelimiterEdit; + QComboBox* mComboLine; + QComboBox* mComboQuote; + QCheckBox* mIgnoreDuplicates; + KURLRequester* mUrlRequester; + + void initGUI(); + void fillTable(); + void clearTable(); + void fillComboBox(); + void setText( int row, int col, const QString& text ); + void adjustRows( int rows ); + QString getText( int row, int col ); + uint posToType( int pos ) const; + int typeToPos( uint type ) const; + + bool mAdjustRows; + int mStartLine; + QChar mTextQuote; + QString mDelimiter; + QString mData; + QByteArray mFileArray; + QMap<QString, uint> mTypeMap; + KABC::AddressBook *mAddressBook; + int mCustomCounter; + bool mClearTypeStore; + QValueList<int> mTypeStore; + +}; + +#endif diff --git a/kaddressbook/xxport/kde2_xxport.cpp b/kaddressbook/xxport/kde2_xxport.cpp new file mode 100644 index 0000000..d5fc075 --- a/dev/null +++ b/kaddressbook/xxport/kde2_xxport.cpp @@ -0,0 +1,116 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qfile.h> + +#include <kdebug.h> +#include <kfiledialog.h> +#ifndef KAB_EMBEDDED +#include <kio/netaccess.h> +#endif //KAB_EMBEDDED +#include <klocale.h> +#include <kmessagebox.h> +#include <kprocess.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kurl.h> + +#include "xxportmanager.h" + +#include "kde2_xxport.h" + +#ifndef KAB_EMBEDDED + +class KDE2XXPortFactory : public XXPortFactory +{ + public: + XXPortObject *xxportObject( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new KDE2XXPort( ab, parent, name ); + } +}; + + +extern "C" +{ + void *init_libkaddrbk_kde2_xxport() + { + return ( new KDE2XXPortFactory() ); + } +} +#endif //KAB_EMBEDDED + + +KDE2XXPort::KDE2XXPort( KABC::AddressBook *ab, QWidget *parent, const char *name ) + : XXPortObject( ab, parent, name ) +{ + createImportAction( i18n( "Import KDE 2 Addressbook..." ) ); +} + +KABC::AddresseeList KDE2XXPort::importContacts( const QString& ) const +{ + QString fileName = locateLocal( "data", "kabc/std.vcf" ); + if ( !QFile::exists( fileName ) ) { + KMessageBox::sorry( parentWidget(), i18n( "<qt>Couldn't find a KDE 2 address book <b>%1</b>.</qt>" ).arg( fileName ) ); + return KABC::AddresseeList(); + } + +#ifndef KAB_EMBEDDED + int result = KMessageBox::questionYesNoCancel( parentWidget(), + i18n( "Override previously imported entries?" ), + i18n( "Import KDE 2 Addressbook" ) ); +#else //KAB_EMBEDDED + int result = KMessageBox::warningYesNoCancel( parentWidget(), + i18n( "Override previously imported entries?" ), + i18n( "Import KDE 2 Addressbook" ) ); +#endif //KAB_EMBEDDED + + if ( !result ) return KABC::AddresseeList(); + + KProcess proc; + + if ( result == KMessageBox::Yes ) { + proc << "kab2kabc"; + proc << "--override"; + } else if ( result == KMessageBox::No ) + proc << "kab2kabc"; + else + kdDebug(5720) << "KAddressBook::importKDE2(): Unknow return value." << endl; + + proc.start( KProcess::Block ); + + addressBook()->load(); + + return KABC::AddresseeList(); +} + +#ifndef KAB_EMBEDDED +#include "kde2_xxport.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/xxport/kde2_xxport.h b/kaddressbook/xxport/kde2_xxport.h new file mode 100644 index 0000000..4fb1d0b --- a/dev/null +++ b/kaddressbook/xxport/kde2_xxport.h @@ -0,0 +1,62 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef KDE2_XXPORT_H +#define KDE2_XXPORT_H + +#include <xxportobject.h> + +class KDE2XXPort : public XXPortObject +{ + Q_OBJECT + + public: + KDE2XXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + + QString identifier() const { return "kde2"; } + + public slots: + KABC::AddresseeList importContacts( const QString &data ) const; +}; + + +#ifdef KAB_EMBEDDED +class KDE2XXPortFactory : public XXPortFactory +{ + public: + XXPortObject *xxportObject( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new KDE2XXPort( ab, parent, name ); + } +}; +#endif //KAB_EMBEDDED + + +#endif diff --git a/kaddressbook/xxport/vcard_xxport.cpp b/kaddressbook/xxport/vcard_xxport.cpp new file mode 100644 index 0000000..dd49a9c --- a/dev/null +++ b/kaddressbook/xxport/vcard_xxport.cpp @@ -0,0 +1,238 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qfile.h> +#include <qtextstream.h> + +#include <kabc/vcardconverter.h> +#include <kfiledialog.h> +#ifndef KAB_EMBEDDED +#include <kio/netaccess.h> +#endif //KAB_EMBEDDED + +#include <klocale.h> +#include <kmessagebox.h> +#include <ktempfile.h> +#include <kurl.h> + +#include "xxportmanager.h" + +#include "vcard_xxport.h" + +#ifndef KAB_EMBEDDED + +class VCardXXPortFactory : public XXPortFactory +{ + public: + XXPortObject *xxportObject( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new VCardXXPort( ab, parent, name ); + } +}; + + +extern "C" +{ + void *init_libkaddrbk_vcard_xxport() + { + return ( new VCardXXPortFactory() ); + } +} +#endif //KAB_EMBEDDED + + +VCardXXPort::VCardXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name ) + : XXPortObject( ab, parent, name ) +{ + createImportAction( i18n( "Import vCard..." ) ); + createExportAction( i18n( "Export vCard 2.1..." ), "v21" ); + createExportAction( i18n( "Export vCard 3.0..." ), "v30" ); +} + +bool VCardXXPort::exportContacts( const KABC::AddresseeList &list, const QString &data ) +{ + QString name; + + if ( list.count() == 1 ) + name = list[ 0 ].givenName() + "_" + list[ 0 ].familyName() + ".vcf"; + else + name = "addressbook.vcf"; + +#ifndef KAB_EMBEDDED + QString fileName = KFileDialog::getSaveFileName( name ); +#else //KAB_EMBEDDED + QString fileName = KFileDialog::getSaveFileName( name, i18n("Save file"), parentWidget() ); +#endif //KAB_EMBEDDED + + if ( fileName.isEmpty() ) + return true; + + QFile outFile( fileName ); + if ( !outFile.open( IO_WriteOnly ) ) { + QString text = i18n( "<qt>Unable to open file <b>%1</b> for export.</qt>" ); + KMessageBox::error( parentWidget(), text.arg( fileName ) ); + return false; + } + + QTextStream t( &outFile ); + t.setEncoding( QTextStream::UnicodeUTF8 ); + + KABC::Addressee::List::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + KABC::VCardConverter converter; + QString vcard; + + KABC::VCardConverter::Version version; + if ( data == "v21" ) + version = KABC::VCardConverter::v2_1; + else + version = KABC::VCardConverter::v3_0; + + converter.addresseeToVCard( *it, vcard, version ); + t << vcard << "\r\n\r\n"; + } + + outFile.close(); + + return true; +} + +KABC::AddresseeList VCardXXPort::importContacts( const QString& ) const +{ + QString fileName; + KABC::AddresseeList addrList; + KURL url; + +#ifndef KAB_EMBEDDED + if ( !XXPortManager::importData.isEmpty() ) + addrList = parseVCard( XXPortManager::importData ); + else { + if ( XXPortManager::importURL.isEmpty() ) + { + url = KFileDialog::getLoadFileName( QString::null, i18n("Select vCard to Import"), parentWidget() ); + } + else + url = XXPortManager::importURL; + + if ( url.isEmpty() ) + return addrList; + + QString caption( i18n( "vCard Import Failed" ) ); + if ( KIO::NetAccess::download( url, fileName ) ) { + QFile file( fileName ); + + file.open( IO_ReadOnly ); + QByteArray rawData = file.readAll(); + file.close(); + + QString data = QString::fromUtf8( rawData.data(), rawData.size() + 1 ); + addrList = parseVCard( data ); + + if ( !url.isLocalFile() ) + KIO::NetAccess::removeTempFile( fileName ); + + } else { + QString text = i18n( "<qt>Unable to access <b>%1</b>.</qt>" ); + KMessageBox::error( parentWidget(), text.arg( url.url() ), caption ); + } + + } + + +#else //KAB_EMBEDDED + + + if ( !XXPortManager::importData.isEmpty() ) + addrList = parseVCard( XXPortManager::importData ); + else { + if ( XXPortManager::importURL.isEmpty() ) + { + fileName = KFileDialog::getOpenFileName( QString::null, i18n("Select vCard to Import"), parentWidget() ); + } + else + { +//US url = XXPortManager::importURL; + qDebug("VCardXXPort::importContacts Urls at the moment not supported"); + } + + if ( url.isEmpty() ) + return addrList; + + QFile file( fileName ); + + file.open( IO_ReadOnly ); + QByteArray rawData = file.readAll(); + file.close(); + + QString data = QString::fromUtf8( rawData.data(), rawData.size() + 1 ); + addrList = parseVCard( data ); + + } +#endif //KAB_EMBEDDED + + return addrList; +} + +KABC::AddresseeList VCardXXPort::parseVCard( const QString &data ) const +{ + KABC::VCardConverter converter; + KABC::AddresseeList addrList; + + uint numVCards = data.contains( "BEGIN:VCARD", false ); + QStringList dataList = QStringList::split( "\r\n\r\n", data ); + + for ( uint i = 0; i < numVCards && i < dataList.count(); ++i ) { + KABC::Addressee addr; + bool ok = false; + + if ( dataList[ i ].contains( "VERSION:3.0" ) ) + ok = converter.vCardToAddressee( dataList[ i ], addr, KABC::VCardConverter::v3_0 ); + else if ( dataList[ i ].contains( "VERSION:2.1" ) ) + ok = converter.vCardToAddressee( dataList[ i ], addr, KABC::VCardConverter::v2_1 ); + else { + KMessageBox::sorry( parentWidget(), i18n( "Not supported vCard version." ) ); + continue; + } + + if ( !addr.isEmpty() && ok ) + addrList.append( addr ); + else { + QString text = i18n( "The selected file does not include a valid vCard. " + "Please check the file and try again." ); + KMessageBox::sorry( parentWidget(), text ); + } + } + + return addrList; +} + +#ifndef KAB_EMBEDDED +#include "vcard_xxport.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/xxport/vcard_xxport.h b/kaddressbook/xxport/vcard_xxport.h new file mode 100644 index 0000000..b9708a9 --- a/dev/null +++ b/kaddressbook/xxport/vcard_xxport.h @@ -0,0 +1,64 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef VCARD_XXPORT_H +#define VCARD_XXPORT_H + +#include <xxportobject.h> + +class VCardXXPort : public XXPortObject +{ + Q_OBJECT + + public: + VCardXXPort( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + + QString identifier() const { return "vcard"; } + + public slots: + bool exportContacts( const KABC::AddresseeList &list, const QString &data ); + KABC::AddresseeList importContacts( const QString &data ) const; + + private: + KABC::AddresseeList parseVCard( const QString &data ) const; +}; + +#ifdef KAB_EMBEDDED +class VCardXXPortFactory : public XXPortFactory +{ + public: + XXPortObject *xxportObject( KABC::AddressBook *ab, QWidget *parent, const char *name ) + { + return new VCardXXPort( ab, parent, name ); + } +}; +#endif //KAB_EMBEDDED + +#endif diff --git a/kaddressbook/xxportmanager.cpp b/kaddressbook/xxportmanager.cpp new file mode 100644 index 0000000..6cfa9cb --- a/dev/null +++ b/kaddressbook/xxportmanager.cpp @@ -0,0 +1,269 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qlayout.h> + +#include <kabc/addressbook.h> +#include <kabc/resource.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <klocale.h> +#include <kmessagebox.h> + +#ifndef KAB_EMBEDDED +#include <ktrader.h> +#else //KAB_EMBEDDED +#include "xxport/csv_xxport.h" +#include "xxport/kde2_xxport.h" +#include "xxport/vcard_xxport.h" +#endif //KAB_EMBEDDED + +#include <libkdepim/addresseeview.h> + +#include "kabcore.h" +#include "undocmds.h" +#include "xxportselectdialog.h" + +#include "xxportmanager.h" + +KURL XXPortManager::importURL = KURL(); +QString XXPortManager::importData = QString::null; + +class PreviewDialog : public KDialogBase +{ + public: + PreviewDialog( const KABC::Addressee &addr, + QWidget *parent, const char *name = 0 ); +}; + +XXPortManager::XXPortManager( KABCore *core, QObject *parent, const char *name ) + : QObject( parent, name ), mCore( core ), mShowPreview( false ) +{ + loadPlugins(); +} + +XXPortManager::~XXPortManager() +{ +} + +void XXPortManager::restoreSettings() +{ +} + +void XXPortManager::saveSettings() +{ +} + +void XXPortManager::importVCard( const KURL &url ) +{ + importVCard( url, false ); +} + +void XXPortManager::importVCard( const KURL &url, bool showPreview ) +{ + importURL = url; + mShowPreview = showPreview; + slotImport( "vcard", "<empty>" ); + mShowPreview = false; + importURL = KURL(); +} + +void XXPortManager::importVCard( const QString &vCard, bool showPreview ) +{ + importData = vCard; + mShowPreview = showPreview; + slotImport( "vcard", "<empty>" ); + mShowPreview = false; + importData = ""; +} + +void XXPortManager::slotImport( const QString &identifier, const QString &data ) +{ + XXPortObject *obj = mXXPortObjects[ identifier ]; + if ( !obj ) { + KMessageBox::error( mCore, i18n( "<qt>No import plugin available for <b>%1</b>.</qt>" ).arg( identifier ) ); + return; + } + + KABC::Resource *resource = mCore->requestResource( mCore ); + if ( !resource ) + return; + + KABC::AddresseeList list = obj->importContacts( data ); + KABC::AddresseeList::Iterator it; + bool imported = false; + for ( it = list.begin(); it != list.end(); ++it ) { + if ( mShowPreview ) { + PreviewDialog dlg( *it, mCore ); + if ( !dlg.exec() ) + continue; + } + + (*it).setResource( resource ); + // We use a PwNewCommand so the user can undo it. + PwNewCommand *command = new PwNewCommand( mCore->addressBook(), *it ); + UndoStack::instance()->push( command ); + RedoStack::instance()->clear(); + imported = true; + } + + if ( imported ) { + KMessageBox::information( mCore, i18n( "contacts successfully imported." ) ); + + emit modified(); + } +} + +void XXPortManager::slotExport( const QString &identifier, const QString &data ) +{ + XXPortObject *obj = mXXPortObjects[ identifier ]; + if ( !obj ) { + KMessageBox::error( mCore, i18n( "<qt>No export plugin available for <b>%1</b>.</qt>" ).arg( identifier ) ); + return; + } + + KABC::AddresseeList addrList; + XXPortSelectDialog dlg( mCore, obj->requiresSorting(), mCore ); + if ( dlg.exec() ) + addrList = dlg.contacts(); + else + return; + + if ( !obj->exportContacts( addrList, data ) ) + KMessageBox::error( mCore, i18n( "Unable to export contacts." ) ); + else + KMessageBox::information( mCore, i18n( "contacts successfully exported." ) ); +} + +void XXPortManager::loadPlugins() +{ + mXXPortObjects.clear(); + +#ifndef KAB_EMBEDDED + KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/XXPort" ); + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + if ( !(*it)->hasServiceType( "KAddressBook/XXPort" ) ) + continue; + + KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().latin1() ); + if ( !factory ) { + kdDebug(5720) << "XXPortManager::loadExtensions(): Factory creation failed" << endl; + continue; + } + + XXPortFactory *xxportFactory = static_cast<XXPortFactory*>( factory ); + + if ( !xxportFactory ) { + kdDebug(5720) << "XXPortManager::loadExtensions(): Cast failed" << endl; + continue; + } + + XXPortObject *obj = xxportFactory->xxportObject( mCore->addressBook(), mCore ); + if ( obj ) { + mCore->addGUIClient( obj ); + mXXPortObjects.insert( obj->identifier(), obj ); + connect( obj, SIGNAL( exportActivated( const QString&, const QString& ) ), + this, SLOT( slotExport( const QString&, const QString& ) ) ); + connect( obj, SIGNAL( importActivated( const QString&, const QString& ) ), + this, SLOT( slotImport( const QString&, const QString& ) ) ); + } + } + +#else //KAB_EMBEDDED +//lets load the export/import stubs directly. Is dynamic loading necessary for KA/Pi? + + // CVS import/export + XXPortFactory *xxportFactory = new CSVXXPortFactory(); + + XXPortObject *obj = xxportFactory->xxportObject( mCore->addressBook(), mCore ); + if ( obj ) { + mCore->addGUIClient( obj ); + mXXPortObjects.insert( obj->identifier(), obj ); + connect( obj, SIGNAL( exportActivated( const QString&, const QString& ) ), + this, SLOT( slotExport( const QString&, const QString& ) ) ); + connect( obj, SIGNAL( importActivated( const QString&, const QString& ) ), + this, SLOT( slotImport( const QString&, const QString& ) ) ); + } + + + + // KDE2 import/export + xxportFactory = new KDE2XXPortFactory(); + + obj = xxportFactory->xxportObject( mCore->addressBook(), mCore ); + if ( obj ) { + mCore->addGUIClient( obj ); + mXXPortObjects.insert( obj->identifier(), obj ); + connect( obj, SIGNAL( exportActivated( const QString&, const QString& ) ), + this, SLOT( slotExport( const QString&, const QString& ) ) ); + connect( obj, SIGNAL( importActivated( const QString&, const QString& ) ), + this, SLOT( slotImport( const QString&, const QString& ) ) ); + } + + + + // VCARD import/export + xxportFactory = new VCardXXPortFactory(); + + obj = xxportFactory->xxportObject( mCore->addressBook(), mCore ); + if ( obj ) { + mCore->addGUIClient( obj ); + mXXPortObjects.insert( obj->identifier(), obj ); + connect( obj, SIGNAL( exportActivated( const QString&, const QString& ) ), + this, SLOT( slotExport( const QString&, const QString& ) ) ); + connect( obj, SIGNAL( importActivated( const QString&, const QString& ) ), + this, SLOT( slotImport( const QString&, const QString& ) ) ); + } +#endif //KAB_EMBEDDED + +} + + +PreviewDialog::PreviewDialog( const KABC::Addressee &addr, QWidget *parent, + const char *name ) + : KDialogBase( Plain, i18n( "Contact Preview" ), Ok | Cancel, Ok, parent, + name, true, true ) +{ + QWidget *page = plainPage(); + QVBoxLayout *layout = new QVBoxLayout( page, marginHint(), spacingHint() ); + + KPIM::AddresseeView *view = new KPIM::AddresseeView( page ); + view->setAddressee( addr ); + + layout->addWidget( view ); + + resize( 400, 300 ); +} + +#ifndef KAB_EMBEDDED +#include "xxportmanager.moc" +#endif //KAB_EMBEDDED + diff --git a/kaddressbook/xxportmanager.h b/kaddressbook/xxportmanager.h new file mode 100644 index 0000000..f8436ed --- a/dev/null +++ b/kaddressbook/xxportmanager.h @@ -0,0 +1,79 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + + +#ifndef XXPORTMANAGER_H +#define XXPORTMANAGER_H + +#include <qdict.h> +#include <qobject.h> + +#include <kurl.h> + +#include "xxportobject.h" + +class KABCore; + +class XXPortManager : public QObject +{ + Q_OBJECT + + public: + XXPortManager( KABCore *core, QObject *parent, const char *name = 0 ); + ~XXPortManager(); + + void restoreSettings(); + void saveSettings(); + + static KURL importURL; + static QString importData; + + public slots: + void importVCard( const KURL &url ); + void importVCard( const KURL &url, bool showPreview ); + void importVCard( const QString &vCard, bool showPreview ); + + signals: + void modified(); + + protected slots: + void slotImport( const QString&, const QString& ); + void slotExport( const QString&, const QString& ); + + private: + void loadPlugins(); + + QDict<XXPortObject> mXXPortObjects; + + KABCore *mCore; + bool mShowPreview; +}; + +#endif diff --git a/kaddressbook/xxportobject.cpp b/kaddressbook/xxportobject.cpp new file mode 100644 index 0000000..42ab0fb --- a/dev/null +++ b/kaddressbook/xxportobject.cpp @@ -0,0 +1,152 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <qmap.h> +#include <qsignalmapper.h> + +#include <kaction.h> +#include <kmessagebox.h> + +#include "kabcore.h" + +#include "xxportobject.h" + +class XXPortObject::XXPortObjectPrivate +{ + public: + QSignalMapper *mExportMapper; + QSignalMapper *mImportMapper; +}; + +XXPortObject::XXPortObject( KABC::AddressBook *ab, QWidget *parent, + const char *name ) + : QObject( parent, name ), mAddressBook( ab ), mParentWidget( parent ), + d( new XXPortObjectPrivate ) +{ + d->mExportMapper = new QSignalMapper( this ); + d->mImportMapper = new QSignalMapper( this ); + + connect( d->mExportMapper, SIGNAL( mapped( const QString& ) ), + SLOT( slotExportActivated( const QString& ) ) ); + connect( d->mImportMapper, SIGNAL( mapped( const QString& ) ), + SLOT( slotImportActivated( const QString& ) ) ); +} + +XXPortObject::~XXPortObject() +{ + delete d; + d = 0; +} + +bool XXPortObject::exportContacts( const KABC::AddresseeList&, const QString& ) +{ + // do nothing + return false; +} + +KABC::AddresseeList XXPortObject::importContacts( const QString& ) const +{ + // do nothing + return KABC::AddresseeList(); +} + +void XXPortObject::createImportAction( const QString &label, const QString &data ) +{ +#ifdef KAB_EMBEDDED + KABCore* kabcore = (KABCore*)mParentWidget; +#endif //KAB_EMBEDDED + + QString id = "file_import_" + identifier() + ( data.isEmpty() ? QString( "" ) : "_" + data ); +#ifndef KAB_EMBEDDED + KAction *action = new KAction( label, 0, d->mImportMapper, SLOT( map() ), actionCollection(), id.latin1() ); +#else //KAB_EMBEDDED + KAction *action = new KAction( label, 0, d->mImportMapper, SLOT( map() ), kabcore->actionCollection(), id.latin1() ); +#endif //KAB_EMBEDDED + + d->mImportMapper->setMapping( action, ( data.isEmpty() ? QString( "<empty>" ) : data ) ); + +#ifndef KAB_EMBEDDED + setXMLFile( identifier() + "_xxportui.rc" ); +#endif //KAB_EMBEDDED + +#ifdef KAB_EMBEDDED + action->plug((QWidget*)kabcore->getImportMenu()); +#endif //KAB_EMBEDDED + +} + +void XXPortObject::createExportAction( const QString &label, const QString &data ) +{ +#ifdef KAB_EMBEDDED + KABCore* kabcore = (KABCore*)mParentWidget; +#endif //KAB_EMBEDDED + + QString id = "file_export_" + identifier() + ( data.isEmpty() ? QString( "" ) : "_" + data ); +#ifndef KAB_EMBEDDED + KAction *action = new KAction( label, 0, d->mExportMapper, SLOT( map() ), actionCollection(), id.latin1() ); +#else //KAB_EMBEDDED + KAction *action = new KAction( label, 0, d->mExportMapper, SLOT( map() ), kabcore->actionCollection(), id.latin1() ); +#endif //KAB_EMBEDDED + + d->mExportMapper->setMapping( action, ( data.isEmpty() ? QString( "<empty>" ) : data ) ); + +#ifndef KAB_EMBEDDED + setXMLFile( identifier() + "_xxportui.rc" ); +#endif //KAB_EMBEDDED + +#ifdef KAB_EMBEDDED + action->plug((QWidget*)kabcore->getExportMenu()); +#endif //KAB_EMBEDDED + +} + +KABC::AddressBook *XXPortObject::addressBook() const +{ + return mAddressBook; +} + +QWidget *XXPortObject::parentWidget() const +{ + return mParentWidget; +} + +void XXPortObject::slotExportActivated( const QString &data ) +{ + emit exportActivated( identifier(), ( data == "<empty>" ? QString::null : data ) ); +} + +void XXPortObject::slotImportActivated( const QString &data ) +{ + emit importActivated( identifier(), ( data == "<empty>" ? QString::null : data ) ); +} + +#ifndef KAB_EMBEDDED +#include "xxportobject.moc" +#endif //KAB_EMBEDDED diff --git a/kaddressbook/xxportobject.h b/kaddressbook/xxportobject.h new file mode 100644 index 0000000..d697700 --- a/dev/null +++ b/kaddressbook/xxportobject.h @@ -0,0 +1,157 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#ifndef XXPORTOBJECT_H +#define XXPORTOBJECT_H + +#include <qobject.h> + +#include <kabc/addressbook.h> +#include <kabc/addresseelist.h> +#include <kxmlguiclient.h> +#ifndef KAB_EMBEDDED +#include <klibloader.h> +#endif //KAB_EMBEDDED + + +class XXPortObject : public QObject, virtual public KXMLGUIClient +{ + Q_OBJECT + + public: + XXPortObject( KABC::AddressBook *ab, QWidget *parent, const char *name = 0 ); + ~XXPortObject(); + + /** + Returns the unique identifier of this xxport modul, it should + be the lowercase name of the import/export format e.g. 'vcard' + */ + virtual QString identifier() const = 0; + + /** + Reimplement this method if the XXPortManager shall + pass a sorted list to @ref exportContacts(). + */ + virtual bool requiresSorting() const { return false; } + + public slots: + /** + Reimplement this method for exporting the contacts. + */ + virtual bool exportContacts( const KABC::AddresseeList &list, const QString& identifier ); + + /** + Reimplement this method for importing the contacts. + */ + virtual KABC::AddresseeList importContacts( const QString& identifier ) const; + + signals: + /** + Emitted whenever the export action is activated. + The parameter contains the @ref identifier() for + unique identification. + */ + void exportActivated( const QString&, const QString& ); + + /** + Emitted whenever the import action is activated. + The parameter contains the @ref identifier() for + unique identification. + */ + void importActivated( const QString&, const QString& ); + + protected: + /** + Create the import action. The identifier is passed in the import slot. + */ + void createImportAction( const QString &label, const QString &identifier = QString::null ); + + /** + Create the export action. The identifier is passed in the export slot. + */ + void createExportAction( const QString &label, const QString &identifier = QString::null ); + + /** + Returns a pointer to the address book object. + */ + KABC::AddressBook *addressBook() const; + + /** + Returns a pointer to the parent widget. It can be used as parent for + message boxes. + */ + QWidget *parentWidget() const; + + + private slots: + void slotImportActivated( const QString& ); + void slotExportActivated( const QString& ); + + private: + KABC::AddressBook *mAddressBook; + QWidget *mParentWidget; + + class XXPortObjectPrivate; + XXPortObjectPrivate *d; +}; + +#ifndef KAB_EMBEDDED +class XXPortFactory : public KLibFactory +{ + public: + virtual XXPortObject *xxportObject( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ) = 0; + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } +}; + +#else //KAB_EMBEDDED +class XXPortFactory +{ + public: + virtual XXPortObject *xxportObject( KABC::AddressBook *ab, QWidget *parent, + const char *name = 0 ) = 0; + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } +}; +#endif //KAB_EMBEDDED + + +#endif diff --git a/kaddressbook/xxportselectdialog.cpp b/kaddressbook/xxportselectdialog.cpp new file mode 100644 index 0000000..e0da3b2 --- a/dev/null +++ b/kaddressbook/xxportselectdialog.cpp @@ -0,0 +1,279 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk> + Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +/* +Enhanced Version of the file for platform independent KDE tools. +Copyright (c) 2004 Ulf Schenk + +$Id$ +*/ + +#include <kabc/addressbook.h> +#include <kapplication.h> +#include <kcombobox.h> +#include <klocale.h> +#include <kglobal.h> + +#include <qbuttongroup.h> +#include <qcombobox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qstringlist.h> +#include <qwhatsthis.h> + +#include "kabcore.h" +#include "kabprefs.h" + +#include "xxportselectdialog.h" + +XXPortSelectDialog::XXPortSelectDialog( KABCore *core, bool sort, + QWidget* parent, const char* name ) + : KDialogBase( Plain, i18n( "Choose which contacts to export" ), Help | Ok | Cancel, + Ok, parent, name, true, true ), mCore( core ), + mUseSorting( sort ) +{ + initGUI(); + + connect( mFiltersCombo, SIGNAL( activated( int ) ), + SLOT( filterChanged( int ) ) ); + connect( mCategoriesView, SIGNAL( clicked( QListViewItem* ) ), + SLOT( categoryClicked( QListViewItem* ) ) ); + + // setup filters +#ifndef KAB_EMBEDDED + mFilters = Filter::restore( kapp->config(), "Filter" ); + Filter::List::iterator filterIt; +#else //KAB_EMBEDDED + mFilters = Filter::restore( KGlobal::config(), "Filter" ); + Filter::List::Iterator filterIt; +#endif //KAB_EMBEDDED + QStringList filters; + for ( filterIt = mFilters.begin(); filterIt != mFilters.end(); ++filterIt ) + filters.append( (*filterIt).name() ); + + mFiltersCombo->insertStringList( filters ); + mUseFilters->setEnabled( filters.count() > 0 ); + + // setup categories + QStringList categories = KABPrefs::instance()->mCustomCategories; + QStringList::Iterator it; + for ( it = categories.begin(); it != categories.end(); ++it ) + new QCheckListItem( mCategoriesView, *it, QCheckListItem::CheckBox ); + mUseCategories->setEnabled( categories.count() > 0 ); + + int count = mCore->selectedUIDs().count(); + mUseSelection->setEnabled( count != 0 ); + mUseSelection->setChecked( count > 1 ); + + mSortTypeCombo->insertItem( i18n( "Ascending" ) ); + mSortTypeCombo->insertItem( i18n( "Descending" ) ); + + mFields = mCore->addressBook()->fields( KABC::Field::All ); + KABC::Field::List::Iterator fieldIt; + for ( fieldIt = mFields.begin(); fieldIt != mFields.end(); ++fieldIt ) + mFieldCombo->insertItem( (*fieldIt)->label() ); +} + +KABC::AddresseeList XXPortSelectDialog::contacts() +{ + QStringList selection = mCore->selectedUIDs(); + + KABC::AddresseeList list; + if ( mUseSelection->isChecked() ) { + QStringList::Iterator it; + for ( it = selection.begin(); it != selection.end(); ++it ) { + KABC::Addressee addr = mCore->addressBook()->findByUid( *it ); + if ( !addr.isEmpty() ) + list.append( addr ); + } + } else if ( mUseFilters->isChecked() ) { + // find contacts that can pass selected filter + Filter::List::Iterator filterIt; + for ( filterIt = mFilters.begin(); filterIt != mFilters.end(); ++filterIt ) + if ( (*filterIt).name() == mFiltersCombo->currentText() ) + break; + + KABC::AddressBook::Iterator it; + for ( it = mCore->addressBook()->begin(); it != mCore->addressBook()->end(); ++it ) { + if ( (*filterIt).filterAddressee( *it ) ) + list.append( *it ); + } + } else if ( mUseCategories->isChecked() ) { + QStringList categorieList = categories(); + KABC::AddressBook::Iterator it; + for ( it = mCore->addressBook()->begin(); it != mCore->addressBook()->end(); ++it ) { + QStringList tmp( (*it).categories() ); + QStringList::Iterator tmpIt; + for ( tmpIt = tmp.begin(); tmpIt != tmp.end(); ++tmpIt ) + if ( categorieList.contains( *tmpIt ) ) { + list.append( *it ); + break; + } + } + } else { + // create a string list of all entries: + KABC::AddressBook::Iterator it; + for ( it = mCore->addressBook()->begin(); it != mCore->addressBook()->end(); ++it ) + list.append( *it ); + } + + if ( mUseSorting ) { + list.setReverseSorting( mSortTypeCombo->currentItem() == 1 ); + uint pos = mFieldCombo->currentItem(); + if ( pos < mFields.count() ) + list.sortByField( mFields[ pos ] ); + } + + return list; +} + +QStringList XXPortSelectDialog::categories() const +{ + QStringList list; + + QListViewItemIterator it( mCategoriesView ); + for ( ; it.current(); ++it ) { + QCheckListItem* qcli = static_cast<QCheckListItem*>(it.current()); + if ( qcli->isOn() ) + list.append( it.current()->text( 0 ) ); + } + + return list; +} + +void XXPortSelectDialog::filterChanged( int ) +{ + mUseFilters->setChecked( true ); +} + +void XXPortSelectDialog::categoryClicked( QListViewItem *i ) +{ + QCheckListItem *qcli = static_cast<QCheckListItem*>( i ); + if ( qcli->isOn() ) + mUseCategories->setChecked( true ); +} + +void XXPortSelectDialog::slotHelp() +{ +#ifndef KAB_EMBEDDED + kapp->invokeHelp( "import-and-export" ); +#else //KAB_EMBEDDED + qDebug("XXPortSelectDialog::slotHelp is not implemented yet"); +#endif //KAB_EMBEDDED + +} + +void XXPortSelectDialog::initGUI() +{ + QFrame *page = plainPage(); + + QVBoxLayout *topLayout = new QVBoxLayout( page, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *label = new QLabel( i18n( "Which contacts do you want to export?" ), page ); + topLayout->addWidget( label ); + + mButtonGroup = new QButtonGroup( i18n( "Selection" ), page ); + mButtonGroup->setColumnLayout( 0, Qt::Vertical ); + mButtonGroup->layout()->setSpacing( KDialog::spacingHint() ); + mButtonGroup->layout()->setMargin( KDialog::marginHint() ); + + QGridLayout *groupLayout = new QGridLayout( mButtonGroup->layout() ); + groupLayout->setAlignment( Qt::AlignTop ); + + mUseWholeBook = new QRadioButton( i18n( "&All contacts" ), mButtonGroup ); + mUseWholeBook->setChecked( true ); + QWhatsThis::add( mUseWholeBook, i18n( "Export the entire address book" ) ); + groupLayout->addWidget( mUseWholeBook, 0, 0 ); + + mUseSelection = new QRadioButton( i18n( "&Selected contacts" ), mButtonGroup ); + QWhatsThis::add( mUseSelection, i18n( "Only export contacts selected in KAddressBook.\n" + "This option is disabled if no contacts are selected." ) ); + groupLayout->addWidget( mUseSelection, 1, 0 ); + + mUseFilters = new QRadioButton( i18n( "Contacts matching &filter" ), mButtonGroup ); + QWhatsThis::add( mUseFilters, i18n( "Only export contacts matching the selected filter.\n" + "This option is disabled if you haven't defined any filters" ) ); + groupLayout->addWidget( mUseFilters, 2, 0 ); + + mUseCategories = new QRadioButton( i18n( "Category &members" ), mButtonGroup ); + QWhatsThis::add( mUseCategories, i18n( "Only export contacts who are members of a category that is checked on the list to the left.\n" + "This option is disabled if you have no categories." ) ); + groupLayout->addWidget( mUseCategories, 3, 0 ); + + mFiltersCombo = new QComboBox( false, mButtonGroup ); + QWhatsThis::add( mFiltersCombo, i18n( "Select a filter to decide which contacts to export." ) ); + groupLayout->addWidget( mFiltersCombo, 2, 1 ); + + mCategoriesView = new QListView( mButtonGroup ); + mCategoriesView->addColumn( "" ); + mCategoriesView->header()->hide(); + QWhatsThis::add( mCategoriesView, i18n( "Check the categories whose members you want to export." ) ); + groupLayout->addWidget( mCategoriesView, 3, 1 ); + + topLayout->addWidget( mButtonGroup ); + + QButtonGroup *sortingGroup = new QButtonGroup( i18n( "Sorting" ), page ); + sortingGroup->setColumnLayout( 0, Qt::Vertical ); + QGridLayout *sortLayout = new QGridLayout( sortingGroup->layout(), 2, 2, + KDialog::spacingHint() ); + sortLayout->setAlignment( Qt::AlignTop ); + + label = new QLabel( i18n( "Criterion:" ), sortingGroup ); + sortLayout->addWidget( label, 0, 0 ); + +#ifndef KAB_EMBEDDED + mFieldCombo = new KComboBox( false, sortingGroup ); +#else //KAB_EMBEDDED + //US Combobox is not editable anyway + mFieldCombo = new KComboBox( sortingGroup ); +#endif //KAB_EMBEDDED + sortLayout->addWidget( mFieldCombo, 0, 1 ); + + label = new QLabel( i18n( "Order:" ), sortingGroup ); + sortLayout->addWidget( label, 1, 0 ); + +#ifndef KAB_EMBEDDED + mSortTypeCombo = new KComboBox( false, sortingGroup ); +#else //KAB_EMBEDDED + //US Combobox is not editable anyway + mSortTypeCombo = new KComboBox( sortingGroup ); +#endif //KAB_EMBEDDED + sortLayout->addWidget( mSortTypeCombo, 1, 1 ); + + topLayout->addWidget( sortingGroup ); + + if ( !mUseSorting ) + sortingGroup->hide(); +} + +#ifndef KAB_EMBEDDED +#include "xxportselectdialog.moc" +#endif //KAB_EMBEDDED + + diff --git a/kaddressbook/xxportselectdialog.h b/kaddressbook/xxportselectdialog.h new file mode 100644 index 0000000..8d56f66 --- a/dev/null +++ b/kaddressbook/xxportselectdialog.h @@ -0,0 +1,81 @@ +/* + This file is part of KAddressBook. + Copyright (c) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk> + Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef XXPORTSELECTDIALOG_H +#define XXPORTSELECTDIALOG_H + +#include <kabc/addresseelist.h> +#include <kabc/field.h> +#include <kdialogbase.h> + +#include "filter.h" + +class QButtonGroup; +class QComboBox; +class QListView; +class QListViewItem; +class QRadioButton; + +class KABCore; +class KComboBox; + +class XXPortSelectDialog : public KDialogBase +{ + Q_OBJECT + + public: + XXPortSelectDialog( KABCore *core, bool sort, QWidget* parent, + const char* name = 0 ); + + KABC::AddresseeList contacts(); + + private slots: + void filterChanged( int ); + void categoryClicked( QListViewItem * i ); + + protected slots: + void slotHelp(); + + private: + void initGUI(); + QStringList categories() const; + + QButtonGroup* mButtonGroup; + QRadioButton* mUseCategories; + QRadioButton* mUseFilters; + QRadioButton* mUseWholeBook; + QRadioButton* mUseSelection; + QComboBox* mFiltersCombo; + QListView* mCategoriesView; + + KComboBox *mFieldCombo; + KComboBox *mSortTypeCombo; + + KABCore *mCore; + KABC::AddresseeList mAddresseeList; + Filter::List mFilters; + KABC::Field::List mFields; + bool mUseSorting; +}; + +#endif diff --git a/kalarmd/alarmdialog.cpp b/kalarmd/alarmdialog.cpp new file mode 100644 index 0000000..b82724f --- a/dev/null +++ b/kalarmd/alarmdialog.cpp @@ -0,0 +1,259 @@ +/* + This file is part of the KDE alarm daemon. + Copyright (c) 2000 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +// $Id$ + +#include <qhbox.h> +#include <qvbox.h> +#include <qapp.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qfile.h> +#include <qtimer.h> +#include <qsound.h> +#include <qpushbutton.h> +#include <qspinbox.h> +#include <stdlib.h> +#ifndef _WIN32_ +#include <unistd.h> +#include <sys/ioctl.h> +#endif +#include <stdio.h> +#include <fcntl.h> + +#ifndef DESKTOP_VERSION +#include <qtopia/alarmserver.h> +#include <qpe/resource.h> +#include <qtopia/sound.h> +#endif + +#include "alarmdialog.h" +#include "alarmdialog.moc" + + +AlarmDialog::AlarmDialog(QWidget *parent,const char *name) + : QDialog (parent, name, true, Qt::WStyle_StaysOnTop ) +{ + setCaption( "KO/Pi Alarm!" ); + QVBoxLayout* layout = new QVBoxLayout( this); + QLabel* l = new QLabel("The following event triggered alarm:",this); + layout->addWidget ( l ); + l->setAlignment( AlignCenter); + mMessage = new QLabel ( " ", this ); + int fs = 18; + int fs2 = 12; + if ( QApplication::desktop()->width() < 480 ) { + setMaximumSize(220, 260); + fs2 = 10; + } + else { + setMaximumSize(440, 440); + } + layout->setSpacing( 3 ); + layout->setMargin( 3 ); + + l->setFont( QFont("helvetica",fs2, QFont::Bold) ); + mMessage->setFont( QFont("helvetica",fs, QFont::Bold) ); + mMessage->setAlignment( AlignCenter); + l = new QLabel("Missed Alarms:",this); + l->setAlignment( AlignCenter); + layout->addWidget ( mMessage ); + layout->addWidget ( l ); + mMissedAlarms= new QLabel ( "", this ); + mMissedAlarms->setAlignment( AlignCenter); + + playSoundTimer = new QTimer( this ); + connect ( playSoundTimer, SIGNAL( timeout() ), this, SLOT (playSound() ) ); + + playSoundTimer->stop(); + + layout->addWidget ( mMissedAlarms ); + QHBox *suspendBox = new QHBox( this ); + suspendBox->setSpacing(3); + layout->addWidget ( suspendBox ); + (void)new QLabel("Suspend duration (minutes):",suspendBox); + mSuspendSpin = new QSpinBox(1,1440,1,suspendBox); + mSuspendSpin->setValue(7); // default suspend duration + QHBox * bbox = new QHBox ( this ); + layout->addWidget ( bbox ); + bbox->layout()->setSpacing( 5 ); + QPushButton* suspend = new QPushButton( "Suspend", bbox); + QPushButton* silen = new QPushButton( " Stop sound ", bbox); + QPushButton* okbut = new QPushButton( "Ok", bbox); + connect (silen , SIGNAL( clicked() ), this, SLOT (silent() ) ); + connect (suspend , SIGNAL( clicked() ), this, SLOT (slotSuspend() ) ); + connect (okbut , SIGNAL( clicked() ), this, SLOT (slotOk() ) ); +#ifndef _WIN32_ + if ( QFile::exists ( "/dev/sharp_led" ) ) + fd_led = open ( "/dev/sharp_led", O_RDWR|O_NONBLOCK ); + else +#endif + fd_led = 0; + statusLED.which = SHARP_LED_SALARM; + mSilent = false; + mSuspendCounter = 0; + setServerNotification( true ); +} +void AlarmDialog::reject () +{ + QTimer::singleShot ( 3000, this, SLOT (suspend()) ); + slotSuspend(); +} +AlarmDialog::~AlarmDialog() +{ +} +void AlarmDialog::silent () +{ + mSilent = true; +} +void AlarmDialog::accept() +{ + slotOk(); +} + +void AlarmDialog::suspend() +{ +#ifdef DESKTOP_VERSION + +#else + Sound::soundAlarm (); +#endif +} +void AlarmDialog::slotOk() +{ + mStopAlarm = true; + mMissedAlarms->setText(""); + mMessage->setText(""); +#ifndef _WIN32_ + if ( fd_led > 0 ) { + statusLED.status = LED_SALARM_OFF ; + ioctl (fd_led, SHARP_LED_SETSTATUS, &statusLED); + } +#endif + QDialog::accept(); +} + +void AlarmDialog::slotSuspend() +{ + //qDebug("AlarmDialog::suspend() "); // emit suspendSignal(mSuspendSpin->value()); + mStopAlarm = true; + QDateTime nextA = QDateTime::currentDateTime().addSecs( mSuspendSpin->value() * 60 ); + QString mess = "suspend_alarm" +mFileName+"+++" ; + if ( mMessage->text().left( 10 ) !="Suspended:" ) + mess += "Suspended:\n"; + mess +=mMessage->text(); +#ifndef DESKTOP_VERSION + if ( mServerNotification ) + AlarmServer::addAlarm ( nextA,"koalarm",mess.latin1()); +#endif + emit addAlarm( nextA , mess ); + slotOk(); +} + +void AlarmDialog::setServerNotification( bool b ) +{ + mServerNotification = b; +} +int AlarmDialog::getSuspendTime( ) +{ + return mSuspendSpin->value(); + +} +void AlarmDialog::setSuspendTime( int val ) +{ + mSuspendSpin->setValue( val ); +} +bool AlarmDialog::eventNotification( QString mess, int replay , QString fn, bool playwav, int pause , int suspendtimes) +{ + if ( mess.left( 9) != "Suspended" ) + mSuspendCounter = suspendtimes; + mPauseCount = pause; + mFileName = fn; + mPlayWav = playwav; + if ( !QFile::exists( fn ) ) + mFileName = ""; + alarmCounter = 0 ; + maxAlarmReplay = replay ; + mStopAlarm = false; + mSilent = false; + if ( mMissedAlarms->text() == "" ) + mMissedAlarms->setText( mMessage->text()); + else + mMissedAlarms->setText( mMessage->text()+ "\n" + mMissedAlarms->text() ); + if ( mMissedAlarms->text().length() > 180 ) + mMissedAlarms->setText(mMissedAlarms->text().left ( 180 )); + mMessage->setText(mess); + int w =sizeHint().width() ; + int h = sizeHint().height() ; + int dw = QApplication::desktop()->width(); + int dh = QApplication::desktop()->height(); + setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); + show(); + raise(); + qApp->processEvents(); + repaint(); + qApp->processEvents(); + +#ifndef _WIN32_ + if ( fd_led > 0 ) { + statusLED.status = LED_SALARM_ON ; + ioctl (fd_led, SHARP_LED_SETSTATUS, &statusLED); + } +#endif + playSoundTimer->start( 1000, true ); + return true; + +} + + +void AlarmDialog::playSound () +{ + if (mStopAlarm ) + return; + showNormal(); + setActiveWindow(); + setFocus(); + raise(); + + qApp->processEvents(); + if ( alarmCounter < maxAlarmReplay && ! mSilent) { + ++alarmCounter; + if ( !mPlayWav || mFileName.length() < 2 ) { + +#ifndef DESKTOP_VERSION + Sound::soundAlarm (); +#endif + } else { + QSound::play ( mFileName ); + //qDebug("BEEP!"); + } + } else { + if ( ! mSilent && mSuspendCounter > 0 ) { + --mSuspendCounter; + reject (); + hide(); + return; + } + } + playSoundTimer->start( mPauseCount * 1000, true ); +} diff --git a/kalarmd/alarmdialog.h b/kalarmd/alarmdialog.h new file mode 100644 index 0000000..3155f18 --- a/dev/null +++ b/kalarmd/alarmdialog.h @@ -0,0 +1,80 @@ +/* + This file is part of the KDE alarm daemon. + Copyright (c) 2000 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef ALARMDIALOG_H +#define ALARMDIALOG_H + + + +#include <qdialog.h> +#include <qdatetime.h> +#include <qstring.h> + +#include "sharp_char.h" + + +class QSpinBox; +class QLabel; +class QString; + +class AlarmDialog : public QDialog { + Q_OBJECT + public: + AlarmDialog( QWidget *parent = 0, const char *name = 0 ); + virtual ~AlarmDialog(); + + bool eventNotification(QString m, int replay , QString m2 , bool, int, int ); + int getSuspendTime( ); + void setSuspendTime( int ); + void setServerNotification( bool b ); + + public slots: + void slotOk(); + void slotSuspend(); + void reject () ; + void silent () ; + void accept(); + void suspend(); + void playSound (); + signals: + // void suspendSignal(int duration); + void addAlarm(const QDateTime &, const QString & ); + + private: + int alarmCounter; + int mPauseCount; + int mSuspendCounter; + int maxAlarmReplay; + QTimer* playSoundTimer; + bool mStopAlarm; + bool mSilent; + bool mPlayWav; + bool mServerNotification; + QLabel* mMessage; + QLabel* mMissedAlarms; + QSpinBox *mSuspendSpin; + QString mFileName; + int fd_led; + sharp_led_status statusLED; +}; + +#endif diff --git a/kalarmd/alarmdialog.moc b/kalarmd/alarmdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/kalarmd/alarmdialog.moc diff --git a/kalarmd/kalarmdE.pro b/kalarmd/kalarmdE.pro new file mode 100644 index 0000000..1370ec1 --- a/dev/null +++ b/kalarmd/kalarmdE.pro @@ -0,0 +1,20 @@ +TEMPLATE = lib +CONFIG += qt warn_on +TARGET = kopialarmapplet +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) + +DESTDIR = $(QPEDIR)/plugins/applets + +INTERFACES = \ + +HEADERS = \ + alarmdialog.h \ + simplealarmdaemonapplet.h \ + simplealarmdaemonimpl.h + +SOURCES = \ + alarmdialog.cpp \ + simplealarmdaemonapplet.cpp \ + simplealarmdaemonimpl.cpp + diff --git a/kalarmd/sharp_char.h b/kalarmd/sharp_char.h new file mode 100644 index 0000000..33fabd4 --- a/dev/null +++ b/kalarmd/sharp_char.h @@ -0,0 +1,258 @@ +/* + * linux/include/asm/sharp_char.h + */ + +#ifndef __ASM_SHARP_CHAR_H_INCLUDED +#define __ASM_SHARP_CHAR_H_INCLUDED + +/* + * If SHARPCHAR_USE_MISCDEV defined , misc driver architecture used instead of sharp_char + */ + +#define SHARPCHAR_USE_MISCDEV + +/* + * devices defines... + */ + +#ifndef SHARP_DEV_MAJOR +#define SHARP_DEV_MAJOR 11 +#endif + +#ifndef SHARP_DEV_MINOR_START +#define SHARP_DEV_MINOR_START 210 +#endif + +#define SHARP_DEV_MINOR_MAX 4 /* defines last minor number of SHARP device */ + +#define SHARP_LED_MINOR (SHARP_DEV_MINOR_START+0) +#define SHARP_BUZZER_MINOR (SHARP_DEV_MINOR_START+1) +#define SHARP_GSM_MINOR (SHARP_DEV_MINOR_START+2) +#define SHARP_AUDIOCTL_MINOR (SHARP_DEV_MINOR_START+3) +#define SHARP_KBDCTL_MINOR (SHARP_DEV_MINOR_START+4) + +/* + * ioctl defines... + */ + +#define SHARP_DEV_IOCTL_COMMAND_START 0x5680 + +/* --- for SHARP_LED device --- */ +#define SHARP_LED_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_LED_GETSTATUS (SHARP_LED_IOCTL_START) +#define SHARP_LED_SETSTATUS (SHARP_LED_IOCTL_START+1) +#define SHARP_LED_ISUPPORTED (SHARP_LED_IOCTL_START+2) + +typedef struct sharp_led_status { + int which; /* select which LED status is wanted. */ + int status; /* set new led status if you call SHARP_LED_SETSTATUS */ +} sharp_led_status; + +#define SHARP_LED_WHICH_MAX 15 /* last number of LED */ + +/* parameters for 'which' member */ +#define SHARP_LED_PDA 0 /* PDA status */ +#define SHARP_LED_DALARM 1 /* daily alarm */ +#define SHARP_LED_SALARM 2 /* schedule alarm */ +#define SHARP_LED_BATTERY 3 /* main battery status */ +#define SHARP_LED_ACSTATUS 4 /* AC line status */ +#define SHARP_LED_CHARGER 5 /* charger status */ +#define SHARP_LED_PHONE_RSSI 6 /* phone status (RSSI...) */ +#define SHARP_LED_PHONE_DIAL 7 /* phone status (dialing...) */ +#define SHARP_LED_PHONE_IN 8 /* phone status (incoming..) */ +#define SHARP_LED_MAIL_EXISTS 9 /* mail status (exists or not) */ +#define SHARP_LED_MAIL_SEND 10 /* mail status (sending...) */ +#define SHARP_LED_MAIL_QUEUE 11 /* mail to send is in queue */ +#define SHARP_LED_COLLIE_0 12 /* 1st pri. battery LED control */ +#define SHARP_LED_COLLIE_1 13 /* 1st pri. mail LED control */ +#define SHARP_LED_COMM 14 /* communication status */ +#define SHARP_LED_BROWSER 15 /* WWW browser status */ + +/* parameters for 'status' member */ +#define LED_PDA_RUNNING 0 /* for SHARP_LED_RUN */ +#define LED_PDA_SUSPENDED 1 /* for SHARP_LED_RUN */ +#define LED_PDA_OFF 2 /* for SHARP_LED_RUN */ +#define LED_PDA_ERROR 3 /* for SHARP_LED_RUN */ + +#define LED_DALARM_OFF 0 /* for SHARP_LED_DALARM */ +#define LED_DALARM_ON 1 /* for SHARP_LED_DALARM */ + +#define LED_SALARM_OFF 0 /* for SHARP_LED_SALARM */ +#define LED_SALARM_ON 1 /* for SHARP_LED_SALARM */ + +#define LED_BATTERY_GOOD 0 /* for SHARP_LED_BATTERY */ +#define LED_BATTERY_LOW 1 /* for SHARP_LED_BATTERY */ +#define LED_BATTERY_VERY_LOW 2 /* for SHARP_LED_BATTERY */ +#define LED_BATTERY_CRITICAL 3 /* for SHARP_LED_BATTERY */ + +#define LED_CHARGER_OFF 0 /* for SHARP_LED_CHARGER */ +#define LED_CHARGER_CHARGING 1 /* for SHARP_LED_CHARGER */ +#define LED_CHARGER_ERROR 2 /* for SHARP_LED_CHARGER */ + +#define LED_AC_NOT_CONNECTED 0 /* for SHARP_LED_ACSTATUS */ +#define LED_AC_CONNECTED 1 /* for SHARP_LED_ACSTATUS */ + +#define LED_RSSI_OUT 0 /* for SHARP_LED_PHONE_RSSI */ +#define LED_RSSI_IN 1 /* for SHARP_LED_PHONE_RSSI */ + +#define LED_DIAL_OFF 0 /* for SHARP_LED_PHONE_DIAL */ +#define LED_DIAL_DIALING 1 /* for SHARP_LED_PHONE_DIAL */ +#define LED_DIAL_HOLDING 2 /* for SHARP_LED_PHONE_DIAL */ + +#define LED_PHONE_WAITING 0 /* for SHARP_LED_PHONE_IN */ +#define LED_PHONE_INCOMING 1 /* for SHARP_LED_PHONE_IN */ + +#define LED_MAIL_NO_UNREAD_MAIL 0 /* for SHARP_LED_MAIL_EXISTS */ +#define LED_MAIL_NEWMAIL_EXISTS 1 /* for SHARP_LED_MAIL_EXISTS */ +#define LED_MAIL_UNREAD_MAIL_EX 2 /* for SHARP_LED_MAIL_EXISTS */ + +#define LED_SENDMAIL_OFF 0 /* for SHARP_LED_MAIL_SEND */ +#define LED_SENDMAIL_SENDING 1 /* for SHARP_LED_MAIL_SEND */ +#define LED_SENDMAIL_ERROR 2 /* for SHARP_LED_MAIL_SEND */ + +#define LED_MAILQUEUE_NOUNREAD 0 /* for SHARP_LED_MAIL_QUEUE */ +#define LED_MAILQUEUE_NEWMAIL 1 /* for SHARP_LED_MAIL_QUEUE */ +#define LED_MAILQUEUE_UNREAD 2 /* for SHARP_LED_MAIL_QUEUE */ + +#define LED_COLLIE_0_DEFAULT 0 /* for SHARP_LED_COLLIE_0 */ +#define LED_COLLIE_0_OFF 1 /* for SHARP_LED_COLLIE_0 */ +#define LED_COLLIE_0_ON 2 /* for SHARP_LED_COLLIE_0 */ +#define LED_COLLIE_0_FASTBLINK 3 /* for SHARP_LED_COLLIE_0 */ +#define LED_COLLIE_0_SLOWBLINK 4 /* for SHARP_LED_COLLIE_0 */ + +#define LED_COLLIE_1_DEFAULT 0 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_OFF 1 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_ON 2 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_FLASHON 3 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_FLASHOFF 4 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_VFSTBLINK 5 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_FASTBLINK 6 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_NORMBLINK 7 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_SLOWBLINK 8 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_SOFTBLINK 9 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_SOFTFLASH 10 /* for SHARP_LED_COLLIE_1 */ + +#define LED_COMM_OFFLINE 0 /* for SHARP_LED_COMM */ +#define LED_COMM_ONLINE 1 /* for SHARP_LED_COMM */ +#define LED_COMM_ERROR 2 /* for SHARP_LED_COMM */ + +#define LED_BROWSER_OFFLINE 0 /* for SHARP_LED_BROWSER */ +#define LED_BROWSER_ONLINE 1 /* for SHARP_LED_BROWSER */ +#define LED_BROWSER_ERROR 2 /* for SHARP_LED_BROWSER */ + + +/* --- for SHARP_BUZZER device --- */ +#define SHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START) +#define SHARP_BUZZER_SETVOLUME (SHARP_BUZZER_IOCTL_START+1) +#define SHARP_BUZZER_GETVOLUME (SHARP_BUZZER_IOCTL_START+2) +#define SHARP_BUZZER_ISSUPPORTED (SHARP_BUZZER_IOCTL_START+3) +#define SHARP_BUZZER_SETMUTE (SHARP_BUZZER_IOCTL_START+4) +#define SHARP_BUZZER_STOPSOUND (SHARP_BUZZER_IOCTL_START+5) +#define SHARP_BUZZER_SET_BUFFER (SHARP_BUZZER_IOCTL_START+6) + +typedef struct sharp_buzzer_status { /* this struct is used for setvolume/getvolume */ + int which; /* select which LED status is wanted. */ + int volume; /* set new buzzer volume if you call SHARP_BUZZER_SETVOLUME */ + int mute; /* set 1 to MUTE if you call SHARP_BUZZER_SETMUTE */ +} sharp_buzzer_status; + +#define SHARP_BUZ_WHICH_MAX 14 /* last number of buzzer */ + +#define SHARP_BUZ_ALL_SOUNDS -1 /* for setting volumes of ALL sounds at a time */ + +#define SHARP_BUZ_WRITESOUND 0 /* for sound datas through 'write' calls */ +#define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */ +#define SHARP_BUZ_KEYSOUND 2 /* key sound */ +#define SHARP_PDA_ILLCLICKSOUND 3 /* illegal click */ +#define SHARP_PDA_WARNSOUND 4 /* warning occurred */ +#define SHARP_PDA_ERRORSOUND 5 /* error occurred */ +#define SHARP_PDA_CRITICALSOUND 6 /* critical error occurred */ +#define SHARP_PDA_SYSSTARTSOUND 7 /* system start */ +#define SHARP_PDA_SYSTEMENDSOUND 8 /* system shutdown */ +#define SHARP_PDA_APPSTART 9 /* application start */ +#define SHARP_PDA_APPQUIT 10 /* application ends */ +#define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */ +#define SHARP_BUZ_DAILY_ALARM 12 /* daily alarm */ +#define SHARP_BUZ_GOT_PHONE_CALL 13 /* phone call sound */ +#define SHARP_BUZ_GOT_MAIL 14 /* mail sound */ + +#define SHARP_BUZ_VOLUME_OFF 0 +#define SHARP_BUZ_VOLUME_LOW 33 +#define SHARP_BUZ_VOLUME_MEDIUM 67 +#define SHARP_BUZ_VOLUME_HIGH 100 /* currentry , this is the maximum ... */ +#define SHARP_BUZ_VOLUME_MAX (SHARP_BUZ_VOLUME_HIGH) + +/* --- for SHARP_GSM device --- */ +#define SHARP_GSM_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_GSM_GETEXTSTATUS (SHARP_GSM_IOCTL_START+16) +#define SHARP_GSM_INFO_TELL_MODE (SHARP_GSM_IOCTL_START+17) +#define SHARP_IRIS_GETSYNCSTATUS (SHARP_GSM_IOCTL_START+18) +#define SHARP_IRIS_RECHECKDEVICE (SHARP_GSM_IOCTL_START+19) + +#define GSM_PHONE_NO_POWER 0 /* for SHARP_GSM_INFO_TELL_MODE */ +#define GSM_PHONE_NO_CONNECTION 1 /* for SHARP_GSM_INFO_TELL_MODE */ +#define GSM_PHONE_IN_ANALOG_MODE 2 /* for SHARP_GSM_INFO_TELL_MODE */ +#define GSM_PHONE_IN_DATA_MODE 3 /* for SHARP_GSM_INFO_TELL_MODE */ + +typedef struct sharp_gsmext_status { + int carkit; /* be set as 1 , if car-kit is connected */ + int headphone_mic; /* be set as 1 , if head-phone-microphone is inserted */ +} sharp_gsmext_status; + +typedef struct sharp_irisext_status { /* for SHARP_IRIS_GETSYNCSTATUS */ + int usb; + int uart; + int carkit; +} sharp_irisext_status; + +/* --- for SHARP_AUDIOCTL device --- */ +#define SHARP_AUDIOCTL_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_AUDIOCTL_ARCH_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START+0x10) +#define SHARP_IRIS_AUFIL_GETVAL (SHARP_AUDIOCTL_ARCH_IOCTL_START+0) +#define SHARP_IRIS_AUFIL_SETVAL (SHARP_AUDIOCTL_ARCH_IOCTL_START+1) +#define SHARP_IRIS_AMP_EXT_ON (SHARP_AUDIOCTL_ARCH_IOCTL_START+2) +#define SHARP_IRIS_AMP_EXT_OFF (SHARP_AUDIOCTL_ARCH_IOCTL_START+3) + + +#define SHARP_IRIS_AUFIL_FILTERON 0x01 /* Iris AudioCtl Specific. Enable Audio Filter */ + +/* --- for SHARP_AUDIOCTL device --- */ +#define SHARP_KBDCTL_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_KBDCTL_GETMODIFSTAT (SHARP_KBDCTL_IOCTL_START+0) +#define SHARP_KBDCTL_TOGGLEMODIFSTAT (SHARP_KBDCTL_IOCTL_START+1) +#define SHARP_KBDCTL_SETHOLDTH (SHARP_KBDCTL_IOCTL_START+2) +#define SHARP_KBDCTL_SETHOLDTH_GR (SHARP_KBDCTL_IOCTL_START+3) +#define SHARP_KBDCTL_HOLDINFO_SETHD (SHARP_KBDCTL_IOCTL_START+4) +#define SHARP_KBDCTL_HOLDINFO_SETSL (SHARP_KBDCTL_IOCTL_START+5) +#define SHARP_KBDCTL_HOLDINFO_DELHD (SHARP_KBDCTL_IOCTL_START+6) +#define SHARP_KBDCTL_HOLDINFO_DELSL (SHARP_KBDCTL_IOCTL_START+7) +#define SHARP_KBDCTL_HOLDINFO_RESTHD (SHARP_KBDCTL_IOCTL_START+8) +#define SHARP_KBDCTL_HOLDINFO_RESTSL (SHARP_KBDCTL_IOCTL_START+9) +#define SHARP_KBDCTL_HOLDINFO_RESTFULL (SHARP_KBDCTL_IOCTL_START+10) + +typedef struct sharp_kbdctl_modifstat { + int which; + int stat; +} sharp_kbdctl_modifstat; + +typedef struct sharp_kbdctl_holdstat { + int group; + int timeout; +} sharp_kbdctl_holdstat; + +typedef struct sharp_kbdctl_holdcustom { + int normal_hardcode; + int normal_slcode; + int hold_slcode; +} sharp_kbdctl_holdcustom; + +#define SHARP_EXTMODIF_2ND 0x01 +#define SHARP_EXTMODIF_CAPS 0x02 +#define SHARP_EXTMODIF_NUMLOCK 0x03 + +#define HOLDKEY_GROUP_NORMAL 0 +#define HOLDKEY_GROUP_POWER 1 + +#endif /* __ASM_SHARP_CHAR_H_INCLUDED */ + diff --git a/kalarmd/simplealarmdaemon.desktop b/kalarmd/simplealarmdaemon.desktop new file mode 100644 index 0000000..dae86ba --- a/dev/null +++ b/kalarmd/simplealarmdaemon.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Comment=KOrganizer Alarm Daemon +Exec=simplealarmdaemon +Icon=SimpleAlarmDaemon +Type=Application +Name=Alarm Daemon diff --git a/kalarmd/simplealarmdaemonapplet.cpp b/kalarmd/simplealarmdaemonapplet.cpp new file mode 100644 index 0000000..bb89606 --- a/dev/null +++ b/kalarmd/simplealarmdaemonapplet.cpp @@ -0,0 +1,58 @@ +#include "simplealarmdaemonapplet.h" + +#include "simplealarmdaemonimpl.h" + +#include <qpe/global.h> +#include <qcopchannel_qws.h> +#include <qlabel.h> +#include <qapp.h> +#include <qpe/resource.h> +SimpleAlarmDaemonApplet::SimpleAlarmDaemonApplet() + : mApplet( 0 ), ref( 0 ) +{ + +} + +SimpleAlarmDaemonApplet::~SimpleAlarmDaemonApplet() +{ + delete mApplet; +} + + +QWidget *SimpleAlarmDaemonApplet::applet( QWidget *parent ) +{ + if ( !mApplet ) { + mApplet = new SimpleAlarmDaemonImpl( parent ); + if ( QApplication::desktop()->width() < 480 ) + mApplet->setPixmap( Resource::loadPixmap( "ko16" ) ); + else + mApplet->setPixmap( Resource::loadPixmap( "ko24" ) ); + QCopChannel* c = new QCopChannel("koalarm",mApplet , "channel" ) ; + QObject::connect( c, SIGNAL (received ( const QCString &, const QByteArray & )),mApplet, SLOT(recieve( const QCString&, const QByteArray& ))); + mApplet->show(); + } + return mApplet; +} + +int SimpleAlarmDaemonApplet::position() const +{ + return 7; +} + +QRESULT SimpleAlarmDaemonApplet::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( uuid == IID_QUnknown ) + *iface = this; + else if ( uuid == IID_TaskbarApplet ) + *iface = this; + + if ( *iface ) + (*iface)->addRef(); + return QS_OK; +} + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( SimpleAlarmDaemonApplet ) +} diff --git a/kalarmd/simplealarmdaemonapplet.h b/kalarmd/simplealarmdaemonapplet.h new file mode 100644 index 0000000..a4cbee4 --- a/dev/null +++ b/kalarmd/simplealarmdaemonapplet.h @@ -0,0 +1,26 @@ +#ifndef SIMPLEALARMDAEMONAPPLET_H +#define SIMPLEALARMDAEMONAPPLET_H + +#include <qpe/taskbarappletinterface.h> + +class SimpleAlarmDaemonImpl; +class ScreenshotApplet; + +class SimpleAlarmDaemonApplet : public TaskbarAppletInterface +{ + public: + SimpleAlarmDaemonApplet(); + virtual ~SimpleAlarmDaemonApplet(); + + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + + virtual QWidget *applet( QWidget *parent ); + virtual int position() const; + + private: + SimpleAlarmDaemonImpl *mApplet; + ulong ref; +}; + +#endif diff --git a/kalarmd/simplealarmdaemonimpl.cpp b/kalarmd/simplealarmdaemonimpl.cpp new file mode 100644 index 0000000..2bc6643 --- a/dev/null +++ b/kalarmd/simplealarmdaemonimpl.cpp @@ -0,0 +1,552 @@ +/* + This file is part of the KOrganizer alarm daemon. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "simplealarmdaemonimpl.h" + +#include "alarmdialog.h" +#include <qpopupmenu.h> +#include <qapp.h> +#include <qdir.h> +#include <qfile.h> +#include <qhbox.h> +#include <qtimer.h> +#include <qfile.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qdialog.h> +#include <qspinbox.h> +#include <qtextstream.h> +#include <qtopia/qcopenvelope_qws.h> +#include <qtopia/alarmserver.h> + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + + +SimpleAlarmDaemonImpl::SimpleAlarmDaemonImpl( QWidget *parent ) + : QLabel( parent ) +{ + mAlarmDialog = new AlarmDialog( 0 ); + mPopUp = new QPopupMenu( 0 ); + mPopUp->insertItem( "Addresses", this, SLOT ( showAdd() ) ); + mPopUp->insertSeparator(); + mPopUp->insertItem( "Multi Sync", this, SLOT ( ringSync() ) ); + mPopUp->insertSeparator(); + mPopUp->insertItem( "What's Next?", this, SLOT ( showWN() ) ); + mPopUp->insertSeparator(); + mPopUp->insertItem( "What's Todo?", this, SLOT ( showTodo() ) ); + mPopUp->insertSeparator(); + mPopUp->insertItem( "Next Days!", this, SLOT ( showKO() ) ); + mPopUp->insertSeparator(); + mPopUp->insertItem( "Edit Journal", this, SLOT ( writeJournal() ) ); + mPopUp->insertSeparator(); + mPopUp->insertItem( "New Event", this, SLOT ( newEvent() ) ); + mPopUp->insertItem( "New Todo", this, SLOT ( newTodo() ) ); + mTimerPopUp = new QPopupMenu( mPopUp ); + + mBeepPopUp = new QPopupMenu( mPopUp ); + mSoundPopUp = new QPopupMenu( mBeepPopUp ); + mPausePopUp = new QPopupMenu( mBeepPopUp ); + QPopupMenu* savePopUp = new QPopupMenu( mBeepPopUp ); + savePopUp->insertItem( "Save", 0 ); + savePopUp->insertItem( "Load", 1 ); + mSoundPopUp->insertItem( "Buzzer", 0 ); + mSoundPopUp->insertItem( "Wav file", 1 ); + mPausePopUp->insertItem( " 1 sec", 1 ); + mPausePopUp->insertItem( " 2 sec", 2 ); + mPausePopUp->insertItem( " 3 sec", 3 ); + mPausePopUp->insertItem( " 5 sec", 5 ); + mPausePopUp->insertItem( "10 sec", 10 ); + mPausePopUp->insertItem( "30 sec", 30 ); + mPausePopUp->insertItem( " 1 min", 60 ); + mPausePopUp->insertItem( " 5 min", 300 ); + mPausePopUp->insertItem( "10 min", 600 ); + mSuspendPopUp = new QPopupMenu( mBeepPopUp ); + mSuspendPopUp->insertItem( "Off", 0 ); + mSuspendPopUp->insertItem( " 1x", 1 ); + mSuspendPopUp->insertItem( " 2x", 2 ); + mSuspendPopUp->insertItem( " 3x", 3 ); + mSuspendPopUp->insertItem( " 5x", 5 ); + mSuspendPopUp->insertItem( "10x", 10 ); + mSuspendPopUp->insertItem( "20x", 20 ); + mSuspendPopUp->insertItem( "30x", 30 ); + mBeepPopUp->insertItem( "Auto suspend",mSuspendPopUp ); + mBeepPopUp->insertItem( "Beep interval",mPausePopUp ); + mBeepPopUp->insertItem( "Replay",mSoundPopUp ); + mBeepPopUp->insertItem( "Config",savePopUp ); + mBeepPopUp->insertItem( "300", 300 ); + mBeepPopUp->insertItem( "180", 180 ); + mBeepPopUp->insertItem( "60", 60 ); + mBeepPopUp->insertItem( "30", 30 ); + mBeepPopUp->insertItem( "10", 10 ); + mBeepPopUp->insertItem( "3", 3 ); + mBeepPopUp->insertItem( "1", 1 ); + mBeepPopUp->insertItem( "Off", 0 ); + mBeepPopUp->setCheckable( true ); + mPopUp->insertSeparator(); + mPopUp->insertItem( "Play beeps", mBeepPopUp ); + mPopUp->insertSeparator(); + mPopUp->insertItem( "Timer", mTimerPopUp ); + mPopUp->insertSeparator(); + mPopUp->insertItem( "Simulate", this, SLOT ( simulate() ) ); + + mPopUp->resize( mPopUp->sizeHint() ); + mPlayBeeps = 60; + mBeepPopUp->setItemChecked ( mPlayBeeps, true ); + connect ( mBeepPopUp, SIGNAL( activated ( int ) ), this, SLOT (slotPlayBeep( int ) ) ); + connect ( mTimerPopUp, SIGNAL( activated ( int ) ), this, SLOT (confTimer( int ) ) ); + connect ( mTimerPopUp, SIGNAL(aboutToShow() ), this, SLOT ( showTimer( ) ) ); + connect ( mSoundPopUp, SIGNAL( activated ( int ) ), this, SLOT (confSound( int ) ) ); + connect ( mPausePopUp, SIGNAL( activated ( int ) ), this, SLOT (confPause( int ) ) ); + connect ( mSuspendPopUp, SIGNAL( activated ( int ) ), this, SLOT (confSuspend( int ) ) ); + connect ( savePopUp, SIGNAL( activated ( int ) ), this, SLOT (saveSlot( int ) ) ); + mTimerTime = 0; + mCustomText = "Custom Text"; + mCustomMinutes = 7; + mTimerPopupConf = 1; + fillTimerPopUp(); + mPausePlay = 0; + confPause( 1 ); + mSuspend = 0; + confSuspend( 0 ); + if ( QApplication::desktop()->width() < 480 ) { + wavAlarm = false; + mSoundPopUp->setItemChecked ( 0, true ); + } + else { + wavAlarm = true; + mSoundPopUp->setItemChecked ( 1, true ); + } + saveSlot( 1 ); +} + +SimpleAlarmDaemonImpl::~SimpleAlarmDaemonImpl() +{ + delete mPopUp; + delete mAlarmDialog; +} +void SimpleAlarmDaemonImpl::saveSlot( int load ) +{ + QString fileName = QDir::homeDirPath() +"/.kopialarmrc"; + //qDebug("save %d ", load ); + QFile file( fileName ); + if ( load ) { + if( !QFile::exists( fileName) ) + return; + if (!file.open( IO_ReadOnly ) ) { + return ; + } + QString line; + bool ok; + int val; + int len; + while ( file.readLine( line, 1024 ) > 0 ) { + //qDebug("read %s ", line.latin1()); + len = line.length(); + if ( line.left(4 ) == "PPAU" ) { + val = line.mid( 4,len-5).toInt( &ok ); + if ( ok ) { + confPause( val ); + } + } + if ( line.left(4 ) == "SUCO" ) { + val = line.mid( 4,len-5).toInt( &ok ); + if ( ok ) + confSuspend ( val ); + } + if ( line.left(4 ) == "WAAL" ) { + val = line.mid( 4,len-5).toInt( &ok ); + if ( ok ) + confSound( val ); + + } + if ( line.left(4 ) == "PLBE" ) { + val = line.mid( 4,len-5).toInt( &ok ); + if ( ok ) + slotPlayBeep( val ); + + } + if ( line.left(4 ) == "CUTE" ) { + mCustomText = line.mid( 5,len-6); + // qDebug("text ***%s*** ",mCustomText.latin1() ); + + } + if ( line.left(4 ) == "CUMI" ) { + val = line.mid( 4,len-5).toInt( &ok ); + if ( ok ) + mCustomMinutes = val; + + } + if ( line.left(4 ) == "SUTI" ) { + val = line.mid( 4,len-5).toInt( &ok ); + if ( ok ) + mAlarmDialog->setSuspendTime( val );; + + } + } + file.close(); + } else { + if (!file.open( IO_WriteOnly ) ) { + return; + } + QString configString ; + configString += "PPAU " + QString::number( mPausePlay ) + "\n"; + configString += "SUCO " + QString::number( mSuspend ) + "\n"; + configString += "WAAL " + QString::number( wavAlarm ) + "\n"; + configString += "PLBE " + QString::number( mPlayBeeps ) + "\n"; + configString += "CUTE " + mCustomText + "\n"; + configString += "CUMI " + QString::number( mCustomMinutes ) + "\n"; + configString += "SUTI " + QString::number( mAlarmDialog->getSuspendTime( )) + "\n"; + QTextStream ts( &file ); + ts << configString ; + file.close(); + } + +} +void SimpleAlarmDaemonImpl::confSuspend( int num ) +{ + mSuspendPopUp->setItemChecked ( mSuspend,false ); + mSuspend = num; + mSuspendPopUp->setItemChecked ( mSuspend,true ); +} +void SimpleAlarmDaemonImpl::confPause( int num ) +{ + mPausePopUp->setItemChecked ( mPausePlay,false ); + mPausePlay = num; + mPausePopUp->setItemChecked ( mPausePlay,true ); +} +void SimpleAlarmDaemonImpl::confSound( int num ) +{ + if ( num == 0 ) { + wavAlarm = false; + mSoundPopUp->setItemChecked ( 0, true ); + mSoundPopUp->setItemChecked ( 1, false ); + } else { + wavAlarm = true; + mSoundPopUp->setItemChecked ( 0, false ); + mSoundPopUp->setItemChecked ( 1, true ); + } +} +void SimpleAlarmDaemonImpl::slotPlayBeep( int num ) +{ + mBeepPopUp->setItemChecked ( mPlayBeeps,false ); + mPlayBeeps = num; + mBeepPopUp->setItemChecked ( mPlayBeeps, true ); +} + +void SimpleAlarmDaemonImpl::recieve( const QCString& msg, const QByteArray& ) +{ + //qDebug("SimpleAlarmDaemonImpl::ALARM RECEIVED! %s", msg.data()); + QString mess = msg; + mAlarmMessage = mess.mid( 9 ); + QString filename = getenv("QPEDIR") ; + filename += "/pics/kdepim/korganizer/koalarm.wav"; + QString tempfilename; + if ( mess.left( 13 ) == "suspend_alarm") { + bool error = false; + int len = mess.mid( 13 ).find("+++"); + if ( len < 2 ) + error = true; + else { + tempfilename = mess.mid( 13, len ); + if ( !QFile::exists( tempfilename ) ) + error = true; + } + if ( ! error ) { + filename = tempfilename; + } + mAlarmMessage = mess.mid( 13+len+3 ); + //qDebug("suspend file %s ",tempfilename.latin1() ); + startAlarm( mAlarmMessage, filename); + return; + } + if ( mess.left( 11 ) == "timer_alarm") { + mTimerTime = 0; + startAlarm( mess.mid( 11 ), filename ); + return; + } + if ( mess.left( 10 ) == "proc_alarm") { + bool error = false; + int len = mess.mid( 10 ).find("+++"); + if ( len < 2 ) + error = true; + else { + tempfilename = mess.mid( 10, len ); + if ( !QFile::exists( tempfilename ) ) + error = true; + } + if ( error ) { + mAlarmMessage = "Procedure Alarm\nError - File not found\n"; + mAlarmMessage += mess.mid( 10+len+3+9 ); + } else { + QCopEnvelope e("QPE/Application/kopi", "-writeFileSilent"); + //qDebug("-----system command %s ",tempfilename.latin1() ); + if ( vfork () == 0 ) { + execl ( tempfilename.latin1(), 0 ); + return; + } + return; + } + + //qDebug("+++++++system command %s ",tempfilename.latin1() ); + } + if ( mess.left( 11 ) == "audio_alarm") { + bool error = false; + int len = mess.mid( 11 ).find("+++"); + if ( len < 2 ) + error = true; + else { + tempfilename = mess.mid( 11, len ); + if ( !QFile::exists( tempfilename ) ) + error = true; + } + if ( ! error ) { + filename = tempfilename; + } + mAlarmMessage = mess.mid( 11+len+3+9 ); + //qDebug("audio file command %s ",tempfilename.latin1() ); + } + if ( mess.left( 9 ) == "cal_alarm") { + mAlarmMessage = mess.mid( 9 ) ; + } + + writeFile(); + startAlarm( mAlarmMessage, filename ); + +} + +int SimpleAlarmDaemonImpl::getFileNameLen( QString mess ) +{ + return 0; +} +void SimpleAlarmDaemonImpl::startAlarm( QString mess, QString filename ) +{ + //mAlarmDialog->show(); + //mAlarmDialog->raise(); + mAlarmDialog->eventNotification( mess, mPlayBeeps, filename, wavAlarm,mPausePlay ,mSuspend ); +} + + +void SimpleAlarmDaemonImpl::fillTimerPopUp() +{ + + // qDebug(" timer %d %d ",mTimerPopupConf, mTimerTime ); + if ( mTimerPopupConf == mTimerTime ) { + if ( mTimerTime ) { + int secs = QDateTime::currentDateTime().secsTo ( mRunningTimer ); + QTime t ( secs/3600, (secs/60)%60, secs%60 ); + mTimerPopUp->changeItem ( 1 , t.toString()); + } + else { + QString text = mCustomText.stripWhiteSpace (); + int in = text.find( " " ); + text = text.left ( in ); + mTimerPopUp->changeItem ( 3, text ); + } + return; + } + mTimerPopupConf = mTimerTime; + mTimerPopUp->clear(); + if ( mTimerTime ) { + int secs = QDateTime::currentDateTime().secsTo ( mRunningTimer ); + QTime t ( secs/3600, (secs/60)%60, secs%60 ); + mTimerPopUp->insertItem( "Stop", 0 ); + mTimerPopUp->insertItem( t.toString(),1); + } else { + mTimerPopUp->insertItem( "24 h", 1440 ); + // mTimerPopUp->insertItem( i18n("12 h"), 720 ); + mTimerPopUp->insertItem( " 8 h", 480 ); + mTimerPopUp->insertItem( " 5 h", 300 ); + // mTimerPopUp->insertItem( i18n(" 2 h"), 120 ); + mTimerPopUp->insertItem( " 1 h", 60 ); + mTimerPopUp->insertItem( "30 min", 30 ); + mTimerPopUp->insertItem( "15 min", 15 ); + mTimerPopUp->insertItem( "10 min", 10 ); + //mTimerPopUp->insertItem( " 5 min", 5 ); + mTimerPopUp->insertSeparator(); + mTimerPopUp->insertItem( "Pizza", 22 ); + mTimerPopUp->insertItem( "Nap", 45 ); + mTimerPopUp->insertItem( "Tea", 5 ); + QString text = mCustomText.stripWhiteSpace (); + int in = text.find( " " ); + text = text.left ( in ); + mTimerPopUp->insertItem( text, 3 ); + mTimerPopUp->insertSeparator(); + mTimerPopUp->insertItem( "Customize", 2 ); + } + +} + +void SimpleAlarmDaemonImpl::showTimer() +{ + fillTimerPopUp(); +} + +void SimpleAlarmDaemonImpl::confTimer( int time ) +{ + //qDebug("impleAlarmDaemonImpl::confTimer() %d ", time ); + int minutes = time; + if ( minutes == 0 ) { + if ( ! mTimerTime ) + return; + + QDialog dia ( 0, ("Stop Timer" ), true ); + QLabel lab (("Really stop the timer?"), &dia ); + dia.setCaption(("KO/Pi Timer Stop" )); + QVBoxLayout lay( &dia ); + lay.setMargin(5); + lay.setSpacing(5); + lay.addWidget( &lab); + dia.resize( 200, dia.sizeHint().height() ); + + if ( !dia.exec() ) + return; + + AlarmServer::deleteAlarm ( mRunningTimer,"koalarm" , timerMesssage.latin1() ); + mTimerTime = 0; + return; + } + if ( mTimerTime ) + return; + if ( minutes == 1 ) { + return; + } + QString mess = "timer_alarm"; + mess += ("Timer Alarm!\n"); + if ( minutes == 22 ) + mess += ( "Pizza is ready"); + else if ( minutes == 45 ) + mess += ( "Please wake up!"); + else if ( minutes == 5 ) + mess += ( "Tea is ready"); + else if ( minutes == 3 ) { + mess += mCustomText; + minutes = mCustomMinutes ; + } + else { + if ( minutes == 2 ) { + // ask time + QDialog dia ( 0, ("Customize Timer" ), true ); + QLabel lab (("Message Text:"), &dia ); + dia.setCaption(("KO/Pi Timer" )); + QVBoxLayout lay( &dia ); + lay.setMargin(5); + lay.setSpacing(5); + lay.addWidget( &lab); + QLineEdit lEdit( mCustomText, &dia ); + lay.addWidget( &lEdit); + QLabel lab2 (("Countdown time (1 min - 24 h):"), &dia ); + lay.addWidget( &lab2); + QHBox hbox ( &dia ); + QLabel lab3 (("h:"), &hbox ); + QSpinBox spinh( 0, 24, 1,& hbox ); + QLabel lab4 ((" min:"), &hbox ); + QSpinBox spinm( 0, 59, 1,&hbox ); + spinh.setValue( mCustomMinutes/60 ); + spinm.setValue( mCustomMinutes%60 ); + lay.addWidget( &hbox); + dia.resize( dia.sizeHint().width(), dia.sizeHint().height() ); + if ( !dia.exec() ) + return; + mCustomText = lEdit.text(); + mCustomMinutes = spinh.value()*60+spinm.value(); + if ( mCustomMinutes == 0 ) + mCustomMinutes = 1; + if ( mCustomMinutes > 1440 ) + mCustomMinutes = 1440; + mess += mCustomText; + minutes = mCustomMinutes; + } + else + mess+= QString::number ( minutes ) + ( " minutes are past!"); + } + //minutes = 1; + mRunningTimer = QDateTime::currentDateTime().addSecs( minutes * 60 ); + timerMesssage = mess; + AlarmServer::addAlarm ( mRunningTimer,"koalarm",timerMesssage.latin1()); + mTimerTime = 1; +} + +void SimpleAlarmDaemonImpl::writeFile() +{ + QCopEnvelope e("QPE/Application/kopi", "-writeFile"); +} +void SimpleAlarmDaemonImpl::showWN() +{ + QCopEnvelope e("QPE/Application/kopi", "-showWN"); +} +void SimpleAlarmDaemonImpl::newTodo() +{ + QCopEnvelope e("QPE/Application/kopi", "-newTodo"); +} + +void SimpleAlarmDaemonImpl::newEvent() +{ + QCopEnvelope e("QPE/Application/kopi", "-newEvent"); + +} + +void SimpleAlarmDaemonImpl::showAdd() +{ + QCopEnvelope e("QPE/Application/kapi", " "); +} +void SimpleAlarmDaemonImpl::ringSync() +{ + QCopEnvelope e("QPE/Application/kopi", "-ringSync"); + +} +void SimpleAlarmDaemonImpl::newCountdown() +{ + //recieve("cal_alarm", 10 ); +} +void SimpleAlarmDaemonImpl::simulate() +{ + writeFile(); + QString filename = getenv("QPEDIR") ; + filename += "/pics/kdepim/korganizer/koalarm.wav"; + startAlarm("Alarm simulation", filename ); +} +void SimpleAlarmDaemonImpl::showKO() +{ + QCopEnvelope e("QPE/Application/kopi", "-showKO"); + +} +void SimpleAlarmDaemonImpl::showTodo() +{ + QCopEnvelope e("QPE/Application/kopi", "-showTodo"); + +} +void SimpleAlarmDaemonImpl::writeJournal() +{ + QCopEnvelope e("QPE/Application/kopi", "-showJournal"); + +} + +void SimpleAlarmDaemonImpl::mousePressEvent( QMouseEvent * ) +{ + + mPopUp->popup(mapToGlobal(QPoint (0, -mPopUp->height() ))); + +} + diff --git a/kalarmd/simplealarmdaemonimpl.h b/kalarmd/simplealarmdaemonimpl.h new file mode 100644 index 0000000..1c16af8 --- a/dev/null +++ b/kalarmd/simplealarmdaemonimpl.h @@ -0,0 +1,85 @@ +/* + This file is part of the KOrganizer alarm daemon. + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef SIMPLEALARMDAEMONIMPL_H +#define SIMPLEALARMDAEMONIMPL_H + +//#include "simplealarmdaemon.h" +#include <qdatetime.h> +#include <qlabel.h> + +class QLabel; +class QTimer; +class QPopupMenu; +class AlarmDialog; +class SimpleAlarmDaemonImpl : public QLabel +{ + Q_OBJECT + public: + SimpleAlarmDaemonImpl( QWidget *parent = 0 ); + + ~SimpleAlarmDaemonImpl(); + + protected slots: + void recieve( const QCString& msg, const QByteArray& data ); + void newTodo(); + void newEvent(); + void newCountdown(); + void simulate(); + void showKO(); + void showWN(); + void showAdd(); + void ringSync(); + void showTodo(); + void writeFile(); + void writeJournal(); + void slotPlayBeep( int ); + void showTimer( ); + void confPause( int ); + void confTimer( int ); + void saveSlot( int ); + void confSuspend( int ); + void confSound( int num ); + void startAlarm(QString mess, QString fn ); + + protected: + void mousePressEvent( QMouseEvent * ); + + private: + AlarmDialog *mAlarmDialog; + int mPlayBeeps; + int mPausePlay; + int mSuspend; + QString mAlarmMessage; + int mTimerTime; + int getFileNameLen( QString ); + QPopupMenu* mPopUp, *mBeepPopUp, *mTimerPopUp, *mSoundPopUp,*mPausePopUp,*mSuspendPopUp; + QDateTime mRunningTimer; + void fillTimerPopUp(); + QString timerMesssage; + QString mCustomText; + int mCustomMinutes; + int mTimerPopupConf; + bool wavAlarm; +}; + +#endif diff --git a/kdepim.control b/kdepim.control new file mode 100644 index 0000000..116bfef --- a/dev/null +++ b/kdepim.control @@ -0,0 +1,14 @@ +Files: bin/kopi bin/db2file bin/kapi apps/Pim/korganizer.desktop apps/Pim/kaddressbook.desktop pics/kdepim/* lib/libmicro* + +Priority: optional +Section: qpe/pim +Maintainer: Lutz Rogowski <lutz@pi-sync.net> +Architecture: arm +Version: 1.9.1 +License: GPL +Depends: +Description: KOrganizer/Pi and Kaddressbook/Pi + The embedded version of KOrganizer/Platform-independend, + the KDE calendar and scheduling program + optimized for 640x480 and 320x240 resolution + on Zaurus PDA diff --git a/kopi-desktop.pro b/kopi-desktop.pro new file mode 100644 index 0000000..1a5fabd --- a/dev/null +++ b/kopi-desktop.pro @@ -0,0 +1,6 @@ + + +TEMPLATE = subdirs +SUBDIRS = libical libkcal microkde libkdepim kabc korganizer kaddressbook +#kalarmd + diff --git a/korganizer-alarm.control b/korganizer-alarm.control new file mode 100644 index 0000000..60ced20 --- a/dev/null +++ b/korganizer-alarm.control @@ -0,0 +1,9 @@ +Files: plugins/applets/libkopialarmapplet.* pics/ko16.png pics/ko24.png +Priority: optional +Section: qpe/applications +Maintainer: Lutz Rogowski <lutz@pi-sync.net> +Architecture: arm +Version: 1.9.1 +License: GPL +Description: KOrganizer/Pi Alarm Daemon + The alarm daemon needed by KOrganizer/Platform-independend showing alarms. diff --git a/korganizer-opieKABC.control b/korganizer-opieKABC.control new file mode 100644 index 0000000..cb880ea --- a/dev/null +++ b/korganizer-opieKABC.control @@ -0,0 +1,10 @@ +Files: plugins/korganizer/libopiekabc.* +Priority: optional +Section: qpe/applications +Maintainer: Lutz Rogowski <lutz@pi-sync.net> +Architecture: arm +Version: 1.6.2a +License: GPL +Depends: korganizer +Description: KOrganizer/Pi Qtopia Addressbook Plugin + diff --git a/korganizer-qtopiaKABC.control b/korganizer-qtopiaKABC.control new file mode 100644 index 0000000..e124b8e --- a/dev/null +++ b/korganizer-qtopiaKABC.control @@ -0,0 +1,10 @@ +Files: plugins/korganizer/libqtopiakabc.* +Priority: optional +Section: qpe/applications +Maintainer: Lutz Rogowski <lutz@pi-sync.net> +Architecture: arm +Version: 1.6.2a +License: GPL +Depends: korganizer +Description: KOrganizer/Pi Qtopia Addressbook Plugin + diff --git a/korganizer.control b/korganizer.control new file mode 100644 index 0000000..aac713a --- a/dev/null +++ b/korganizer.control @@ -0,0 +1,14 @@ +Files: bin/kopi apps/Pim/korganizer.desktop pics/korganizer/* lib/libmicro* + +Priority: optional +Section: qpe/pim +Maintainer: Lutz Rogowski <lutz@pi-sync.net> +Architecture: arm +Version: 1.6.4b +License: GPL +Depends: +Description: KOrganizer/Pi + The embedded version of KOrganizer/Platform-independend, + the KDE calendar and scheduling program + optimized for 640x480 and 320x240 resolution + on Zaurus PDA diff --git a/korganizer/alarmclient.h b/korganizer/alarmclient.h new file mode 100644 index 0000000..dac4776 --- a/dev/null +++ b/korganizer/alarmclient.h @@ -0,0 +1,60 @@ +/* + This file is part of the KOrganizer interfaces. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef ALARMCLIENT_H +#define ALARMCLIENT_H + +#include <qstring.h> +#include <qstringlist.h> + +/** + This class provides the abstract interface for communicating with the alarm + daemon. It has to be implemented by subclasses for specific daemons. The + default implementation does nothing. +*/ +class AlarmClient +{ + public: + /** + Start alarm daemon. + */ + virtual void startDaemon() = 0; + + /** + Set the list of monitored calendars. Deletes previous settings. + */ + virtual bool setCalendars( const QStringList & ) = 0; + + /** + Add calendar for monitoring by alarm daemon. + */ + virtual bool addCalendar( const QString & ) = 0; + + /** + Remove calendar from monitoring by alarm daemon. + */ + virtual bool removeCalendar( const QString & ) = 0; + + /** + Reload calendar at URL. + */ + virtual bool reloadCalendar( const QString & ) = 0; +}; + +#endif diff --git a/korganizer/baseview.moc b/korganizer/baseview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/baseview.moc diff --git a/korganizer/calendarview.cpp b/korganizer/calendarview.cpp new file mode 100644 index 0000000..7292dcd --- a/dev/null +++ b/korganizer/calendarview.cpp @@ -0,0 +1,3476 @@ +/* + This file is part of KOrganizer. + + Requires the Qt and KDE widget libraries, available at no cost at + http://www.troll.no and http://www.kde.org respectively + + Copyright (c) 1997, 1998, 1999 + Preston Brown (preston.brown@yale.edu) + Fester Zigterman (F.J.F.ZigtermanRustenburg@student.utwente.nl) + Ian Dawes (iadawes@globalserve.net) + Laszlo Boloni (boloni@cs.purdue.edu) + + Copyright (c) 2000, 2001, 2002 + Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <stdlib.h> + +#include <qapplication.h> +#include <qradiobutton.h> +#include <qbuttongroup.h> +#include <qlayout.h> +#include <qclipboard.h> +#include <qcursor.h> +#include <qmessagebox.h> +#include <qprogressbar.h> +#include <qmultilineedit.h> +#include <qtimer.h> +#include <qwidgetstack.h> +#include <qptrlist.h> +#include <qregexp.h> +#include <qgroupbox.h> +#include <qfile.h> +#include <qdir.h> +#ifndef KORG_NOSPLITTER +#include <qsplitter.h> +#endif + +#include <kglobal.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <knotifyclient.h> +#include <kconfig.h> + +#include "kosyncprefsdialog.h" +#include <krun.h> +#include <kdirwatch.h> +#include <libkdepim/kdatepicker.h> +#include <libkdepim/ksyncprofile.h> + +#include <libkcal/vcaldrag.h> +#include <libkcal/icaldrag.h> +#include <libkcal/icalformat.h> +#include <libkcal/vcalformat.h> +#include <libkcal/scheduler.h> +#include <libkcal/calendarlocal.h> +#include <libkcal/journal.h> +#include <libkcal/calfilter.h> +#include <libkcal/attendee.h> +#include <libkcal/dndfactory.h> +#include <libkcal/freebusy.h> +#include <libkcal/filestorage.h> +#include <libkcal/calendarresources.h> +#include <libkcal/qtopiaformat.h> +#include "../kalarmd/alarmdialog.h" + +#ifndef DESKTOP_VERSION +#include <libkcal/sharpformat.h> +#endif +#ifndef KORG_NOMAIL +#include "komailclient.h" +#endif +#ifndef KORG_NOPRINTER +#include "calprinter.h" +#endif +#ifndef KORG_NOPLUGINS +#include "kocore.h" +#endif +#include "koeventeditor.h" +#include "kotodoeditor.h" +#include "koprefs.h" +#include "koeventviewerdialog.h" +#include "publishdialog.h" +#include "kofilterview.h" +#include "koglobals.h" +#include "koviewmanager.h" +#include "koagendaview.h" +#include "kodialogmanager.h" +#include "outgoingdialog.h" +#include "incomingdialog.h" +#include "statusdialog.h" +#include "kdatenavigator.h" +#include "kotodoview.h" +#include "datenavigator.h" +#include "resourceview.h" +#include "navigatorbar.h" +#include "searchdialog.h" +#include "mainwindow.h" + +#include "calendarview.h" +#ifndef DESKTOP_VERSION +#include <qtopia/alarmserver.h> +#endif +#ifndef _WIN32_ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#else +#include <qprocess.h> +#endif +using namespace KOrg; +extern int globalFlagBlockAgenda; +extern int globalFlagBlockStartup; + +#define SYNC_MODE_NORMAL 0 +#define SYNC_MODE_SHARP 1 +#define SYNC_MODE_QTOPIA 2 + +class KOBeamPrefs : public QDialog +{ + public: + KOBeamPrefs( QWidget *parent=0, const char *name=0 ) : + QDialog( parent, name, true ) + { + setCaption( i18n("Beam Options") ); + QVBoxLayout* lay = new QVBoxLayout( this ); + lay->setSpacing( 3 ); + lay->setMargin( 3 ); + QButtonGroup* format = new QButtonGroup( 1, Horizontal, i18n("File format"), this ); + lay->addWidget( format ); + format->setExclusive ( true ) ; + QButtonGroup* time = new QButtonGroup(1, Horizontal, i18n("Time format"), this ); + lay->addWidget( time ); time->setExclusive ( true ) ; + vcal = new QRadioButton(" vCalendar ", format ); + ical = new QRadioButton(" iCalendar ", format ); + vcal->setChecked( true ); + tz = new QRadioButton(i18n(" With timezone "), time ); + local = new QRadioButton(i18n(" Local time "), time ); + tz->setChecked( true ); + QPushButton * ok = new QPushButton( i18n("Beam via IR!"), this ); + lay->addWidget( ok ); + QPushButton * cancel = new QPushButton( i18n("Cancel"), this ); + lay->addWidget( cancel ); + connect ( ok,SIGNAL(clicked() ),this , SLOT ( accept() ) ); + connect (cancel, SIGNAL(clicked() ), this, SLOT ( reject()) ); + resize( 200, 200 ); + } + + bool beamVcal() { return vcal->isChecked(); } + bool beamLocal() { return local->isChecked(); } +private: + QRadioButton* vcal, *ical, *local, *tz; +}; +class KOCatPrefs : public QDialog +{ + public: + KOCatPrefs( QWidget *parent=0, const char *name=0 ) : + QDialog( parent, name, true ) + { + setCaption( i18n("Manage new Categories") ); + QVBoxLayout* lay = new QVBoxLayout( this ); + lay->setSpacing( 3 ); + lay->setMargin( 3 ); + QLabel * lab = new QLabel( i18n("After importing/loading/syncing\nthere may be new categories in\nevents or todos\nwhich are not in the category list.\nPlease choose what to do:\n "), this ); + lay->addWidget( lab ); + QButtonGroup* format = new QButtonGroup( 1, Horizontal, i18n("New categories not in list:"), this ); + lay->addWidget( format ); + format->setExclusive ( true ) ; + addCatBut = new QRadioButton(i18n("Add to category list"), format ); + new QRadioButton(i18n("Remove from Events/Todos"), format ); + addCatBut->setChecked( true ); + QPushButton * ok = new QPushButton( i18n("OK"), this ); + lay->addWidget( ok ); + QPushButton * cancel = new QPushButton( i18n("Cancel"), this ); + lay->addWidget( cancel ); + connect ( ok,SIGNAL(clicked() ),this , SLOT ( accept() ) ); + connect (cancel, SIGNAL(clicked() ), this, SLOT ( reject()) ); + resize( 200, 200 ); + } + + bool addCat() { return addCatBut->isChecked(); } +private: + QRadioButton* addCatBut; +}; + + + +CalendarView::CalendarView( CalendarResources *calendar, + QWidget *parent, const char *name ) + : CalendarViewBase( parent, name ), + mCalendar( calendar ), + mResourceManager( calendar->resourceManager() ) +{ + + mEventEditor = 0; + mTodoEditor = 0; + + init(); +} + +CalendarView::CalendarView( Calendar *calendar, + QWidget *parent, const char *name ) + : CalendarViewBase( parent, name ), + mCalendar( calendar ), + mResourceManager( 0 ) +{ + + mEventEditor = 0; + mTodoEditor = 0; + init();} + +void CalendarView::init() +{ + beamDialog = new KOBeamPrefs(); + mDatePickerMode = 0; + mCurrentSyncDevice = ""; + writeLocale(); + mViewManager = new KOViewManager( this ); + mDialogManager = new KODialogManager( this ); + mEventViewerDialog = 0; + mModified = false; + mReadOnly = false; + mSelectedIncidence = 0; + mSyncProfiles.setAutoDelete(true); + mCalPrinter = 0; + mFilters.setAutoDelete(true); + + mCalendar->registerObserver( this ); + // TODO: Make sure that view is updated, when calendar is changed. + + mStorage = new FileStorage( mCalendar ); + mNavigator = new DateNavigator( this, "datevav", mViewManager ); + + QBoxLayout *topLayout = (QBoxLayout*)layout(); +#ifndef KORG_NOSPLITTER + // create the main layout frames. + mPanner = new QSplitter(QSplitter::Horizontal,this,"CalendarView::Panner"); + topLayout->addWidget(mPanner); + + mLeftSplitter = new QSplitter(QSplitter::Vertical,mPanner, + "CalendarView::LeftFrame"); + mPanner->setResizeMode(mLeftSplitter,QSplitter::KeepSize); + + mDateNavigator = new KDateNavigator(mLeftSplitter, mCalendar, TRUE, + "CalendarView::DateNavigator", QDate::currentDate() ); + mLeftSplitter->setResizeMode(mDateNavigator,QSplitter::KeepSize); + mTodoList = new KOTodoView(mCalendar, mLeftSplitter, "todolist_small2"); + mFilterView = new KOFilterView(&mFilters,mLeftSplitter,"CalendarView::FilterView"); + +#ifdef KORG_NORESOURCEVIEW + mResourceView = 0; +#else + if ( mResourceManager ) { + mResourceView = new ResourceView( mResourceManager, mLeftSplitter ); + mResourceView->updateView(); + connect( mResourceView, SIGNAL( resourcesChanged() ), + SLOT( updateView() ) ); + } else { + mResourceView = 0; + } +#endif + QWidget *rightBox = new QWidget( mPanner ); + QBoxLayout *rightLayout = new QVBoxLayout( rightBox ); + + mNavigatorBar = new NavigatorBar( QDate::currentDate(), rightBox, "useBigPixmaps" ); + rightLayout->addWidget( mNavigatorBar ); + + mRightFrame = new QWidgetStack( rightBox ); + rightLayout->addWidget( mRightFrame, 1 ); + + mLeftFrame = mLeftSplitter; +#else + QWidget *mainBox = new QWidget( this ); + QWidget *leftFrame = new QWidget( mainBox ); + + QBoxLayout * mainBoxLayout; + QBoxLayout * leftFrameLayout; + if ( KOPrefs::instance()->mVerticalScreen ) { + mainBoxLayout = new QVBoxLayout(mainBox); + leftFrameLayout = new QHBoxLayout(leftFrame ); + } else { + mainBoxLayout = new QHBoxLayout(mainBox); + leftFrameLayout = new QVBoxLayout(leftFrame ); + } + topLayout->addWidget( mainBox ); + mainBoxLayout->addWidget (leftFrame); + mDateNavigator = new KDateNavigator(leftFrame, mCalendar, TRUE, + "CalendarView::DateNavigator", QDate::currentDate()); + // mDateNavigator->blockSignals( true ); + leftFrameLayout->addWidget( mDateNavigator ); + mFilterView = new KOFilterView(&mFilters,leftFrame,"CalendarView::FilterView"); + mTodoList = new KOTodoView(mCalendar, leftFrame, "todolist"); + + if ( QApplication::desktop()->width() < 480 ) { + leftFrameLayout->addWidget(mFilterView); + leftFrameLayout->addWidget(mTodoList, 2 ); + + } else { + leftFrameLayout->addWidget(mTodoList,2 ); + leftFrameLayout->addWidget(mFilterView ); + } + mFilterView->hide(); + QWidget *rightBox = new QWidget( mainBox ); + mainBoxLayout->addWidget ( rightBox, 10 ); + QBoxLayout *rightLayout = new QVBoxLayout( rightBox ); + mNavigatorBar = new NavigatorBar( QDate::currentDate(), rightBox, "useBigPixmaps" ); + mRightFrame = new QWidgetStack( rightBox ); + rightLayout->addWidget( mNavigatorBar ); + rightLayout->addWidget( mRightFrame, 10 ); + + mLeftFrame = leftFrame; + if ( KOPrefs::instance()->mVerticalScreen ) { + mTodoList->setFixedHeight( mDateNavigator->sizeHint().height() ); + leftFrame->setFixedHeight( mDateNavigator->sizeHint().height() ); + } else { + mTodoList->setFixedWidth( mDateNavigator->sizeHint().width() ); + leftFrame->setFixedWidth( mDateNavigator->sizeHint().width() ); + } + + //qDebug("Calendarview Size %d %d ", width(), height()); +#endif + + connect( mNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ), + SLOT( showDates( const KCal::DateList & ) ) ); + connect( mNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ), + mDateNavigator, SLOT( selectDates( const KCal::DateList & ) ) ); + + connect( mNavigatorBar, SIGNAL( goPrevYear() ), + mNavigator, SLOT( selectPreviousYear() ) ); + connect( mNavigatorBar, SIGNAL( goNextYear() ), + mNavigator, SLOT( selectNextYear() ) ); + connect( mNavigatorBar, SIGNAL( goPrevMonth() ), + mNavigator, SLOT( selectPreviousMonth() ) ); + connect( mNavigatorBar, SIGNAL( goNextMonth() ), + mNavigator, SLOT( selectNextMonth() ) ); + + connect( mNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ), + mNavigatorBar, SLOT( selectDates( const KCal::DateList & ) ) ); + + connect( mDateNavigator, SIGNAL( weekClicked( const QDate & ) ), + mNavigator, SLOT( selectWeek( const QDate & ) ) ); + + connect( mDateNavigator, SIGNAL( goPrevYear() ), + mNavigator, SLOT( selectPreviousYear() ) ); + connect( mDateNavigator, SIGNAL( goNextYear() ), + mNavigator, SLOT( selectNextYear() ) ); + connect( mDateNavigator, SIGNAL( goPrevMonth() ), + mNavigator, SLOT( selectPreviousMonth() ) ); + connect( mDateNavigator, SIGNAL( goNextMonth() ), + mNavigator, SLOT( selectNextMonth() ) ); + + connect( mDateNavigator, SIGNAL( goPrevious() ), + mNavigator, SLOT( selectPrevious() ) ); + connect( mDateNavigator, SIGNAL( goNext() ), + mNavigator, SLOT( selectNext() ) ); + connect( mDateNavigator, SIGNAL( monthSelected ( int ) ), + mNavigator, SLOT( slotMonthSelect( int ) ) ); + connect( mNavigatorBar, SIGNAL( monthSelected ( int ) ), + mNavigator, SLOT( slotMonthSelect( int ) ) ); + + connect( mDateNavigator, SIGNAL( datesSelected( const KCal::DateList & ) ), + mNavigator, SLOT( selectDates( const KCal::DateList & ) ) ); + + connect( mDateNavigator, SIGNAL( eventDropped( Event * ) ), + SLOT( eventAdded( Event *) ) ); + + connect(mDateNavigator,SIGNAL(dayPassed(QDate)),SLOT(updateView())); + + connect( this, SIGNAL( configChanged() ), + mDateNavigator, SLOT( updateConfig() ) ); + + connect( mTodoList, SIGNAL( newTodoSignal() ), + SLOT( newTodo() ) ); + connect( mTodoList, SIGNAL( newSubTodoSignal( Todo *) ), + SLOT( newSubTodo( Todo * ) ) ); + connect( mTodoList, SIGNAL( editTodoSignal( Todo * ) ), + SLOT( editTodo( Todo * ) ) ); + connect( mTodoList, SIGNAL( showTodoSignal( Todo * ) ), + SLOT( showTodo( Todo *) ) ); + connect( mTodoList, SIGNAL( deleteTodoSignal( Todo *) ), + SLOT( deleteTodo( Todo *) ) ); + connect( this, SIGNAL( configChanged()), mTodoList, SLOT( updateConfig() ) ); + connect( mTodoList, SIGNAL( purgeCompletedSignal() ), + SLOT( purgeCompleted() ) ); + connect( mTodoList, SIGNAL( todoModifiedSignal( Todo *, int ) ), + SIGNAL( todoModified( Todo *, int ) ) ); + + connect( mTodoList, SIGNAL( cloneTodoSignal( Incidence * ) ), + this, SLOT ( cloneIncidence( Incidence * ) ) ); + connect( mTodoList, SIGNAL( cancelTodoSignal( Incidence * ) ), + this, SLOT (cancelIncidence( Incidence * ) ) ); + + connect( mTodoList, SIGNAL( moveTodoSignal( Incidence * ) ), + this, SLOT ( moveIncidence( Incidence * ) ) ); + connect( mTodoList, SIGNAL( beamTodoSignal( Incidence * ) ), + this, SLOT ( beamIncidence( Incidence * ) ) ); + + connect( mTodoList, SIGNAL( unparentTodoSignal( Todo * ) ), + this, SLOT ( todo_unsub( Todo * ) ) ); + + connect( this, SIGNAL( todoModified( Todo *, int )), mTodoList, + SLOT( updateTodo( Todo *, int ) ) ); + connect( this, SIGNAL( todoModified( Todo *, int )), this, + SLOT( changeTodoDisplay( Todo *, int ) ) ); + + + connect( mFilterView, SIGNAL( filterChanged() ), SLOT( updateFilter() ) ); + connect( mFilterView, SIGNAL( editFilters() ), SLOT( editFilters() ) ); + connect( mCalendar, SIGNAL( addAlarm(const QDateTime &, const QString & ) ), SLOT( addAlarm(const QDateTime &, const QString & ) ) ); + connect( mCalendar, SIGNAL( removeAlarm(const QDateTime &, const QString & ) ), SLOT( removeAlarm(const QDateTime &, const QString & ) ) ); + + + + + + connect(QApplication::clipboard(),SIGNAL(dataChanged()), + SLOT(checkClipboard())); + connect( mTodoList,SIGNAL( incidenceSelected( Incidence * ) ), + SLOT( processTodoListSelection( Incidence * ) ) ); + connect(mTodoList,SIGNAL(isModified(bool)),SLOT(setModified(bool))); + + // kdDebug() << "CalendarView::CalendarView() done" << endl; + + mDateFrame = new QVBox(0,0,WType_Popup); + //mDateFrame->setFrameStyle(QFrame::PopupPanel | QFrame::Raised); + mDateFrame->setFrameStyle( QFrame::WinPanel |QFrame::Raised ); + mDateFrame->setLineWidth(3); + mDateFrame->hide(); + mDateFrame->setCaption( i18n( "Pick a date to display")); + mDatePicker = new KDatePicker ( mDateFrame , QDate::currentDate() ); + + connect(mDatePicker,SIGNAL(dateSelected(QDate)),SLOT(slotSelectPickerDate(QDate))); + + mEventEditor = mDialogManager->getEventEditor(); + mTodoEditor = mDialogManager->getTodoEditor(); + + mFlagEditDescription = false; + + mSuspendTimer = new QTimer( this ); + mAlarmTimer = new QTimer( this ); + connect( mSuspendTimer, SIGNAL( timeout () ), SLOT( suspendAlarm() ) ); + connect( mAlarmTimer, SIGNAL( timeout () ), SLOT( timerAlarm() ) ); + mAlarmDialog = new AlarmDialog( this ); + connect( mAlarmDialog, SIGNAL( addAlarm(const QDateTime &, const QString & ) ), SLOT( addSuspendAlarm(const QDateTime &, const QString & ) ) ); + mAlarmDialog->setServerNotification( false ); + mAlarmDialog->setSuspendTime( KOPrefs::instance()->mAlarmSuspendTime ); +} + + +CalendarView::~CalendarView() +{ + // kdDebug() << "~CalendarView()" << endl; + //qDebug("CalendarView::~CalendarView() "); + delete mDialogManager; + delete mViewManager; + delete mStorage; + delete mDateFrame ; + delete beamDialog; + //kdDebug() << "~CalendarView() done" << endl; +} +void CalendarView::timerAlarm() +{ + //qDebug("CalendarView::timerAlarm() "); + computeAlarm(mAlarmNotification ); +} + +void CalendarView::suspendAlarm() +{ + //qDebug(" CalendarView::suspendAlarm() "); + computeAlarm(mSuspendAlarmNotification ); + +} + +void CalendarView::startAlarm( QString mess , QString filename) +{ + mAlarmDialog->eventNotification( mess, KOPrefs::instance()->mAlarmPlayBeeps, filename, true,KOPrefs::instance()->mAlarmBeepInterval ,KOPrefs::instance()->mAlarmSuspendCount ); + +} + + +void CalendarView::computeAlarm( QString msg ) +{ + + QString mess = msg; + QString mAlarmMessage = mess.mid( 9 ); + QString filename = MainWindow::resourcePath(); + filename += "koalarm.wav"; + QString tempfilename; + if ( mess.left( 13 ) == "suspend_alarm") { + bool error = false; + int len = mess.mid( 13 ).find("+++"); + if ( len < 2 ) + error = true; + else { + tempfilename = mess.mid( 13, len ); + if ( !QFile::exists( tempfilename ) ) + error = true; + } + if ( ! error ) { + filename = tempfilename; + } + mAlarmMessage = mess.mid( 13+len+3 ); + //qDebug("suspend file %s ",tempfilename.latin1() ); + startAlarm( mAlarmMessage, filename); + return; + } + if ( mess.left( 11 ) == "timer_alarm") { + //mTimerTime = 0; + startAlarm( mess.mid( 11 ), filename ); + return; + } + if ( mess.left( 10 ) == "proc_alarm") { + bool error = false; + int len = mess.mid( 10 ).find("+++"); + if ( len < 2 ) + error = true; + else { + tempfilename = mess.mid( 10, len ); + if ( !QFile::exists( tempfilename ) ) + error = true; + } + if ( error ) { + mAlarmMessage = "Procedure Alarm\nError - File not found\n"; + mAlarmMessage += mess.mid( 10+len+3+9 ); + } else { + //QCopEnvelope e("QPE/Application/kopi", "-writeFileSilent"); + //qDebug("-----system command %s ",tempfilename.latin1() ); +#ifndef _WIN32_ + if ( vfork () == 0 ) { + execl ( tempfilename.latin1(), 0 ); + return; + } +#else + QProcess* p = new QProcess(); + p->addArgument( tempfilename.latin1() ); + p->start(); + return; +#endif + + return; + } + + //qDebug("+++++++system command %s ",tempfilename.latin1() ); + } + if ( mess.left( 11 ) == "audio_alarm") { + bool error = false; + int len = mess.mid( 11 ).find("+++"); + if ( len < 2 ) + error = true; + else { + tempfilename = mess.mid( 11, len ); + if ( !QFile::exists( tempfilename ) ) + error = true; + } + if ( ! error ) { + filename = tempfilename; + } + mAlarmMessage = mess.mid( 11+len+3+9 ); + //qDebug("audio file command %s ",tempfilename.latin1() ); + } + if ( mess.left( 9 ) == "cal_alarm") { + mAlarmMessage = mess.mid( 9 ) ; + } + + startAlarm( mAlarmMessage, filename ); + + +} + +void CalendarView::addSuspendAlarm(const QDateTime &qdt, const QString ¬i ) +{ + //qDebug("+++++addSUSPENDAlarm %s %s ", qdt.toString().latin1() , noti.latin1() ); + + mSuspendAlarmNotification = noti; + int ms = QDateTime::currentDateTime().secsTo( qdt )*1000; + //qDebug("Suspend Alarm timer started with secs: %d ", ms/1000); + mSuspendTimer->start( ms , true ); + +} + +void CalendarView::addAlarm(const QDateTime &qdt, const QString ¬i ) +{ + //qDebug("+++++addAlarm %s %s ", qdt.toString().latin1() , noti.latin1() ); + if ( ! KOPrefs::instance()->mUseInternalAlarmNotification ) { +#ifndef DESKTOP_VERSION + AlarmServer::addAlarm ( qdt,"koalarm", noti.latin1() ); +#endif + return; + } + mAlarmNotification = noti; + int ms = QDateTime::currentDateTime().secsTo( qdt )*1000; + //qDebug("Alarm timer started with secs: %d ", ms/1000); + mAlarmTimer->start( ms , true ); + +} +void CalendarView::removeAlarm(const QDateTime &qdt, const QString ¬i ) +{ + //qDebug("-----removeAlarm %s %s ", qdt.toString().latin1() , noti.latin1() ); + if ( ! KOPrefs::instance()->mUseInternalAlarmNotification ) { +#ifndef DESKTOP_VERSION + AlarmServer::deleteAlarm (qdt ,"koalarm" ,noti.latin1() ); +#endif + return; + } + mAlarmTimer->stop(); +} +void CalendarView::selectWeekNum ( int num ) +{ + dateNavigator()->selectWeek( num ); + mViewManager->showWeekView(); +} +KOViewManager *CalendarView::viewManager() +{ + return mViewManager; +} + +KODialogManager *CalendarView::dialogManager() +{ + return mDialogManager; +} + +QDate CalendarView::startDate() +{ + DateList dates = mNavigator->selectedDates(); + + return dates.first(); +} + +QDate CalendarView::endDate() +{ + DateList dates = mNavigator->selectedDates(); + + return dates.last(); +} + + +void CalendarView::createPrinter() +{ +#ifndef KORG_NOPRINTER + if (!mCalPrinter) { + mCalPrinter = new CalPrinter(this, mCalendar); + connect(this, SIGNAL(configChanged()), mCalPrinter, SLOT(updateConfig())); + } +#endif +} + +void CalendarView::confSync() +{ + static KOSyncPrefsDialog* sp = 0; + if ( ! sp ) { + sp = new KOSyncPrefsDialog( this, "syncprefs", true ); + } + sp->usrReadConfig(); +#ifndef DESKTOP_VERSION + sp->showMaximized(); +#else + sp->show(); +#endif + sp->exec(); + +} + + +//KOPrefs::instance()->mWriteBackFile +//KOPrefs::instance()->mWriteBackExistingOnly + +// 0 syncPrefsGroup->addRadio(i18n("Take local entry on conflict")); +// 1 syncPrefsGroup->addRadio(i18n("Take remote entry on conflict")); +// 2 syncPrefsGroup->addRadio(i18n("Take newest entry on conflict")); +// 3 syncPrefsGroup->addRadio(i18n("Ask for every entry on conflict")); +// 4 syncPrefsGroup->addRadio(i18n("Force take local entry always")); +// 5 syncPrefsGroup->addRadio(i18n("Force take remote entry always")); + +int CalendarView::takeEvent( Incidence* local, Incidence* remote, int mode , bool full ) +{ + + //void setZaurusId(int id); + // int zaurusId() const; + // void setZaurusUid(int id); + // int zaurusUid() const; + // void setZaurusStat(int id); + // int zaurusStat() const; + // 0 equal + // 1 take local + // 2 take remote + // 3 cancel + QDateTime lastSync = mLastCalendarSync; + if ( mGlobalSyncMode == SYNC_MODE_SHARP ) { + bool remCh, locCh; + remCh = ( remote->zaurusUid() != local->zaurusUid() ); + locCh = ( local->zaurusStat() != local->revision() ); + //qDebug("locCh %d remCh %d locuid %d remuid %d", locCh, remCh,local->zaurusUid(), remote->zaurusUid() ); + if ( !remCh && ! locCh ) { + //qDebug("both not changed "); + lastSync = local->lastModified().addDays(1); + } else { + if ( locCh ) { + //qDebug("loc changed %d %d", local->zaurusStat(), local->revision() ); + lastSync = local->lastModified().addDays( -1 ); + if ( !remCh ) + remote->setLastModified( lastSync.addDays( -1 ) ); + } else { + //qDebug(" not loc changed "); + lastSync = local->lastModified().addDays( 1 ); + if ( remCh ) + remote->setLastModified( lastSync.addDays( 1 ) ); + + } + } + full = true; + if ( mode < 3 ) + mode = 3; + } else { + if ( local->lastModified() == remote->lastModified() ) + if ( local->revision() == remote->revision() ) + return 0; + + } + // qDebug(" %d %d conflict on %s %s ", mode, full, local->summary().latin1(), remote->summary().latin1() ); + + //qDebug("%s %d %s %d", local->lastModified().toString().latin1() , local->revision(), remote->lastModified().toString().latin1(), remote->revision()); + //qDebug("%d %d %d %d ", local->lastModified().time().second(), local->lastModified().time().msec(), remote->lastModified().time().second(), remote->lastModified().time().msec() ); + //full = true; //debug only + if ( full ) { + bool equ = false; + if ( local->type() == "Event" ) { + equ = (*((Event*) local) == *((Event*) remote)); + } + else if ( local->type() =="Todo" ) + equ = (*((Todo*) local) == (*(Todo*) remote)); + else if ( local->type() =="Journal" ) + equ = (*((Journal*) local) == *((Journal*) remote)); + if ( equ ) { + //qDebug("equal "); + if ( mGlobalSyncMode == SYNC_MODE_SHARP ) { + local->setZaurusUid( remote->zaurusUid() ); + } + if ( mode < 4 ) + return 0; + + }//else //debug only + //qDebug("not equal %s %s ", local->summary().latin1(), remote->summary().latin1()); + } + int result; + bool localIsNew; + if ( full && mode < 2 ) + mode = 3; + + switch( mode ) { + case 0: + if ( lastSync > remote->lastModified() ) + return 1; + if ( lastSync > local->lastModified() ) + return 2; + return 1; + break; + case 1: + if ( lastSync > remote->lastModified() ) + return 1; + if ( lastSync > local->lastModified() ) + return 2; + return 2; + break; + case 2: + if ( local->lastModified() > remote->lastModified() ) + return 1; + else + return 2; + break; + case 3: + //qDebug("lsy %s --- lo %s --- re %s ", lastSync.toString().latin1(), local->lastModified().toString().latin1(), remote->lastModified().toString().latin1() ); + if ( lastSync > remote->lastModified() ) + return 1; + if ( lastSync > local->lastModified() ) + return 2; + //qDebug("lsy %s --- lo %s --- re %s ", lastSync.toString().latin1(), local->lastModified().toString().latin1(), remote->lastModified().toString().latin1() ); + localIsNew = local->lastModified() > remote->lastModified(); + if ( localIsNew ) + getEventViewerDialog()->setColorMode( 1 ); + else + getEventViewerDialog()->setColorMode( 2 ); + getEventViewerDialog()->setIncidence(local); + if ( localIsNew ) + getEventViewerDialog()->setColorMode( 2 ); + else + getEventViewerDialog()->setColorMode( 1 ); + getEventViewerDialog()->addIncidence(remote); + getEventViewerDialog()->setColorMode( 0 ); + //qDebug("local %d remote %d ",local->relatedTo(),remote->relatedTo() ); + getEventViewerDialog()->setCaption( mCurrentSyncDevice +i18n(" : Conflict! Please choose entry!")); + getEventViewerDialog()->showMe(); + result = getEventViewerDialog()->executeS( localIsNew ); + return result; + + break; + case 4: + return 1; + break; + case 5: + return 2; + break; + + default: + break; + } + return 0; +} +Event* CalendarView::getLastSyncEvent() +{ + Event* lse; + //qDebug("CurrentSyncDevice %s ",mCurrentSyncDevice .latin1() ); + lse = mCalendar->event( "last-syncEvent-device-"+mCurrentSyncDevice ); + if (!lse) { + lse = new Event(); + lse->setUid( "last-syncEvent-device-"+mCurrentSyncDevice ); + lse->setSummary(mCurrentSyncDevice + i18n(" - sync event")); + lse->setDtStart( mLastCalendarSync ); + lse->setDtEnd( mLastCalendarSync.addSecs( 7200 ) ); + lse->setCategories( i18n("SyncEvent") ); + lse->setReadOnly( true ); + mCalendar->addEvent( lse ); + } + + return lse; + +} +void CalendarView::checkSharpEvent( Event* lastSync, Incidence* toDelete ) +{ + if ( ! lastSync ) + return; + if ( toDelete->zaurusId() < 0 ) + return; + if ( toDelete->type() == "Journal" ) + return; + QString des = lastSync->description(); + QString pref = "e"; + if ( toDelete->type() == "Todo" ) + pref = "t"; + des += pref+ QString::number ( toDelete->zaurusId() ) + ","; + lastSync->setReadOnly( false ); + lastSync->setDescription( des ); + lastSync->setReadOnly( true ); + +} +bool CalendarView::synchronizeCalendar( Calendar* local, Calendar* remote, int mode ) +{ + bool syncOK = true; + int addedEvent = 0; + int addedEventR = 0; + int deletedEventR = 0; + int deletedEventL = 0; + int changedLocal = 0; + int changedRemote = 0; + //QPtrList<Event> el = local->rawEvents(); + Event* eventR; + QString uid; + int take; + Event* eventL; + Event* eventRSync; + Event* eventLSync; + Event* eventRSyncSharp = remote->event( "last-syncEvent-device-Sharp-DTM"); + Event* eventLSyncSharp = local->event( "last-syncEvent-device-Sharp-DTM"); + bool fullDateRange = false; + mLastCalendarSync = QDateTime::currentDateTime(); + QDateTime modifiedCalendar = mLastCalendarSync;; + eventR = remote->event("last-syncEvent-device-"+mCurrentSyncName ); + if ( eventR ) { + eventRSync = (Event*) eventR->clone(); + remote->deleteEvent(eventR ); + + } else { + fullDateRange = true; + eventRSync = new Event(); + eventRSync->setSummary(mCurrentSyncName + i18n(" - sync event")); + eventRSync->setUid("last-syncEvent-device-"+mCurrentSyncName ); + eventRSync->setDtStart( mLastCalendarSync ); + eventRSync->setDtEnd( mLastCalendarSync.addSecs( 7200 ) ); + eventRSync->setCategories( i18n("SyncEvent") ); + } + eventLSync = getLastSyncEvent(); + if ( eventLSync->dtStart() == mLastCalendarSync ) + fullDateRange = true; + + if ( ! fullDateRange ) { + if ( eventLSync->dtStart() != eventRSync->dtStart() ) { + + // qDebug("set fulldate to true %s %s" ,eventLSync->dtStart().toString().latin1(), eventRSync->dtStart().toString().latin1() ); + //qDebug("%d %d %d %d ", eventLSync->dtStart().time().second(), eventLSync->dtStart().time().msec() , eventRSync->dtStart().time().second(), eventRSync->dtStart().time().msec()); + fullDateRange = true; + } + } + if ( fullDateRange ) + mLastCalendarSync = QDateTime::currentDateTime().addDays( -100*365); + else + mLastCalendarSync = eventLSync->dtStart(); + // for resyncing if own file has changed + if ( mCurrentSyncDevice == "deleteaftersync" ) { + mLastCalendarSync = loadedFileVersion; + qDebug("setting mLastCalendarSync "); + } + //qDebug("*************************** "); + qDebug("mLastCalendarSync %s ",mLastCalendarSync.toString().latin1() ); + QPtrList<Incidence> er = remote->rawIncidences(); + Incidence* inR = er.first(); + Incidence* inL; + QProgressBar bar( er.count(),0 ); + bar.setCaption (i18n("Syncing - close to abort!") ); + + int w = 300; + if ( QApplication::desktop()->width() < 320 ) + w = 220; + int h = bar.sizeHint().height() ; + int dw = QApplication::desktop()->width(); + int dh = QApplication::desktop()->height(); + bar.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); + bar.show(); + int modulo = (er.count()/10)+1; + int incCounter = 0; + while ( inR ) { + if ( ! bar.isVisible() ) + return false; + if ( incCounter % modulo == 0 ) + bar.setProgress( incCounter ); + ++incCounter; + uid = inR->uid(); + bool skipIncidence = false; + if ( uid.left(21) == QString("last-syncEvent-device") ) + skipIncidence = true; + + qApp->processEvents(); + if ( !skipIncidence ) { + inL = local->incidence( uid ); + if ( inL ) { // maybe conflict - same uid in both calendars + int maxrev = inL->revision(); + if ( maxrev < inR->revision() ) + maxrev = inR->revision(); + if ( (take = takeEvent( inL, inR, mode, fullDateRange )) > 0 ) { + //qDebug("take %d %s ", take, inL->summary().latin1()); + if ( take == 3 ) + return false; + if ( take == 1 ) {// take local + inL->setZaurusUid( inR->zaurusUid() ); + remote->deleteIncidence( inR ); + if ( inL->revision() < maxrev ) + inL->setRevision( maxrev ); + remote->addIncidence( inL->clone() ); + ++changedRemote; + } else { + if ( inR->revision() < maxrev ) + inR->setRevision( maxrev ); + local->deleteIncidence( inL ); + local->addIncidence( inR->clone() ); + ++changedLocal; + } + } + } else { // no conflict + if ( mGlobalSyncMode == SYNC_MODE_SHARP ) { + QString des = eventLSync->description(); + QString pref = "e"; + if ( inR->type() == "Todo" ) + pref = "t"; + if ( des.find(pref+QString::number( inR->zaurusId() ) +"," ) >= 0 && mode != 5) { // delete it + inR->setZaurusStat( -3 ); + //remote->deleteIncidence( inR ); + ++deletedEventR; + } else { + inR->setLastModified( modifiedCalendar ); + local->addIncidence( inR->clone() ); + ++addedEvent; + } + } else { + if ( inR->lastModified() > mLastCalendarSync || mode == 5 ) { + inR->setLastModified( modifiedCalendar ); + local->addIncidence( inR->clone() ); + ++addedEvent; + } else { + checkSharpEvent(eventRSyncSharp, inR); + remote->deleteIncidence( inR ); + ++deletedEventR; + } + } + } + } + inR = er.next(); + } + QPtrList<Incidence> el = local->rawIncidences(); + inL = el.first(); + modulo = (el.count()/10)+1; + bar.setCaption (i18n("Add / remove events") ); + bar.setTotalSteps ( el.count() ) ; + bar.show(); + incCounter = 0; + + while ( inL ) { + + qApp->processEvents(); + if ( ! bar.isVisible() ) + return false; + if ( incCounter % modulo == 0 ) + bar.setProgress( incCounter ); + ++incCounter; + uid = inL->uid(); + bool skipIncidence = false; + if ( uid.left(21) == QString("last-syncEvent-device") ) + skipIncidence = true; + if ( mGlobalSyncMode == SYNC_MODE_SHARP && inL->type() == "Journal" ) + skipIncidence = true; + if ( !skipIncidence ) { + inR = remote->incidence( uid ); + if ( ! inR ) { + if ( mGlobalSyncMode == SYNC_MODE_SHARP ) { + if ( inL->zaurusId() >= 0 && mode != 4 ) { + local->deleteIncidence( inL ); + ++deletedEventL; + } else { + if ( ! KOPrefs::instance()->mWriteBackExistingOnly ) { + inL->setZaurusId( -1 ); + ++addedEventR; + inL->setLastModified( modifiedCalendar ); + remote->addIncidence( inL->clone() ); + } + } + } else { + if ( inL->lastModified() < mLastCalendarSync && mode != 4 ) { + checkSharpEvent(eventLSyncSharp, inL); + local->deleteIncidence( inL ); + ++deletedEventL; + } else { + if ( ! KOPrefs::instance()->mWriteBackExistingOnly ) { + ++addedEventR; + inL->setLastModified( modifiedCalendar ); + remote->addIncidence( inL->clone() ); + } + } + } + } + } + inL = el.next(); + } + + bar.hide(); + mLastCalendarSync = QDateTime::currentDateTime().addSecs( 1 ); + eventLSync->setReadOnly( false ); + eventLSync->setDtStart( mLastCalendarSync ); + eventRSync->setDtStart( mLastCalendarSync ); + eventLSync->setDtEnd( mLastCalendarSync.addSecs( 3600 ) ); + eventRSync->setDtEnd( mLastCalendarSync.addSecs( 3600 ) ); + eventRSync->setLocation( i18n("Remote from: ")+mCurrentSyncName ) ; + eventLSync->setLocation(i18n("Local from: ") + mCurrentSyncName ); + eventLSync->setReadOnly( true ); + if ( mGlobalSyncMode == SYNC_MODE_NORMAL) + remote->addEvent( eventRSync ); + QString mes; + mes .sprintf( i18n("Synchronization summary:\n\n %d items added to local\n %d items added to remote\n %d items updated on local\n %d items updated on remote\n %d items deleted on local\n %d items deleted on remote\n"),addedEvent, addedEventR, changedLocal, changedRemote, deletedEventL, deletedEventR ); + if ( KOPrefs::instance()->mShowSyncSummary ) { + KMessageBox::information(this, mes, i18n("KO/Pi Synchronization") ); + } + qDebug( mes ); + mCalendar->checkAlarmForIncidence( 0, true ); + return syncOK; +} + +void CalendarView::setSyncDevice( QString s ) +{ + mCurrentSyncDevice= s; +} +void CalendarView::setSyncName( QString s ) +{ + mCurrentSyncName= s; +} +bool CalendarView::syncCalendar(QString filename, int mode) +{ + mGlobalSyncMode = SYNC_MODE_NORMAL; + CalendarLocal* calendar = new CalendarLocal(); + calendar->setTimeZoneId(KOPrefs::instance()->mTimeZoneId); + FileStorage* storage = new FileStorage( calendar ); + bool syncOK = false; + storage->setFileName( filename ); + // qDebug("loading ... "); + if ( storage->load(KOPrefs::instance()->mUseQuicksave) ) { + getEventViewerDialog()->setSyncMode( true ); + syncOK = synchronizeCalendar( mCalendar, calendar, mode ); + getEventViewerDialog()->setSyncMode( false ); + if ( syncOK ) { + if ( KOPrefs::instance()->mWriteBackFile ) + { + storage->setSaveFormat( new ICalFormat( KOPrefs::instance()->mUseQuicksave) ); + storage->save(); + } + } + setModified( true ); + } + delete storage; + delete calendar; + if ( syncOK ) + updateView(); + return syncOK; +} +void CalendarView::syncSharp() +{ +#ifndef DESKTOP_VERSION + mGlobalSyncMode = SYNC_MODE_SHARP; + //mCurrentSyncDevice = "sharp-DTM"; + if ( KOPrefs::instance()->mAskForPreferences ) + edit_sync_options(); + qApp->processEvents(); + CalendarLocal* calendar = new CalendarLocal(); + calendar->setTimeZoneId(KOPrefs::instance()->mTimeZoneId); + bool syncOK = false; + SharpFormat sharpFormat; + if ( sharpFormat.load( calendar, mCalendar ) ) { + getEventViewerDialog()->setSyncMode( true ); + syncOK = synchronizeCalendar( mCalendar, calendar, KOPrefs::instance()->mSyncAlgoPrefs ); + getEventViewerDialog()->setSyncMode( false ); + qApp->processEvents(); + if ( syncOK ) { + if ( KOPrefs::instance()->mWriteBackFile ) + { + QPtrList<Incidence> iL = mCalendar->rawIncidences(); + Incidence* inc = iL.first(); + while ( inc ) { + inc->setZaurusStat( inc->revision () ); + inc = iL.next(); + } + // pending: clean last sync event description + sharpFormat.save(calendar); + iL = calendar->rawIncidences(); + inc = iL.first(); + Incidence* loc; + while ( inc ) { + if ( inc->zaurusStat() == -4 ) { + loc = mCalendar->incidence(inc->uid() ); + if ( loc ) { + loc->setZaurusId( inc->zaurusId() ); + loc->setZaurusUid( inc->zaurusUid() ); + } + } + inc = iL.next(); + } + Incidence* lse = getLastSyncEvent(); + if ( lse ) { + lse->setReadOnly( false ); + lse->setDescription( "" ); + lse->setReadOnly( true ); + } + } + } + setModified( true ); + } else { + QString question = i18n("Sorry, the database access\ncommand failed!\n\nNothing synced!\n") ; + QMessageBox::information( 0, i18n("KO/Pi Import - ERROR"), + question, i18n("Ok")) ; + + } + delete calendar; + updateView(); + return ;//syncOK; +#endif +} + + +#include <kabc/stdaddressbook.h> +bool CalendarView::importBday() +{ + KABC::StdAddressBook* AddressBook = KABC::StdAddressBook::self( true ); + KABC::AddressBook::Iterator it; + int count = 0; + for( it = AddressBook->begin(); it != AddressBook->end(); ++it ) { + ++count; + } + QProgressBar bar(count,0 ); + int w = 300; + if ( QApplication::desktop()->width() < 320 ) + w = 220; + int h = bar.sizeHint().height() ; + int dw = QApplication::desktop()->width(); + int dh = QApplication::desktop()->height(); + bar.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); + bar.show(); + bar.setCaption (i18n("Reading addressbook - close to abort!") ); + qApp->processEvents(); + count = 0; + int addCount = 0; + KCal::Attendee* a = 0; + for( it = AddressBook->begin(); it != AddressBook->end(); ++it ) { + if ( ! bar.isVisible() ) + return false; + bar.setProgress( count++ ); + qApp->processEvents(); + //qDebug("add BDay %s %s", (*it).realName().latin1(),(*it).birthday().date().toString().latin1() ); + if ( (*it).birthday().date().isValid() ){ + a = new KCal::Attendee( (*it).realName(), (*it).preferredEmail(),false,KCal::Attendee::NeedsAction,KCal::Attendee::ReqParticipant,(*it).uid()) ; + if ( addAnniversary( (*it).birthday().date(), (*it).assembledName(), a, true ) ) + ++addCount; + } + QDate anni = KGlobal::locale()->readDate( (*it).custom("KADDRESSBOOK", "X-Anniversary" ), "%Y-%m-%d"); + if ( anni.isValid() ){ + a = new KCal::Attendee( (*it).realName(), (*it).preferredEmail(),false,KCal::Attendee::NeedsAction,KCal::Attendee::ReqParticipant,(*it).uid()) ; + if ( addAnniversary( anni, (*it).assembledName(), a, false ) ) + ++addCount; + } + } + updateView(); + topLevelWidget()->setCaption(QString::number( addCount )+ i18n(" birthdays/anniversaries added!")); + return true; +} + +bool CalendarView::addAnniversary( QDate date, QString name, KCal::Attendee* a, bool birthday) +{ + //qDebug("addAnni "); + Event * ev = new Event(); + if ( a ) { + ev->addAttendee( a ); + } + QString kind; + if ( birthday ) + kind = i18n( "Birthday" ); + else + kind = i18n( "Anniversary" ); + ev->setSummary( name + " - " + kind ); + ev->setOrganizer( "nobody@nowhere" ); + ev->setCategories( kind ); + ev->setDtStart( QDateTime(date) ); + ev->setDtEnd( QDateTime(date) ); + ev->setFloats( true ); + Recurrence * rec = ev->recurrence(); + rec->setYearly(Recurrence::rYearlyMonth,1,-1); + rec->addYearlyNum( date.month() ); + if ( !mCalendar->addEventNoDup( ev ) ) { + delete ev; + return false; + } + return true; + +} +bool CalendarView::importQtopia( const QString &categories, + const QString &datebook, + const QString &todolist ) +{ + + QtopiaFormat qtopiaFormat; + qtopiaFormat.setCategoriesList ( &(KOPrefs::instance()->mCustomCategories)); + if ( !categories.isEmpty() ) qtopiaFormat.load( mCalendar, categories ); + if ( !datebook.isEmpty() ) qtopiaFormat.load( mCalendar, datebook ); + if ( !todolist.isEmpty() ) qtopiaFormat.load( mCalendar, todolist ); + + updateView(); + return true; + +#if 0 + mGlobalSyncMode = SYNC_MODE_QTOPIA; + mCurrentSyncDevice = "qtopia-XML"; + if ( KOPrefs::instance()->mAskForPreferences ) + edit_sync_options(); + qApp->processEvents(); + CalendarLocal* calendar = new CalendarLocal(); + calendar->setTimeZoneId(KOPrefs::instance()->mTimeZoneId); + bool syncOK = false; + QtopiaFormat qtopiaFormat; + qtopiaFormat.setCategoriesList ( &(KOPrefs::instance()->mCustomCategories)); + bool loadOk = true; + if ( !categories.isEmpty() ) + loadOk = qtopiaFormat.load( calendar, categories ); + if ( loadOk && !datebook.isEmpty() ) + loadOk = qtopiaFormat.load( calendar, datebook ); + if ( loadOk && !todolist.isEmpty() ) + loadOk = qtopiaFormat.load( calendar, todolist ); + + if ( loadOk ) { + getEventViewerDialog()->setSyncMode( true ); + syncOK = synchronizeCalendar( mCalendar, calendar, KOPrefs::instance()->mSyncAlgoPrefs ); + getEventViewerDialog()->setSyncMode( false ); + qApp->processEvents(); + if ( syncOK ) { + if ( KOPrefs::instance()->mWriteBackFile ) + { + // write back XML file + + } + setModified( true ); + } + } else { + QString question = i18n("Sorry, the file loading\ncommand failed!\n\nNothing synced!\n") ; + QMessageBox::information( 0, i18n("KO/Pi Sync - ERROR"), + question, i18n("Ok")) ; + } + delete calendar; + updateView(); + return syncOK; + + +#endif + +} + +void CalendarView::setSyncEventsReadOnly() +{ + Event * ev; + QPtrList<Event> eL = mCalendar->rawEvents(); + ev = eL.first(); + while ( ev ) { + if ( ev->uid().left(21) == QString("last-syncEvent-device") ) + ev->setReadOnly( true ); + ev = eL.next(); + } +} +bool CalendarView::openCalendar(QString filename, bool merge) +{ + + if (filename.isEmpty()) { + return false; + } + + if (!QFile::exists(filename)) { + KMessageBox::error(this,i18n("File does not exist:\n '%1'.").arg(filename)); + return false; + } + + globalFlagBlockAgenda = 1; + if (!merge) mCalendar->close(); + + mStorage->setFileName( filename ); + + if ( mStorage->load(KOPrefs::instance()->mUseQuicksave) ) { + if ( merge ) ;//setModified( true ); + else { + //setModified( true ); + mViewManager->setDocumentId( filename ); + mDialogManager->setDocumentId( filename ); + mTodoList->setDocumentId( filename ); + } + globalFlagBlockAgenda = 2; + // if ( getLastSyncEvent() ) + // getLastSyncEvent()->setReadOnly( true ); + mCalendar->reInitAlarmSettings(); + setSyncEventsReadOnly(); + updateUnmanagedViews(); + updateView(); + if ( filename != MainWindow::defaultFileName() ) + saveCalendar( MainWindow::defaultFileName() ); + loadedFileVersion = QDateTime::currentDateTime(); + return true; + } else { + // while failing to load, the calendar object could + // have become partially populated. Clear it out. + if ( !merge ) mCalendar->close(); + + KMessageBox::error(this,i18n("Couldn't load calendar\n '%1'.").arg(filename)); + + globalFlagBlockAgenda = 2; + updateView(); + } + return false; +} +void CalendarView::setLoadedFileVersion(QDateTime dt) +{ + loadedFileVersion = dt; +} +bool CalendarView::checkFileChanged(QString fn) +{ + QFileInfo finf ( fn ); + if ( !finf.exists() ) + return true; + QDateTime dt = finf.lastModified (); + if ( dt <= loadedFileVersion ) + return false; + return true; + +} +bool CalendarView::checkFileVersion(QString fn) +{ + QFileInfo finf ( fn ); + if ( !finf.exists() ) + return true; + QDateTime dt = finf.lastModified (); + //qDebug("loaded file version %s",loadedFileVersion.toString().latin1()); + //qDebug("file on disk version %s",dt.toString().latin1()); + if ( dt <= loadedFileVersion ) + return true; + int km = KMessageBox::warningYesNoCancel(this, i18n("\nThe file on disk has changed!\nFile size: %1 bytes.\nLast modified: %2\nDo you want to:\n\n - Save and overwrite file?\n - Sync with file, then save?\n - Cancel without saving? \n").arg( QString::number( finf.size())).arg( KGlobal::locale()->formatDateTime(finf.lastModified (), true, false)) , + i18n("KO/Pi Warning"),i18n("Overwrite"), + i18n("Sync+save")); + + if ( km == KMessageBox::Cancel ) + return false; + if ( km == KMessageBox::Yes ) + return true; + + setSyncDevice("deleteaftersync" ); + KOPrefs::instance()->mAskForPreferences = true; + KOPrefs::instance()->mSyncAlgoPrefs = 3; + KOPrefs::instance()->mWriteBackFile = false; + KOPrefs::instance()->mWriteBackExistingOnly = false; + KOPrefs::instance()->mShowSyncSummary = false; + syncCalendar( fn, 3 ); + Event * e = getLastSyncEvent(); + mCalendar->deleteEvent ( e ); + updateView(); + return true; +} + +bool CalendarView::saveCalendar( QString filename ) +{ + + // Store back all unsaved data into calendar object + // qDebug("file %s %d ", filename.latin1() , mViewManager->currentView() ); + if ( mViewManager->currentView() ) + mViewManager->currentView()->flushView(); + + //mStorage->setFileName( filename ); + + mStorage->setSaveFormat( new ICalFormat( KOPrefs::instance()->mUseQuicksave) ); + mStorage->setFileName( filename ); + bool success; + success = mStorage->save(); + if ( !success ) { + return false; + } + + return true; +} + +void CalendarView::closeCalendar() +{ + + // child windows no longer valid + emit closingDown(); + + mCalendar->close(); + setModified(false); + updateView(); +} + +void CalendarView::archiveCalendar() +{ + mDialogManager->showArchiveDialog(); +} + + +void CalendarView::readSettings() +{ + + + // mViewManager->showAgendaView(); + QString str; + //qDebug("CalendarView::readSettings() "); + // read settings from the KConfig, supplying reasonable + // defaults where none are to be found + KConfig *config = KOGlobals::config(); +#ifndef KORG_NOSPLITTER + config->setGroup("KOrganizer Geometry"); + + QValueList<int> sizes = config->readIntListEntry("Separator1"); + if (sizes.count() != 2) { + sizes << mDateNavigator->minimumSizeHint().width(); + sizes << 300; + } + mPanner->setSizes(sizes); + + sizes = config->readIntListEntry("Separator2"); + if ( ( mResourceView && sizes.count() == 4 ) || + ( !mResourceView && sizes.count() == 3 ) ) { + mLeftSplitter->setSizes(sizes); + } +#endif + globalFlagBlockAgenda = 1; + mViewManager->showAgendaView(); + //mViewManager->readSettings( config ); + mTodoList->restoreLayout(config,QString("Todo Layout")); + readFilterSettings(config); + config->setGroup( "Views" ); + int dateCount = config->readNumEntry( "ShownDatesCount", 7 ); + if ( dateCount == 5 ) mNavigator->selectWorkWeek(); + else if ( dateCount == 7 ) mNavigator->selectWeek(); + else mNavigator->selectDates( dateCount ); + // mViewManager->readSettings( config ); + updateConfig(); + globalFlagBlockAgenda = 2; + mViewManager->readSettings( config ); +#ifdef DESKTOP_VERSION + config->setGroup("WidgetLayout"); + QStringList list; + list = config->readListEntry("MainLayout"); + int x,y,w,h; + if ( ! list.isEmpty() ) { + x = list[0].toInt(); + y = list[1].toInt(); + w = list[2].toInt(); + h = list[3].toInt(); + topLevelWidget()->setGeometry(x,y,w,h); + + } else { + topLevelWidget()->setGeometry( 40 ,40 , 640, 440); + } + list = config->readListEntry("EditEventLayout"); + if ( ! list.isEmpty() ) { + x = list[0].toInt(); + y = list[1].toInt(); + w = list[2].toInt(); + h = list[3].toInt(); + mEventEditor->setGeometry(x,y,w,h); + + } + list = config->readListEntry("EditTodoLayout"); + if ( ! list.isEmpty() ) { + x = list[0].toInt(); + y = list[1].toInt(); + w = list[2].toInt(); + h = list[3].toInt(); + mTodoEditor->setGeometry(x,y,w,h); + + } + list = config->readListEntry("ViewerLayout"); + if ( ! list.isEmpty() ) { + x = list[0].toInt(); + y = list[1].toInt(); + w = list[2].toInt(); + h = list[3].toInt(); + getEventViewerDialog()->setGeometry(x,y,w,h); + } +#endif + + + // pending read sync settings; + mSyncProfileNames.clear(); + mSyncProfileNames << "Profile_1"; + mSyncProfileNames << "Profile_2"; + mSyncProfileNames << "Profile_3"; + mSyncProfileNames << "Profile_4"; + mSyncProfileNames << "Profile_5"; + KSyncProfile* temp = new KSyncProfile (); + temp->setName("Profile_1" ); + mSyncProfiles.append( temp ); + temp = new KSyncProfile (); + temp->setName("Profile_2" ); + mSyncProfiles.append( temp ); + temp = new KSyncProfile (); + temp->setName("Profile_3" ); + mSyncProfiles.append( temp ); + temp = new KSyncProfile (); + temp->setName("Profile_4" ); + mSyncProfiles.append( temp ); + temp = new KSyncProfile (); + temp->setName("Profile_5" ); + mSyncProfiles.append( temp ); +} + + +void CalendarView::writeSettings() +{ + // kdDebug() << "CalendarView::writeSettings" << endl; + + KConfig *config = KOGlobals::config(); + +#ifndef KORG_NOSPLITTER + config->setGroup("KOrganizer Geometry"); + + QValueList<int> list = mPanner->sizes(); + config->writeEntry("Separator1",list); + + list = mLeftSplitter->sizes(); + config->writeEntry("Separator2",list); +#endif + + mViewManager->writeSettings( config ); + mTodoList->saveLayout(config,QString("Todo Layout")); + mDialogManager->writeSettings( config ); + //KOPrefs::instance()->usrWriteConfig(); + KOPrefs::instance()->writeConfig(); + + writeFilterSettings(config); + + config->setGroup( "Views" ); + config->writeEntry( "ShownDatesCount", mNavigator->selectedDates().count() ); + +#ifdef DESKTOP_VERSION + config->setGroup("WidgetLayout"); + QStringList list ;//= config->readListEntry("MainLayout"); + int x,y,w,h; + QWidget* wid; + wid = topLevelWidget(); + x = wid->geometry().x(); + y = wid->geometry().y(); + w = wid->width(); + h = wid->height(); + list.clear(); + list << QString::number( x ); + list << QString::number( y ); + list << QString::number( w ); + list << QString::number( h ); + config->writeEntry("MainLayout",list ); + + wid = mEventEditor; + x = wid->geometry().x(); + y = wid->geometry().y(); + w = wid->width(); + h = wid->height(); + list.clear(); + list << QString::number( x ); + list << QString::number( y ); + list << QString::number( w ); + list << QString::number( h ); + config->writeEntry("EditEventLayout",list ); + + wid = mTodoEditor; + x = wid->geometry().x(); + y = wid->geometry().y(); + w = wid->width(); + h = wid->height(); + list.clear(); + list << QString::number( x ); + list << QString::number( y ); + list << QString::number( w ); + list << QString::number( h ); + config->writeEntry("EditTodoLayout",list ); + wid = getEventViewerDialog(); + x = wid->geometry().x(); + y = wid->geometry().y(); + w = wid->width(); + h = wid->height(); + list.clear(); + list << QString::number( x ); + list << QString::number( y ); + list << QString::number( w ); + list << QString::number( h ); + config->writeEntry("ViewerLayout",list ); + wid = mDialogManager->getSearchDialog(); + if ( wid ) { + x = wid->geometry().x(); + y = wid->geometry().y(); + w = wid->width(); + h = wid->height(); + list.clear(); + list << QString::number( x ); + list << QString::number( y ); + list << QString::number( w ); + list << QString::number( h ); + config->writeEntry("SearchLayout",list ); + } +#endif + + + config->sync(); +} + +void CalendarView::readFilterSettings(KConfig *config) +{ + // kdDebug() << "CalendarView::readFilterSettings()" << endl; + + mFilters.clear(); + + config->setGroup("General"); + QStringList filterList = config->readListEntry("CalendarFilters"); + + QStringList::ConstIterator it = filterList.begin(); + QStringList::ConstIterator end = filterList.end(); + while(it != end) { + // kdDebug() << " filter: " << (*it) << endl; + + CalFilter *filter; + filter = new CalFilter(*it); + config->setGroup("Filter_" + (*it)); + //qDebug("readFilterSettings %d ",config->readNumEntry("Criteria",0) ); + filter->setCriteria(config->readNumEntry("Criteria",0)); + filter->setCategoryList(config->readListEntry("CategoryList")); + mFilters.append(filter); + + ++it; + } + + if (mFilters.count() == 0) { + CalFilter *filter = new CalFilter(i18n("Default")); + mFilters.append(filter); + } + mFilterView->updateFilters(); + config->setGroup("FilterView"); + + mFilterView->blockSignals(true); + mFilterView->setFiltersEnabled(config->readBoolEntry("FilterEnabled")); + mFilterView->setSelectedFilter(config->readEntry("Current Filter")); + mFilterView->blockSignals(false); + // We do it manually to avoid it being done twice by the above calls + updateFilter(); +} + +void CalendarView::writeFilterSettings(KConfig *config) +{ + // kdDebug() << "CalendarView::writeFilterSettings()" << endl; + + QStringList filterList; + + CalFilter *filter = mFilters.first(); + while(filter) { + // kdDebug() << " fn: " << filter->name() << endl; + filterList << filter->name(); + config->setGroup("Filter_" + filter->name()); + config->writeEntry("Criteria",filter->criteria()); + config->writeEntry("CategoryList",filter->categoryList()); + filter = mFilters.next(); + } + config->setGroup("General"); + config->writeEntry("CalendarFilters",filterList); + + config->setGroup("FilterView"); + config->writeEntry("FilterEnabled",mFilterView->filtersEnabled()); + config->writeEntry("Current Filter",mFilterView->selectedFilter()->name()); +} + + +void CalendarView::goToday() +{ + mNavigator->selectToday(); +} + +void CalendarView::goNext() +{ + mNavigator->selectNext(); +} + +void CalendarView::goPrevious() +{ + mNavigator->selectPrevious(); +} +void CalendarView::goNextMonth() +{ + mNavigator->selectNextMonth(); +} + +void CalendarView::goPreviousMonth() +{ + mNavigator->selectPreviousMonth(); +} +void CalendarView::writeLocale() +{ + KGlobal::locale()->setHore24Format( !KOPrefs::instance()->mPreferredTime ); + KGlobal::locale()->setWeekStartMonday( !KOPrefs::instance()->mWeekStartsOnSunday ); + KGlobal::locale()->setIntDateFormat( KOPrefs::instance()->mPreferredDate ); + KGlobal::locale()->setLanguage( KOPrefs::instance()->mPreferredLanguage ); + QString dummy = KOPrefs::instance()->mUserDateFormatLong; + KGlobal::locale()->setDateFormat(dummy.replace( QRegExp("K"), QString(",") )); + dummy = KOPrefs::instance()->mUserDateFormatShort; + KGlobal::locale()->setDateFormatShort(dummy.replace( QRegExp("K"), QString(",") )); + KGlobal::locale()->setDaylightSaving( KOPrefs::instance()->mUseDaylightsaving, + KOPrefs::instance()->mDaylightsavingStart, + KOPrefs::instance()->mDaylightsavingEnd ); + KGlobal::locale()->setTimezone( KOPrefs::instance()->mTimeZoneId ); +} +void CalendarView::updateConfig() +{ + writeLocale(); + if ( KOPrefs::instance()->mUseAppColors ) + QApplication::setPalette( QPalette (KOPrefs::instance()->mAppColor1, KOPrefs::instance()->mAppColor2), true ); + emit configChanged(); + mTodoList->updateConfig(); + // mDateNavigator->setFont ( KOPrefs::instance()->mDateNavigatorFont); + mCalendar->setTimeZoneId(KOPrefs::instance()->mTimeZoneId); + // To make the "fill window" configurations work + //mViewManager->raiseCurrentView(); +} + + +void CalendarView::eventChanged(Event *event) +{ + changeEventDisplay(event,KOGlobals::EVENTEDITED); + //updateUnmanagedViews(); +} + +void CalendarView::eventAdded(Event *event) +{ + changeEventDisplay(event,KOGlobals::EVENTADDED); +} + +void CalendarView::eventToBeDeleted(Event *) +{ + kdDebug() << "CalendarView::eventToBeDeleted(): to be implemented" << endl; +} + +void CalendarView::eventDeleted() +{ + changeEventDisplay(0,KOGlobals::EVENTDELETED); +} +void CalendarView::changeTodoDisplay(Todo *which, int action) +{ + changeIncidenceDisplay((Incidence *)which, action); +} +void CalendarView::checkZaurusId( int id, bool todo ) +{ + if ( id >= 0 ) { + Incidence* lse = mCalendar->event( "last-syncEvent-device-Sharp-DTM"); + if ( lse ) { + QString des = lse->description(); + QString pref = "e"; + if ( todo ) + pref = "t"; + des += pref+ QString::number ( id ) + ","; + lse->setReadOnly( false ); + lse->setDescription( des ); + lse->setReadOnly( true ); + } + } +} +void CalendarView::changeIncidenceDisplay(Incidence *which, int action) +{ + updateUnmanagedViews(); + //qDebug(" CalendarView::changeIncidenceDisplay++++++++++++++++++++++++++ %d %d ",which, action ); + if ( action == KOGlobals::EVENTDELETED ) { //delete + mCalendar->checkAlarmForIncidence( 0, true ); + if ( mEventViewerDialog ) + mEventViewerDialog->hide(); + } + else + mCalendar->checkAlarmForIncidence( which , false ); +} + +// most of the changeEventDisplays() right now just call the view's +// total update mode, but they SHOULD be recoded to be more refresh-efficient. +void CalendarView::changeEventDisplay(Event *which, int action) +{ + // kdDebug() << "CalendarView::changeEventDisplay" << endl; + changeIncidenceDisplay((Incidence *)which, action); + mDateNavigator->updateView(); + //mDialogManager->updateSearchDialog(); + + if (which) { + // If there is an event view visible update the display + mViewManager->currentView()->changeEventDisplay(which,action); + // TODO: check, if update needed + // if (which->getTodoStatus()) { + mTodoList->updateView(); + // } + } else { + mViewManager->currentView()->updateView(); + } +} + + +void CalendarView::updateTodoViews() +{ + + mTodoList->updateView(); + mViewManager->currentView()->updateView(); + +} + + +void CalendarView::updateView(const QDate &start, const QDate &end) +{ + mTodoList->updateView(); + mViewManager->updateView(start, end); + //mDateNavigator->updateView(); +} + +void CalendarView::updateView() +{ + DateList tmpList = mNavigator->selectedDates(); + + // We assume that the navigator only selects consecutive days. + updateView( tmpList.first(), tmpList.last() ); +} + +void CalendarView::updateUnmanagedViews() +{ + mDateNavigator->updateDayMatrix(); +} + +int CalendarView::msgItemDelete() +{ + return KMessageBox::warningContinueCancel(this, + i18n("This item will be\npermanently deleted."), + i18n("KO/Pi Confirmation"),i18n("Delete")); +} + + +void CalendarView::edit_cut() +{ + Event *anEvent=0; + + Incidence *incidence = mViewManager->currentView()->selectedIncidences().first(); + + if (mViewManager->currentView()->isEventView()) { + if ( incidence && incidence->type() == "Event" ) { + anEvent = static_cast<Event *>(incidence); + } + } + + if (!anEvent) { + KNotifyClient::beep(); + return; + } + DndFactory factory( mCalendar ); + factory.cutEvent(anEvent); + changeEventDisplay(anEvent, KOGlobals::EVENTDELETED); +} + +void CalendarView::edit_copy() +{ + Event *anEvent=0; + + Incidence *incidence = mViewManager->currentView()->selectedIncidences().first(); + + if (mViewManager->currentView()->isEventView()) { + if ( incidence && incidence->type() == "Event" ) { + anEvent = static_cast<Event *>(incidence); + } + } + + if (!anEvent) { + KNotifyClient::beep(); + return; + } + DndFactory factory( mCalendar ); + factory.copyEvent(anEvent); +} + +void CalendarView::edit_paste() +{ + QDate date = mNavigator->selectedDates().first(); + + DndFactory factory( mCalendar ); + Event *pastedEvent = factory.pasteEvent( date ); + + changeEventDisplay( pastedEvent, KOGlobals::EVENTADDED ); +} + +void CalendarView::edit_options() +{ + mDialogManager->showOptionsDialog(); + //writeSettings(); +} +void CalendarView::edit_sync_options() +{ + //mDialogManager->showSyncOptions(); + //KOPrefs::instance()->mSyncAlgoPrefs + QDialog dia( this, "dia", true ); + dia.setCaption( i18n("Device: " ) +mCurrentSyncDevice ); + QButtonGroup gr ( 1, Qt::Horizontal, i18n("Sync preferences"), &dia); + QVBoxLayout lay ( &dia ); + lay.setSpacing( 2 ); + lay.setMargin( 3 ); + lay.addWidget(&gr); + QRadioButton loc ( i18n("Take local entry on conflict"), &gr ); + QRadioButton rem ( i18n("Take remote entry on conflict"), &gr ); + QRadioButton newest( i18n("Take newest entry on conflict"), &gr ); + QRadioButton ask( i18n("Ask for every entry on conflict"), &gr ); + QRadioButton f_loc( i18n("Force: Take local entry always"), &gr ); + QRadioButton f_rem( i18n("Force: Take remote entry always"), &gr ); + //QRadioButton both( i18n("Take both on conflict"), &gr ); + QPushButton pb ( "OK", &dia); + lay.addWidget( &pb ); + connect(&pb, SIGNAL( clicked() ), &dia, SLOT ( accept() ) ); + switch ( KOPrefs::instance()->mSyncAlgoPrefs ) { + case 0: + loc.setChecked( true); + break; + case 1: + rem.setChecked( true ); + break; + case 2: + newest.setChecked( true); + break; + case 3: + ask.setChecked( true); + break; + case 4: + f_loc.setChecked( true); + break; + case 5: + f_rem.setChecked( true); + break; + case 6: + // both.setChecked( true); + break; + default: + break; + } + if ( dia.exec() ) { + KOPrefs::instance()->mSyncAlgoPrefs = rem.isChecked()*1+newest.isChecked()*2+ ask.isChecked()*3+ f_loc.isChecked()*4+ f_rem.isChecked()*5;//+ both.isChecked()*6 ; + } + +} + +void CalendarView::slotSelectPickerDate( QDate d) +{ + mDateFrame->hide(); + if ( mDatePickerMode == 1 ) { + mNavigator->slotDaySelect( d ); + } else if ( mDatePickerMode == 2 ) { + if ( mMoveIncidence->type() == "Todo" ) { + Todo * to = (Todo *) mMoveIncidence; + QTime tim; + if ( to->hasDueDate() ) + tim = to->dtDue().time(); + else { + tim = QTime ( 0,0,0 ); + to->setFloats( true ); + to->setHasDueDate( true ); + } + QDateTime dt ( d,tim ); + to->setDtDue( dt ); + todoChanged( to ); + } else { + QTime tim = mMoveIncidence->dtStart().time(); + int secs = mMoveIncidence->dtStart().secsTo( mMoveIncidence->dtEnd()); + QDateTime dt ( d,tim ); + mMoveIncidence->setDtStart( dt ); + ((Event*)mMoveIncidence)->setDtEnd( dt.addSecs( secs ) ); + changeEventDisplay((Event*)mMoveIncidence, KOGlobals::EVENTEDITED); + } + + mMoveIncidence->setRevision( mMoveIncidence->revision()+1 ); + } +} + +void CalendarView::removeCategories() +{ + QPtrList<Incidence> incList = mCalendar->rawIncidences(); + QStringList catList = KOPrefs::instance()->mCustomCategories; + QStringList catIncList; + QStringList newCatList; + Incidence* inc = incList.first(); + int i; + int count = 0; + while ( inc ) { + newCatList.clear(); + catIncList = QStringList::split (",", inc->categoriesStr() ); + for( i = 0; i< catIncList.count(); ++i ) { + if ( catList.contains (catIncList[i])) + newCatList.append( catIncList[i] ); + } + newCatList.sort(); + inc->setCategories( newCatList.join(",") ); + inc = incList.next(); + } +} + +int CalendarView::addCategories() +{ + QPtrList<Incidence> incList = mCalendar->rawIncidences(); + QStringList catList = KOPrefs::instance()->mCustomCategories; + QStringList catIncList; + Incidence* inc = incList.first(); + int i; + int count = 0; + while ( inc ) { + catIncList = QStringList::split (",", inc->categoriesStr() ); + for( i = 0; i< catIncList.count(); ++i ) { + if ( !catList.contains (catIncList[i])) { + catList.append( catIncList[i] ); + //qDebug("add cat %s ", catIncList[i].latin1()); + ++count; + } + } + inc = incList.next(); + } + catList.sort(); + KOPrefs::instance()->mCustomCategories = catList; + return count; +} + +void CalendarView::manageCategories() +{ + KOCatPrefs* cp = new KOCatPrefs(); + cp->show(); + int w =cp->sizeHint().width() ; + int h = cp->sizeHint().height() ; + int dw = QApplication::desktop()->width(); + int dh = QApplication::desktop()->height(); + cp->setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); + if ( !cp->exec() ) { + delete cp; + return; + } + int count = 0; + if ( cp->addCat() ) { + count = addCategories(); + if ( count ) { + topLevelWidget()->setCaption(QString::number( count )+ i18n(" Categories added to list! ")); + writeSettings(); + } + } else { + removeCategories(); + updateView(); + } + delete cp; +} + +void CalendarView::beamIncidence(Incidence * Inc) +{ + QPtrList<Incidence> delSel ; + delSel.append(Inc); + beamIncidenceList( delSel ); +} +void CalendarView::beamCalendar() +{ + QPtrList<Incidence> delSel = mCalendar->rawIncidences(); + //qDebug("beamCalendar() "); + beamIncidenceList( delSel ); +} +void CalendarView::beamFilteredCalendar() +{ + QPtrList<Incidence> delSel = mCalendar->incidences(); + //qDebug("beamFilteredCalendar() "); + beamIncidenceList( delSel ); +} +void CalendarView::beamIncidenceList(QPtrList<Incidence> delSel ) +{ + if ( beamDialog->exec () == QDialog::Rejected ) + return; + + QString fn = "/tmp/kopibeamfile"; + QString mes; + bool createbup = true; + if ( createbup ) { + QString description = "\n"; + CalendarLocal* cal = new CalendarLocal(); + if ( beamDialog->beamLocal() ) + cal->setLocalTime(); + else + cal->setTimeZoneId(KOPrefs::instance()->mTimeZoneId); + Incidence *incidence = delSel.first(); + bool addText = false; + if ( delSel.count() < 10 ) + addText = true; + else { + description.sprintf(i18n(" %d items?"),delSel.count() ); + } + while ( incidence ) { + Incidence *in = incidence->clone(); + if ( addText ) + description += in->summary() + "\n"; + cal->addIncidence( in ); + incidence = delSel.next(); + } + if ( beamDialog->beamVcal() ) { + fn += ".vcs"; + FileStorage storage( cal, fn, new VCalFormat ); + storage.save(); + } else { + fn += ".ics"; + FileStorage storage( cal, fn, new ICalFormat( KOPrefs::instance()->mUseQuicksave) ); + storage.save(); + } + delete cal; + mes = i18n("KO/Pi: Ready for beaming"); + setCaption(mes); + +#ifndef DESKTOP_VERSION + Ir *ir = new Ir( this ); + connect( ir, SIGNAL( done( Ir * ) ), this, SLOT( beamDone( Ir * ) ) ); + ir->send( fn, description, "text/x-vCalendar" ); +#endif + } +} +void CalendarView::beamDone( Ir *ir ) +{ +#ifndef DESKTOP_VERSION + delete ir; +#endif +} + +void CalendarView::moveIncidence(Incidence * inc ) +{ + if ( !inc ) return; + // qDebug("showDatePickerForIncidence( ) "); + if ( mDateFrame->isVisible() ) + mDateFrame->hide(); + else { + int w =mDatePicker->sizeHint().width()+2*mDateFrame->lineWidth() ; + int h = mDatePicker->sizeHint().height()+2*mDateFrame->lineWidth() ; + int dw = QApplication::desktop()->width(); + int dh = QApplication::desktop()->height(); + mDateFrame->setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); + mDateFrame->show(); + } + mDatePickerMode = 2; + mMoveIncidence = inc ; + QDate da; + if ( mMoveIncidence->type() == "Todo" ) { + Todo * to = (Todo *) mMoveIncidence; + if ( to->hasDueDate() ) + da = to->dtDue().date(); + else + da = QDate::currentDate(); + } else { + da = mMoveIncidence->dtStart().date(); + } + mDatePicker->setDate( da ); +} +void CalendarView::showDatePicker( ) +{ + //qDebug("CalendarView::showDatePicker( ) "); + if ( mDateFrame->isVisible() ) + mDateFrame->hide(); + else { + int w =mDatePicker->sizeHint().width() ; + int h = mDatePicker->sizeHint().height() ; + int dw = QApplication::desktop()->width(); + int dh = QApplication::desktop()->height(); + mDateFrame->setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); + mDateFrame->show(); + } + mDatePickerMode = 1; + mDatePicker->setDate( mNavigator->selectedDates().first() ); +} + +void CalendarView::showEventEditor() +{ +#ifdef DESKTOP_VERSION + mEventEditor->show(); +#else + mEventEditor->showMaximized(); +#endif +} +void CalendarView::showTodoEditor() +{ +#ifdef DESKTOP_VERSION + mTodoEditor->show(); +#else + mTodoEditor->showMaximized(); +#endif +} +void CalendarView::cancelIncidence(Incidence * inc ) +{ + inc->setCancelled( ! inc->cancelled() ); + changeIncidenceDisplay( inc,KOGlobals::EVENTEDITED ); + updateView(); +} +void CalendarView::cloneIncidence(Incidence * orgInc ) +{ + Incidence * newInc = orgInc->clone(); + newInc->recreate(); + + if ( newInc->type() == "Todo" ) { + Todo* t = (Todo*) newInc; + mTodoEditor->editTodo( t ); + showTodoEditor(); + if ( mTodoEditor->exec() ) { + mCalendar->addTodo( t ); + updateView(); + } else { + delete t; + } + } + else { + Event* e = (Event*) newInc; + mEventEditor->editEvent( e ); + showEventEditor(); + if ( mEventEditor->exec() ) { + mCalendar->addEvent( e ); + updateView(); + } else { + delete e; + } + } +} + +void CalendarView::newEvent() +{ + // TODO: Replace this code by a common eventDurationHint of KOBaseView. + KOAgendaView *aView = mViewManager->agendaView(); + if (aView) { + if (aView->selectionStart().isValid()) { + if (aView->selectedIsAllDay()) { + newEvent(aView->selectionStart(),aView->selectionEnd(),true); + } else { + newEvent(aView->selectionStart(),aView->selectionEnd()); + } + return; + } + } + + QDate date = mNavigator->selectedDates().first(); + QDateTime current = QDateTime::currentDateTime(); + if ( date <= current.date() ) { + int hour = current.time().hour() +1; + newEvent( QDateTime( current.date(), QTime( hour, 0, 0 ) ), + QDateTime( current.date(), QTime( hour+ KOPrefs::instance()->mDefaultDuration, 0, 0 ) ) ); + } else + newEvent( QDateTime( date, QTime( KOPrefs::instance()->mStartTime, 0, 0 ) ), + QDateTime( date, QTime( KOPrefs::instance()->mStartTime + + KOPrefs::instance()->mDefaultDuration, 0, 0 ) ) ); +} + +void CalendarView::newEvent(QDateTime fh) +{ + newEvent(fh, + QDateTime(fh.addSecs(3600*KOPrefs::instance()->mDefaultDuration))); +} + +void CalendarView::newEvent(QDate dt) +{ + newEvent(QDateTime(dt, QTime(0,0,0)), + QDateTime(dt, QTime(0,0,0)), true); +} + +void CalendarView::newEvent(QDateTime fromHint, QDateTime toHint, bool allDay) +{ + + mEventEditor->newEvent(fromHint,toHint,allDay); + if ( mFilterView->filtersEnabled() ) { + CalFilter *filter = mFilterView->selectedFilter(); + if (filter && filter->showCategories()) { + mEventEditor->setCategories(filter->categoryList().join(",") ); + } + if ( filter ) + mEventEditor->setSecrecy( filter->getSecrecy() ); + } + showEventEditor(); +} +void CalendarView::todoAdded(Todo * t) +{ + + changeTodoDisplay ( t ,KOGlobals::EVENTADDED); + updateTodoViews(); +} +void CalendarView::todoChanged(Todo * t) +{ + emit todoModified( t, 4 ); + // updateTodoViews(); +} +void CalendarView::todoToBeDeleted(Todo *) +{ + //qDebug("todoToBeDeleted(Todo *) "); + updateTodoViews(); +} +void CalendarView::todoDeleted() +{ + //qDebug(" todoDeleted()"); + updateTodoViews(); +} + + + +void CalendarView::newTodo() +{ + + mTodoEditor->newTodo(QDateTime::currentDateTime().addDays(7),0,true); + if ( mFilterView->filtersEnabled() ) { + CalFilter *filter = mFilterView->selectedFilter(); + if (filter && filter->showCategories()) { + mTodoEditor->setCategories(filter->categoryList().join(",") ); + } + if ( filter ) + mTodoEditor->setSecrecy( filter->getSecrecy() ); + } + showTodoEditor(); +} + +void CalendarView::newSubTodo() +{ + Todo *todo = selectedTodo(); + if ( todo ) newSubTodo( todo ); +} + +void CalendarView::newSubTodo(Todo *parentEvent) +{ + + mTodoEditor->newTodo(QDateTime::currentDateTime().addDays(7),parentEvent,true); + showTodoEditor(); +} + +void CalendarView::newFloatingEvent() +{ + DateList tmpList = mNavigator->selectedDates(); + QDate date = tmpList.first(); + + newEvent( QDateTime( date, QTime( 12, 0, 0 ) ), + QDateTime( date, QTime( 12, 0, 0 ) ), true ); +} + + +void CalendarView::editEvent( Event *event ) +{ + + if ( !event ) return; + if ( event->isReadOnly() ) { + showEvent( event ); + return; + } + mEventEditor->editEvent( event , mFlagEditDescription); + showEventEditor(); +} +void CalendarView::editJournal( Journal *jour ) +{ + if ( !jour ) return; + mDialogManager->hideSearchDialog(); + mViewManager->showJournalView(); + mNavigator->slotDaySelect( jour->dtStart().date() ); +} +void CalendarView::editTodo( Todo *todo ) +{ + if ( !todo ) return; + + if ( todo->isReadOnly() ) { + showTodo( todo ); + return; + } + mTodoEditor->editTodo( todo ,mFlagEditDescription); + showTodoEditor(); + +} + +KOEventViewerDialog* CalendarView::getEventViewerDialog() +{ + if ( !mEventViewerDialog ) { + mEventViewerDialog = new KOEventViewerDialog(this); + connect( mEventViewerDialog, SIGNAL( editIncidence( Incidence* )), this, SLOT(editIncidence( Incidence* ) ) ); + connect( this, SIGNAL(configChanged()), mEventViewerDialog, SLOT(updateConfig())); + connect( mEventViewerDialog, SIGNAL(jumpToTime( const QDate &)), + dateNavigator(), SLOT( selectWeek( const QDate & ) ) ); + connect( mEventViewerDialog, SIGNAL(showAgendaView( bool ) ), + viewManager(), SLOT( showAgendaView( bool ) ) ); + mEventViewerDialog->resize( 640, 480 ); + + } + return mEventViewerDialog; +} +void CalendarView::showEvent(Event *event) +{ + getEventViewerDialog()->setEvent(event); + getEventViewerDialog()->showMe(); +} + +void CalendarView::showTodo(Todo *event) +{ + getEventViewerDialog()->setTodo(event); + getEventViewerDialog()->showMe(); +} +void CalendarView::showJournal( Journal *jour ) +{ + getEventViewerDialog()->setJournal(jour); + getEventViewerDialog()->showMe(); + +} +// void CalendarView::todoModified (Todo *event, int changed) +// { +// // if (mDialogList.find (event) != mDialogList.end ()) { +// // kdDebug() << "Todo modified and open" << endl; +// // KOTodoEditor* temp = (KOTodoEditor *) mDialogList[event]; +// // temp->modified (changed); + +// // } + +// mViewManager->updateView(); +// } + +void CalendarView::appointment_show() +{ + Event *anEvent = 0; + + Incidence *incidence = mViewManager->currentView()->selectedIncidences().first(); + + if (mViewManager->currentView()->isEventView()) { + if ( incidence && incidence->type() == "Event" ) { + anEvent = static_cast<Event *>(incidence); + } + } + + if (!anEvent) { + KNotifyClient::beep(); + return; + } + + showEvent(anEvent); +} + +void CalendarView::appointment_edit() +{ + Event *anEvent = 0; + + Incidence *incidence = mViewManager->currentView()->selectedIncidences().first(); + + if (mViewManager->currentView()->isEventView()) { + if ( incidence && incidence->type() == "Event" ) { + anEvent = static_cast<Event *>(incidence); + } + } + + if (!anEvent) { + KNotifyClient::beep(); + return; + } + + editEvent(anEvent); +} + +void CalendarView::appointment_delete() +{ + Event *anEvent = 0; + + Incidence *incidence = mViewManager->currentView()->selectedIncidences().first(); + + if (mViewManager->currentView()->isEventView()) { + if ( incidence && incidence->type() == "Event" ) { + anEvent = static_cast<Event *>(incidence); + } + } + + if (!anEvent) { + KNotifyClient::beep(); + return; + } + + deleteEvent(anEvent); +} + +void CalendarView::todo_unsub(Todo *anTodo ) +{ + // Todo *anTodo = selectedTodo(); + if (!anTodo) return; + if (!anTodo->relatedTo()) return; + anTodo->relatedTo()->removeRelation(anTodo); + anTodo->setRelatedTo(0); + anTodo->updated(); + anTodo->setRelatedToUid(""); + setModified(true); + updateView(); +} + +void CalendarView::deleteTodo(Todo *todo) +{ + if (!todo) { + KNotifyClient::beep(); + return; + } + if (KOPrefs::instance()->mConfirm) { + switch (msgItemDelete()) { + case KMessageBox::Continue: // OK + if (!todo->relations().isEmpty()) { + KMessageBox::sorry(this,i18n("Cannot delete To-Do\nwhich has children."), + i18n("Delete To-Do")); + } else { + checkZaurusId( todo->zaurusId(), true ); + calendar()->deleteTodo(todo); + changeTodoDisplay( todo,KOGlobals::EVENTDELETED ); + updateView(); + } + break; + } // switch + } else { + if (!todo->relations().isEmpty()) { + KMessageBox::sorry(this,i18n("Cannot delete To-Do\nwhich has children."), + i18n("Delete To-Do")); + } else { + checkZaurusId( todo->zaurusId(), true ); + mCalendar->deleteTodo(todo); + changeTodoDisplay( todo,KOGlobals::EVENTDELETED ); + updateView(); + } + } + emit updateSearchDialog(); +} +void CalendarView::deleteJournal(Journal *jour) +{ + if (!jour) { + KNotifyClient::beep(); + return; + } + if (KOPrefs::instance()->mConfirm) { + switch (msgItemDelete()) { + case KMessageBox::Continue: // OK + calendar()->deleteJournal(jour); + updateView(); + break; + } // switch + } else { + calendar()->deleteJournal(jour);; + updateView(); + } + emit updateSearchDialog(); +} + +void CalendarView::deleteEvent(Event *anEvent) +{ + if (!anEvent) { + KNotifyClient::beep(); + return; + } + + if (anEvent->recurrence()->doesRecur()) { + QDate itemDate = mViewManager->currentSelectionDate(); + int km; + if (!itemDate.isValid()) { + //kdDebug() << "Date Not Valid" << endl; + if (KOPrefs::instance()->mConfirm) { + km = KMessageBox::warningContinueCancel(this,anEvent->summary() + + i18n("\nThis event recurs\nover multiple dates.\nAre you sure you want\nto delete this event\nand all its recurrences?"), + i18n("KO/Pi Confirmation"),i18n("Delete All")); + if ( km == KMessageBox::Continue ) + km = KMessageBox::No; // No = all below + } else + km = KMessageBox::No; + } else { + km = KMessageBox::warningYesNoCancel(this,anEvent->summary() + + i18n("\nThis event recurs\nover multiple dates.\nDo you want to delete\nall it's recurrences,\nor only the current one on:\n")+ + KGlobal::locale()->formatDate(itemDate)+i18n(" ?\n\nDelete:\n"), + i18n("KO/Pi Confirmation"),i18n("Current"), + i18n("All")); + } + switch(km) { + + case KMessageBox::No: // Continue // all + //qDebug("KMessageBox::No "); + if (anEvent->organizer()==KOPrefs::instance()->email() && anEvent->attendeeCount()>0) + schedule(Scheduler::Cancel,anEvent); + + checkZaurusId( anEvent->zaurusId()); + mCalendar->deleteEvent(anEvent); + changeEventDisplay(anEvent,KOGlobals::EVENTDELETED); + break; + + // Disabled because it does not work + //#if 0 + case KMessageBox::Yes: // just this one + //QDate qd = mNavigator->selectedDates().first(); + //if (!qd.isValid()) { + // kdDebug() << "no date selected, or invalid date" << endl; + // KNotifyClient::beep(); + // return; + //} + //while (!anEvent->recursOn(qd)) qd = qd.addDays(1); + if (itemDate!=QDate(1,1,1) || itemDate.isValid()) { + anEvent->addExDate(itemDate); + int duration = anEvent->recurrence()->duration(); + if ( duration > 0 ) { + anEvent->recurrence()->setDuration( duration - 1 ); + } + changeEventDisplay(anEvent, KOGlobals::EVENTEDITED); + } + break; + //#endif + } // switch + } else { + if (KOPrefs::instance()->mConfirm) { + switch (KMessageBox::warningContinueCancel(this,anEvent->summary() + + i18n("\nAre you sure you want\nto delete this event?"), + i18n("KO/Pi Confirmation"),i18n("Delete"))) { + case KMessageBox::Continue: // OK + if (anEvent->organizer()==KOPrefs::instance()->email() && anEvent->attendeeCount()>0) + schedule(Scheduler::Cancel,anEvent); + checkZaurusId( anEvent->zaurusId()); + mCalendar->deleteEvent(anEvent); + changeEventDisplay(anEvent, KOGlobals::EVENTDELETED); + break; + } // switch + } else { + if (anEvent->organizer()==KOPrefs::instance()->email() && anEvent->attendeeCount()>0) + schedule(Scheduler::Cancel,anEvent); + checkZaurusId( anEvent->zaurusId()); + mCalendar->deleteEvent(anEvent); + changeEventDisplay(anEvent, KOGlobals::EVENTDELETED); + } + } // if-else + emit updateSearchDialog(); +} + +bool CalendarView::deleteEvent(const QString &uid) +{ + Event *ev = mCalendar->event(uid); + if (ev) { + deleteEvent(ev); + return true; + } else { + return false; + } +} + +/*****************************************************************************/ + +void CalendarView::action_mail() +{ +#ifndef KORG_NOMAIL + KOMailClient mailClient; + + Incidence *incidence = currentSelection(); + + if (!incidence) { + KMessageBox::sorry(this,i18n("Can't generate mail:\nNo event selected.")); + return; + } + if(incidence->attendeeCount() == 0 ) { + KMessageBox::sorry(this, + i18n("Can't generate mail:\nNo attendees defined.\n")); + return; + } + + CalendarLocal cal_tmp; + Event *event = 0; + Event *ev = 0; + if ( incidence && incidence->type() == "Event" ) { + event = static_cast<Event *>(incidence); + ev = new Event(*event); + cal_tmp.addEvent(ev); + } + ICalFormat mForm( KOPrefs::instance()->mUseQuicksave); + QString attachment = mForm.toString( &cal_tmp ); + if (ev) delete(ev); + + mailClient.mailAttendees(currentSelection(), attachment); + +#endif + +#if 0 + Event *anEvent = 0; + if (mViewManager->currentView()->isEventView()) { + anEvent = dynamic_cast<Event *>((mViewManager->currentView()->selectedIncidences()).first()); + } + + if (!anEvent) { + KMessageBox::sorry(this,i18n("Can't generate mail:\nNo event selected.")); + return; + } + if(anEvent->attendeeCount() == 0 ) { + KMessageBox::sorry(this, + i18n("Can't generate mail:\nNo attendees defined.\n")); + return; + } + + mailobject.emailEvent(anEvent); +#endif +} + + +void CalendarView::schedule_publish(Incidence *incidence) +{ + Event *event = 0; + Todo *todo = 0; + + if (incidence == 0) { + incidence = mViewManager->currentView()->selectedIncidences().first(); + if (incidence == 0) { + incidence = mTodoList->selectedIncidences().first(); + } + } + if ( incidence && incidence->type() == "Event" ) { + event = static_cast<Event *>(incidence); + } else { + if ( incidence && incidence->type() == "Todo" ) { + todo = static_cast<Todo *>(incidence); + } + } + + if (!event && !todo) { + KMessageBox::sorry(this,i18n("No event selected.")); + return; + } + + PublishDialog *publishdlg = new PublishDialog(); + if (incidence->attendeeCount()>0) { + QPtrList<Attendee> attendees = incidence->attendees(); + attendees.first(); + while ( attendees.current()!=0 ) { + publishdlg->addAttendee(attendees.current()); + attendees.next(); + } + } + bool send = true; + if ( KOPrefs::instance()->mMailClient == KOPrefs::MailClientSendmail ) { + if ( publishdlg->exec() != QDialog::Accepted ) + send = false; + } + if ( send ) { + OutgoingDialog *dlg = mDialogManager->outgoingDialog(); + if ( event ) { + Event *ev = new Event(*event); + ev->registerObserver(0); + ev->clearAttendees(); + if (!dlg->addMessage(ev,Scheduler::Publish,publishdlg->addresses())) { + delete(ev); + } + } else { + if ( todo ) { + Todo *ev = new Todo(*todo); + ev->registerObserver(0); + ev->clearAttendees(); + if (!dlg->addMessage(ev,Scheduler::Publish,publishdlg->addresses())) { + delete(ev); + } + } + } + } + delete publishdlg; +} + +void CalendarView::schedule_request(Incidence *incidence) +{ + schedule(Scheduler::Request,incidence); +} + +void CalendarView::schedule_refresh(Incidence *incidence) +{ + schedule(Scheduler::Refresh,incidence); +} + +void CalendarView::schedule_cancel(Incidence *incidence) +{ + schedule(Scheduler::Cancel,incidence); +} + +void CalendarView::schedule_add(Incidence *incidence) +{ + schedule(Scheduler::Add,incidence); +} + +void CalendarView::schedule_reply(Incidence *incidence) +{ + schedule(Scheduler::Reply,incidence); +} + +void CalendarView::schedule_counter(Incidence *incidence) +{ + schedule(Scheduler::Counter,incidence); +} + +void CalendarView::schedule_declinecounter(Incidence *incidence) +{ + schedule(Scheduler::Declinecounter,incidence); +} + +void CalendarView::schedule_publish_freebusy(int daysToPublish) +{ + QDateTime start = QDateTime::currentDateTime(); + QDateTime end = start.addDays(daysToPublish); + + FreeBusy *freebusy = new FreeBusy(mCalendar, start, end); + freebusy->setOrganizer(KOPrefs::instance()->email()); + + + PublishDialog *publishdlg = new PublishDialog(); + if ( publishdlg->exec() == QDialog::Accepted ) { + OutgoingDialog *dlg = mDialogManager->outgoingDialog(); + if (!dlg->addMessage(freebusy,Scheduler::Publish,publishdlg->addresses())) { + delete(freebusy); + } + } + delete publishdlg; +} + +void CalendarView::schedule(Scheduler::Method method, Incidence *incidence) +{ + Event *event = 0; + Todo *todo = 0; + + if (incidence == 0) { + incidence = mViewManager->currentView()->selectedIncidences().first(); + if (incidence == 0) { + incidence = mTodoList->selectedIncidences().first(); + } + } + if ( incidence && incidence->type() == "Event" ) { + event = static_cast<Event *>(incidence); + } + if ( incidence && incidence->type() == "Todo" ) { + todo = static_cast<Todo *>(incidence); + } + + if (!event && !todo) { + KMessageBox::sorry(this,i18n("No event selected.")); + return; + } + + if( incidence->attendeeCount() == 0 && method != Scheduler::Publish ) { + KMessageBox::sorry(this,i18n("The event has no attendees.")); + return; + } + + Event *ev = 0; + if (event) ev = new Event(*event); + Todo *to = 0; + if (todo) to = new Todo(*todo); + + if (method == Scheduler::Reply || method == Scheduler::Refresh) { + Attendee *me = incidence->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email()); + if (!me) { + KMessageBox::sorry(this,i18n("Could not find your attendee entry.\nPlease check the emails.")); + return; + } + if (me->status()==Attendee::NeedsAction && me->RSVP() && method==Scheduler::Reply) { + StatusDialog *statdlg = new StatusDialog(this); + if (!statdlg->exec()==QDialog::Accepted) return; + me->setStatus( statdlg->status() ); + delete(statdlg); + } + Attendee *menew = new Attendee(*me); + if (ev) { + ev->clearAttendees(); + ev->addAttendee(menew,false); + } else { + if (to) { + todo->clearAttendees(); + todo->addAttendee(menew,false); + } + } + } + + OutgoingDialog *dlg = mDialogManager->outgoingDialog(); + if (ev) { + if ( !dlg->addMessage(ev,method) ) delete(ev); + } else { + if (to) { + if ( !dlg->addMessage(to,method) ) delete(to); + } + } +} + +void CalendarView::openAddressbook() +{ + KRun::runCommand("kaddressbook"); +} + +void CalendarView::setModified(bool modified) +{ + if ( modified ) + emit signalmodified(); + if (mModified != modified) { + mModified = modified; + emit modifiedChanged(mModified); + } +} + +bool CalendarView::isReadOnly() +{ + return mReadOnly; +} + +void CalendarView::setReadOnly(bool readOnly) +{ + if (mReadOnly != readOnly) { + mReadOnly = readOnly; + emit readOnlyChanged(mReadOnly); + } +} + +bool CalendarView::isModified() +{ + return mModified; +} + +void CalendarView::printSetup() +{ +#ifndef KORG_NOPRINTER + createPrinter(); + + mCalPrinter->setupPrinter(); +#endif +} + +void CalendarView::print() +{ +#ifndef KORG_NOPRINTER + createPrinter(); + + DateList tmpDateList = mNavigator->selectedDates(); + mCalPrinter->print(CalPrinter::Month, + tmpDateList.first(), tmpDateList.last()); +#endif +} + +void CalendarView::printPreview() +{ +#ifndef KORG_NOPRINTER + kdDebug() << "CalendarView::printPreview()" << endl; + + createPrinter(); + + DateList tmpDateList = mNavigator->selectedDates(); + + mViewManager->currentView()->printPreview(mCalPrinter,tmpDateList.first(), + tmpDateList.last()); +#endif +} + +void CalendarView::exportICalendar() +{ + QString filename = KFileDialog::getSaveFileName("icalout.ics",i18n("*.ics|ICalendars"),this); + + // Force correct extension + if (filename.right(4) != ".ics") filename += ".ics"; + + FileStorage storage( mCalendar, filename, new ICalFormat( KOPrefs::instance()->mUseQuicksave) ); + storage.save(); +} + +bool CalendarView::exportVCalendar( QString filename ) +{ + if (mCalendar->journals().count() > 0) { + int result = KMessageBox::warningContinueCancel(this, + i18n("The journal entries can not be\nexported to a vCalendar file."), + i18n("Data Loss Warning"),i18n("Proceed"),i18n("Cancel"), + true); + if (result != KMessageBox::Continue) return false; + } + + //QString filename = KFileDialog::getSaveFileName("vcalout.vcs",i18n("*.vcs|VCalendars"),this); + + // Force correct extension + if (filename.right(4) != ".vcs") filename += ".vcs"; + + FileStorage storage( mCalendar, filename, new VCalFormat ); + return storage.save(); + +} + +void CalendarView::eventUpdated(Incidence *) +{ + setModified(); + // Don't call updateView here. The code, which has caused the update of the + // event is responsible for updating the view. + // updateView(); +} + +void CalendarView::adaptNavigationUnits() +{ + if (mViewManager->currentView()->isEventView()) { + int days = mViewManager->currentView()->currentDateCount(); + if (days == 1) { + emit changeNavStringPrev(i18n("&Previous Day")); + emit changeNavStringNext(i18n("&Next Day")); + } else { + emit changeNavStringPrev(i18n("&Previous Week")); + emit changeNavStringNext(i18n("&Next Week")); + } + } +} + +void CalendarView::processMainViewSelection( Incidence *incidence ) +{ + if ( incidence ) mTodoList->clearSelection(); + processIncidenceSelection( incidence ); +} + +void CalendarView::processTodoListSelection( Incidence *incidence ) +{ + if ( incidence && mViewManager->currentView() ) { + mViewManager->currentView()->clearSelection(); + } + processIncidenceSelection( incidence ); +} + +void CalendarView::processIncidenceSelection( Incidence *incidence ) +{ + if ( incidence == mSelectedIncidence ) return; + + mSelectedIncidence = incidence; + + emit incidenceSelected( mSelectedIncidence ); + + if ( incidence && incidence->type() == "Event" ) { + Event *event = static_cast<Event *>( incidence ); + if ( event->organizer() == KOPrefs::instance()->email() ) { + emit organizerEventsSelected( true ); + } else { + emit organizerEventsSelected(false); + } + if (event->attendeeByMails( KOPrefs::instance()->mAdditionalMails, + KOPrefs::instance()->email() ) ) { + emit groupEventsSelected( true ); + } else { + emit groupEventsSelected(false); + } + return; + } else { + if ( incidence && incidence->type() == "Todo" ) { + emit todoSelected( true ); + Todo *event = static_cast<Todo *>( incidence ); + if ( event->organizer() == KOPrefs::instance()->email() ) { + emit organizerEventsSelected( true ); + } else { + emit organizerEventsSelected(false); + } + if (event->attendeeByMails( KOPrefs::instance()->mAdditionalMails, + KOPrefs::instance()->email() ) ) { + emit groupEventsSelected( true ); + } else { + emit groupEventsSelected(false); + } + return; + } else { + emit todoSelected( false ); + emit organizerEventsSelected(false); + emit groupEventsSelected(false); + } + return; + } + + /* if ( incidence && incidence->type() == "Todo" ) { + emit todoSelected( true ); + } else { + emit todoSelected( false ); + }*/ +} + + +void CalendarView::checkClipboard() +{ +#ifndef KORG_NODND + if (ICalDrag::canDecode(QApplication::clipboard()->data())) { + emit pasteEnabled(true); + } else { + emit pasteEnabled(false); + } +#endif +} + +void CalendarView::showDates(const DateList &selectedDates) +{ + // kdDebug() << "CalendarView::selectDates()" << endl; + + if ( mViewManager->currentView() ) { + updateView( selectedDates.first(), selectedDates.last() ); + } else { + mViewManager->showAgendaView(); + } + + QString selDates; + selDates = KGlobal::locale()->formatDate( selectedDates.first(), true); + if (selectedDates.first() < selectedDates.last() ) + selDates += " - " + KGlobal::locale()->formatDate( selectedDates.last(),true); + topLevelWidget()->setCaption( i18n("Dates: ") + selDates ); + +} + +void CalendarView::editFilters() +{ + // kdDebug() << "CalendarView::editFilters()" << endl; + + CalFilter *filter = mFilters.first(); + while(filter) { + kdDebug() << " Filter: " << filter->name() << endl; + filter = mFilters.next(); + } + + mDialogManager->showFilterEditDialog(&mFilters); +} +void CalendarView::toggleFilter() +{ + showFilter(! mFilterView->isVisible()); +} + +void CalendarView::selectFilter( int fil ) +{ + mFilterView->setSelectedFilter( fil ); +} +void CalendarView::showFilter(bool visible) +{ + if (visible) mFilterView->show(); + else mFilterView->hide(); +} +void CalendarView::toggleFilerEnabled( ) +{ + mFilterView->setFiltersEnabled ( !mFilterView->filtersEnabled() ); + if ( !mFilterView->filtersEnabled() ) + topLevelWidget()->setCaption( i18n("Filter disabled ") ); + +} +void CalendarView::updateFilter() +{ + CalFilter *filter = mFilterView->selectedFilter(); + if (filter) { + if (mFilterView->filtersEnabled()) { + topLevelWidget()->setCaption( i18n("Filter selected: ")+filter->name() ); + filter->setEnabled(true); + } + else filter->setEnabled(false); + mCalendar->setFilter(filter); + updateView(); + } +} + +void CalendarView::filterEdited() +{ + mFilterView->updateFilters(); + updateFilter(); + writeSettings(); +} + + +void CalendarView::takeOverEvent() +{ + Incidence *incidence = currentSelection(); + + if (!incidence) return; + + incidence->setOrganizer(KOPrefs::instance()->email()); + incidence->recreate(); + incidence->setReadOnly(false); + + updateView(); +} + +void CalendarView::takeOverCalendar() +{ + // TODO: Create Calendar::allIncidences() function and use it here + + QPtrList<Event> events = mCalendar->events(); + for(uint i=0; i<events.count(); ++i) { + events.at(i)->setOrganizer(KOPrefs::instance()->email()); + events.at(i)->recreate(); + events.at(i)->setReadOnly(false); + } + + QPtrList<Todo> todos = mCalendar->todos(); + for(uint i=0; i<todos.count(); ++i) { + todos.at(i)->setOrganizer(KOPrefs::instance()->email()); + todos.at(i)->recreate(); + todos.at(i)->setReadOnly(false); + } + + QPtrList<Journal> journals = mCalendar->journals(); + for(uint i=0; i<journals.count(); ++i) { + journals.at(i)->setOrganizer(KOPrefs::instance()->email()); + journals.at(i)->recreate(); + journals.at(i)->setReadOnly(false); + } + + updateView(); +} + +void CalendarView::showIntro() +{ + kdDebug() << "To be implemented." << endl; +} + +QWidgetStack *CalendarView::viewStack() +{ + return mRightFrame; +} + +QWidget *CalendarView::leftFrame() +{ + return mLeftFrame; +} + +DateNavigator *CalendarView::dateNavigator() +{ + return mNavigator; +} + +KDateNavigator* CalendarView::dateNavigatorWidget() +{ + return mDateNavigator; +} +void CalendarView::toggleDateNavigatorWidget() +{ + if (mDateNavigator->isVisible()) + mDateNavigator->hide(); + else + mDateNavigator->show(); +} +void CalendarView::addView(KOrg::BaseView *view) +{ + mViewManager->addView(view); +} + +void CalendarView::showView(KOrg::BaseView *view) +{ + mViewManager->showView(view, mLeftFrame->isVisible()); +} + +Incidence *CalendarView::currentSelection() +{ + return mViewManager->currentSelection(); +} +void CalendarView::toggleAllDaySize() +{ + /* + if ( KOPrefs::instance()->mAllDaySize > 47 ) + KOPrefs::instance()->mAllDaySize = KOPrefs::instance()->mAllDaySize /2; + else + KOPrefs::instance()->mAllDaySize = KOPrefs::instance()->mAllDaySize *2; + */ + viewManager()->agendaView()->toggleAllDay(); +} +void CalendarView::toggleExpand() +{ + // if ( mLeftFrame->isHidden() ) { + // mLeftFrame->show(); + // emit calendarViewExpanded( false ); + // } else { + // mLeftFrame->hide(); + // emit calendarViewExpanded( true ); + // } + + globalFlagBlockAgenda = 1; + emit calendarViewExpanded( !mLeftFrame->isHidden() ); + globalFlagBlockAgenda = 5; + mViewManager->raiseCurrentView( !mLeftFrame->isHidden() ); + //mViewManager->showView( 0, true ); +} + +void CalendarView::calendarModified( bool modified, Calendar * ) +{ + setModified( modified ); +} + +Todo *CalendarView::selectedTodo() +{ + Incidence *incidence = currentSelection(); + if ( incidence && incidence->type() == "Todo" ) { + return static_cast<Todo *>( incidence ); + } + + incidence = mTodoList->selectedIncidences().first(); + if ( incidence && incidence->type() == "Todo" ) { + return static_cast<Todo *>( incidence ); + } + + return 0; +} + +void CalendarView::dialogClosing(Incidence *in) +{ + // mDialogList.remove(in); +} + +void CalendarView::showIncidence() +{ + Incidence *incidence = currentSelection(); + if ( !incidence ) incidence = mTodoList->selectedIncidences().first(); + if ( incidence ) { + ShowIncidenceVisitor v; + v.act( incidence, this ); + } +} +void CalendarView::editIncidenceDescription() +{ + mFlagEditDescription = true; + editIncidence(); + mFlagEditDescription = false; +} +void CalendarView::editIncidence() +{ + // qDebug("editIncidence() "); + Incidence *incidence = currentSelection(); + if ( !incidence ) incidence = mTodoList->selectedIncidences().first(); + if ( incidence ) { + EditIncidenceVisitor v; + v.act( incidence, this ); + } +} + +void CalendarView::deleteIncidence() +{ + Incidence *incidence = currentSelection(); + if ( !incidence ) incidence = mTodoList->selectedIncidences().first(); + if ( incidence ) { + deleteIncidence(incidence); + } +} + +void CalendarView::showIncidence(Incidence *incidence) +{ + if ( incidence ) { + ShowIncidenceVisitor v; + v.act( incidence, this ); + } +} + +void CalendarView::editIncidence(Incidence *incidence) +{ + if ( incidence ) { + + EditIncidenceVisitor v; + v.act( incidence, this ); + + } +} + +void CalendarView::deleteIncidence(Incidence *incidence) +{ + //qDebug(" CalendarView::deleteIncidence "); + if ( incidence ) { + DeleteIncidenceVisitor v; + v.act( incidence, this ); + } +} + + +void CalendarView::lookForOutgoingMessages() +{ + OutgoingDialog *ogd = mDialogManager->outgoingDialog(); + ogd->loadMessages(); +} + +void CalendarView::lookForIncomingMessages() +{ + IncomingDialog *icd = mDialogManager->incomingDialog(); + icd->retrieve(); +} + +bool CalendarView::removeCompletedSubTodos( Todo* t ) +{ + bool deleteTodo = true; + QPtrList<Incidence> subTodos; + Incidence *aTodo; + subTodos = t->relations(); + for (aTodo = subTodos.first(); aTodo; aTodo = subTodos.next()) { + if (! removeCompletedSubTodos( (Todo*) aTodo )) + deleteTodo = false; + } + if ( deleteTodo ) { + if ( t->isCompleted() ) { + checkZaurusId( t->zaurusId(), true ); + mCalendar->deleteTodo( t ); + changeTodoDisplay( t,KOGlobals::EVENTDELETED ); + } + else + deleteTodo = false; + } + return deleteTodo; + +} +void CalendarView::purgeCompleted() +{ + int result = KMessageBox::warningContinueCancel(this, + i18n("Delete all\ncompleted To-Dos?"),i18n("Purge To-Dos"),i18n("Purge")); + + if (result == KMessageBox::Continue) { + + QPtrList<Todo> todoCal; + QPtrList<Todo> rootTodos; + //QPtrList<Incidence> rel; + Todo *aTodo;//, *rTodo; + Incidence *rIncidence; + bool childDelete = false; + bool deletedOne = true; + todoCal = calendar()->todos(); + for (aTodo = todoCal.first(); aTodo; aTodo = todoCal.next()) { + if ( !aTodo->relatedTo() ) + rootTodos.append( aTodo ); + } + for (aTodo = rootTodos.first(); aTodo; aTodo = rootTodos.next()) { + removeCompletedSubTodos( aTodo ); + } + + updateView(); + } +} + +void CalendarView::slotCalendarChanged() +{ + ; +} + +NavigatorBar *CalendarView::navigatorBar() +{ + return mNavigatorBar; +} + + + +void CalendarView::keyPressEvent ( QKeyEvent *e) +{ + //qDebug(" alendarView::keyPressEvent "); + e->ignore(); +} + +#include "calendarview.moc" + +#include "calendarviewbase.moc" diff --git a/korganizer/calendarview.h b/korganizer/calendarview.h new file mode 100644 index 0000000..e7aa351 --- a/dev/null +++ b/korganizer/calendarview.h @@ -0,0 +1,586 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000, 2001 + Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef CALENDARVIEW_H +#define CALENDARVIEW_H + +#include <qframe.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qptrlist.h> +#include <qvbox.h> +#include <qmap.h> +#ifndef DESKTOP_VERSION +#include <qtopia/ir.h> +#else +#define Ir char +#endif +#include <libkcal/calendar.h> +#include <libkcal/scheduler.h> +#include <libkcal/calendarresources.h> +#include <libkcal/resourcecalendar.h> + +#include <korganizer/calendarviewbase.h> + +class QWidgetStack; +class QSplitter; + +class CalPrinter; +class KOFilterView; +class KOViewManager; +class KODialogManager; +class KOTodoView; +class KDateNavigator; +class DateNavigator; +class KOIncidenceEditor; +class KDatePicker; +class ResourceView; +class NavigatorBar; +class KOEventEditor; +class KOTodoEditor ; +class KOEventViewerDialog; +class KOBeamPrefs; +class KSyncProfile; +class AlarmDialog; +class KCal::Attendee; + +namespace KCal { class FileStorage; } + +using namespace KCal; + +/** + This is the main calendar widget. It provides the different vies on t he + calendar data as well as the date navigator. It also handles synchronisation + of the different views and controls the different dialogs like preferences, + event editor, search dialog etc. + + @short main calendar view widget + @author Cornelius Schumacher +*/ +class CalendarView : public KOrg::CalendarViewBase, public KCal::Calendar::Observer +{ + Q_OBJECT + public: + /** + Constructs a new calendar view widget. + + @param calendar calendar document + @param parent parent window + @param name Qt internal widget object name + */ + CalendarView( CalendarResources *calendar, QWidget *parent = 0, + const char *name = 0 ); + CalendarView( Calendar *calendar, QWidget *parent = 0, + const char *name = 0 ); + virtual ~CalendarView(); + + Calendar *calendar() { return mCalendar; } + + KOViewManager *viewManager(); + KODialogManager *dialogManager(); + + QDate startDate(); + QDate endDate(); + + QWidgetStack *viewStack(); + QWidget *leftFrame(); + NavigatorBar *navigatorBar(); + + DateNavigator *dateNavigator(); + KDateNavigator *dateNavigatorWidget(); + + void addView(KOrg::BaseView *); + void showView(KOrg::BaseView *); + KOEventViewerDialog* getEventViewerDialog(); + Incidence *currentSelection(); + + signals: + /** This todo has been modified */ + void todoModified(Todo *, int); + + /** when change is made to options dialog, the topwidget will catch this + * and emit this signal which notifies all widgets which have registered + * for notification to update their settings. */ + void configChanged(); + /** emitted when the topwidget is closing down, so that any attached + child windows can also close. */ + void closingDown(); + /** emitted right before we die */ + void closed(QWidget *); + + /** Emitted when state of modified flag changes */ + void modifiedChanged(bool); + void signalmodified(); + + /** Emitted when state of read-only flag changes */ + void readOnlyChanged(bool); + + /** Emitted when the unit of navigation changes */ + void changeNavStringPrev(const QString &); + void changeNavStringNext(const QString &); + + /** Emitted when state of events selection has changed and user is organizer*/ + void organizerEventsSelected(bool); + /** Emitted when state of events selection has changed and user is attendee*/ + void groupEventsSelected(bool); + /** + Emitted when an incidence gets selected. If the selection is cleared the + signal is emitted with 0 as argument. + */ + void incidenceSelected( Incidence * ); + /** Emitted, when a todoitem is selected or deselected. */ + void todoSelected( bool ); + + /** + Emitted, when clipboard content changes. Parameter indicates if paste + is possible or not. + */ + void pasteEnabled(bool); + + /** Emitted, when the number of incoming messages has changed. */ + void numIncomingChanged(int); + + /** Emitted, when the number of outgoing messages has changed. */ + void numOutgoingChanged(int); + + /** Send status message, which can e.g. be displayed in the status bar. */ + void statusMessage(const QString &); + + void calendarViewExpanded( bool ); + void updateSearchDialog(); + + + public slots: + + void addAlarm(const QDateTime &qdt, const QString ¬i ); + void addSuspendAlarm(const QDateTime &qdt, const QString ¬i ); + void removeAlarm(const QDateTime &qdt, const QString ¬i ); + + /** options dialog made a changed to the configuration. we catch this + * and notify all widgets which need to update their configuration. */ + void updateConfig(); + + /** + Load calendar from file \a filename. If \a merge is true, load + calendar into existing one, if it is false, clear calendar, before + loading. Return true, if calendar could be successfully loaded. + */ + bool openCalendar(QString filename, bool merge=false); + bool syncCalendar(QString filename,int mode = 0 ); + + /** + Save calendar data to file. Return true if calendar could be + successfully saved. + */ + bool saveCalendar(QString filename); + + /** + Close calendar. Clear calendar data and reset views to display an empty + calendar. + */ + void closeCalendar(); + + /** Archive old events of calendar */ + void archiveCalendar(); + + void showIncidence(); + void editIncidence(); + void editIncidenceDescription(); + void deleteIncidence(); + + /** create an editeventwin with supplied date/time, and if bool is true, + * make the event take all day. */ + void newEvent(QDateTime, QDateTime, bool allDay = false); + void newEvent(QDateTime fh); + void newEvent(QDate dt); + /** create new event without having a date hint. Takes current date as + default hint. */ + void newEvent(); + void newFloatingEvent(); + + /** Create a read-only viewer dialog for the supplied incidence. It calls the correct showXXX method*/ + void showIncidence(Incidence *); + /** Create an editor for the supplied incidence. It calls the correct editXXX method*/ + void editIncidence(Incidence *); + /** Delete the supplied incidence. It calls the correct deleteXXX method*/ + void deleteIncidence(Incidence *); + void cloneIncidence(Incidence *); + void cancelIncidence(Incidence *); + /** Create an editor for the supplied event. */ + void editEvent(Event *); + /** Delete the supplied event. */ + void deleteEvent(Event *); + /** Delete the event with the given unique ID. Returns false, if event wasn't + found. */ + bool deleteEvent(const QString &uid); + /** Create a read-only viewer dialog for the supplied event. */ + void showEvent(Event *); + + void editJournal(Journal *); + void showJournal(Journal *); + void deleteJournal(Journal *); + /** Create an editor dialog for a todo */ + void editTodo(Todo *); + /** Create a read-only viewer dialog for the supplied todo */ + void showTodo(Todo *); + /** create new todo */ + void newTodo(); + /** create new todo with a parent todo */ + void newSubTodo(); + /** create new todo with a parent todo */ + void newSubTodo(Todo *); + /** Delete todo */ + void deleteTodo(Todo *); + + + /** Check if clipboard contains vCalendar event. The signal pasteEnabled() is + * emitted as result. */ + void checkClipboard(); + + /** using the KConfig associated with the kapp variable, read in the + * settings from the config file. + */ + void readSettings(); + + /** write current state to config file. */ + void writeSettings(); + + /** read settings for calendar filters */ + void readFilterSettings(KConfig *config); + + /** write settings for calendar filters */ + void writeFilterSettings(KConfig *config); + + /** passes on the message that an event has changed to the currently + * activated view so that it can make appropriate display changes. */ + void changeEventDisplay(Event *, int); + void changeIncidenceDisplay(Incidence *, int); + void changeTodoDisplay(Todo *, int); + + void eventAdded(Event *); + void eventChanged(Event *); + void eventToBeDeleted(Event *); + void eventDeleted(); + + void todoAdded(Todo *); + void todoChanged(Todo *); + void todoToBeDeleted(Todo *); + void todoDeleted(); + + void updateView(const QDate &start, const QDate &end); + void updateView(); + + /** Full update of visible todo views */ + void updateTodoViews(); + + void updateUnmanagedViews(); + + /** cut the current appointment to the clipboard */ + void edit_cut(); + + /** copy the current appointment(s) to the clipboard */ + void edit_copy(); + + /** paste the current vobject(s) in the clipboard buffer into calendar */ + void edit_paste(); + + /** edit viewing and configuration options. */ + void edit_options(); + void edit_sync_options(); + /** + Functions for printing, previewing a print, and setting up printing + parameters. + */ + void print(); + void printSetup(); + void printPreview(); + + /** Export as iCalendar file */ + void exportICalendar(); + + /** Export as vCalendar file */ + bool exportVCalendar( QString fn); + + /** pop up a dialog to show an existing appointment. */ + void appointment_show(); + /** + * pop up an Appointment Dialog to edit an existing appointment. Get + * information on the appointment from the list of unique IDs that is + * currently in the View, called currIds. + */ + void appointment_edit(); + /** + * pop up dialog confirming deletion of currently selected event in the + * View. + */ + void appointment_delete(); + + /** mails the currently selected event to a particular user as a vCalendar + attachment. */ + void action_mail(); + + /* frees a subtodo from it's relation */ + void todo_unsub( Todo * ); + + /** Take ownership of selected event. */ + void takeOverEvent(); + + /** Take ownership of all events in calendar. */ + void takeOverCalendar(); + + /** query whether or not the calendar is "dirty". */ + bool isModified(); + /** set the state of calendar. Modified means "dirty", i.e. needing a save. */ + void setModified(bool modified=true); + + /** query if the calendar is read-only. */ + bool isReadOnly(); + /** set state of calendar to read-only */ + void setReadOnly(bool readOnly=true); + + void eventUpdated(Incidence *); + + /* iTIP scheduling actions */ + void schedule_publish(Incidence *incidence = 0); + void schedule_request(Incidence *incidence = 0); + void schedule_refresh(Incidence *incidence = 0); + void schedule_cancel(Incidence *incidence = 0); + void schedule_add(Incidence *incidence = 0); + void schedule_reply(Incidence *incidence = 0); + void schedule_counter(Incidence *incidence = 0); + void schedule_declinecounter(Incidence *incidence = 0); + void schedule_publish_freebusy(int daysToPublish = 30); + + void openAddressbook(); + + void editFilters(); + void toggleFilerEnabled(); + + void toggleFilter(); + void showFilter(bool visible); + void updateFilter(); + void filterEdited(); + void selectFilter( int ); + + void showIntro(); + + /** Move the curdatepient view date to today */ + void goToday(); + + /** Move to the next date(s) in the current view */ + void goNext(); + + /** Move to the previous date(s) in the current view */ + void goPrevious(); + /** Move to the next date(s) in the current view */ + void goNextMonth(); + + /** Move to the previous date(s) in the current view */ + void goPreviousMonth(); + + void toggleExpand(); + void toggleDateNavigatorWidget(); + void toggleAllDaySize(); + void dialogClosing(Incidence *); + + /** Look for new messages in the inbox */ + void lookForIncomingMessages(); + /** Look for new messages in the outbox */ + void lookForOutgoingMessages(); + + void processMainViewSelection( Incidence * ); + void processTodoListSelection( Incidence * ); + + void processIncidenceSelection( Incidence * ); + + void purgeCompleted(); + bool removeCompletedSubTodos( Todo* ); + void slotCalendarChanged(); + bool importBday(); + bool addAnniversary( QDate data, QString name, KCal::Attendee* a , bool birthday ); + bool importQtopia( const QString &categoriesFile, + const QString &datebookFile, + const QString &tasklistFile ); + void syncSharp( ); + void slotSelectPickerDate( QDate ) ; + void showDatePicker( ) ; + void moveIncidence(Incidence *) ; + void beamIncidence(Incidence *) ; + void beamCalendar() ; + void beamFilteredCalendar() ; + void beamIncidenceList(QPtrList<Incidence>) ; + void manageCategories(); + int addCategories(); + void removeCategories(); + void setSyncDevice( QString ); + void setSyncName( QString ); + protected slots: + void timerAlarm(); + void suspendAlarm(); + void beamDone( Ir *ir ); + /** Select a view or adapt the current view to display the specified dates. */ + void showDates( const KCal::DateList & ); + void selectWeekNum ( int ); + + public: + // show a standard warning + // returns KMsgBox::yesNoCancel() + int msgCalModified(); + void confSync(); + void setLoadedFileVersion(QDateTime); + bool checkFileVersion(QString fn); + bool checkFileChanged(QString fn); + Event* getLastSyncEvent(); + /** Adapt navigation units correpsonding to step size of navigation of the + * current view. + */ + void adaptNavigationUnits(); + bool synchronizeCalendar( Calendar* local, Calendar* remote, int mode ); + int takeEvent( Incidence* local, Incidence* remote, int mode, bool full = false ); + //Attendee* getYourAttendee(Event *event); + protected: + void schedule(Scheduler::Method, Incidence *incidence = 0); + + // returns KMsgBox::OKCandel() + int msgItemDelete(); + void showEventEditor(); + void showTodoEditor(); + void writeLocale(); + Todo *selectedTodo(); + + private: + AlarmDialog * mAlarmDialog; + QString mAlarmNotification; + QString mSuspendAlarmNotification; + QTimer* mSuspendTimer; + QTimer* mAlarmTimer; + void computeAlarm( QString ); + void startAlarm( QString, QString ); + void setSyncEventsReadOnly(); + + QDateTime loadedFileVersion; + void checkSharpEvent( Event* lastSync, Incidence* toDelete ); + QPtrList<KSyncProfile> mSyncProfiles; + QStringList mSyncProfileNames; + void checkZaurusId( int id, bool todo = false ); + int mGlobalSyncMode; + QString mCurrentSyncDevice; + QString mCurrentSyncName; + KOBeamPrefs* beamDialog; + void init(); + int mDatePickerMode; + bool mFlagEditDescription; + QDateTime mLastCalendarSync; + void createPrinter(); + + void calendarModified( bool, Calendar * ); + + CalPrinter *mCalPrinter; + + QSplitter *mPanner; + QSplitter *mLeftSplitter; + QWidget *mLeftFrame; + QWidgetStack *mRightFrame; + + KDatePicker* mDatePicker; + QVBox* mDateFrame; + NavigatorBar *mNavigatorBar; + + KDateNavigator *mDateNavigator; // widget showing small month view. + + KOFilterView *mFilterView; + + ResourceView *mResourceView; + + // calendar object for this viewing instance + Calendar *mCalendar; + + CalendarResourceManager *mResourceManager; + + FileStorage *mStorage; + + DateNavigator *mNavigator; + + KOViewManager *mViewManager; + KODialogManager *mDialogManager; + + // Calendar filters + QPtrList<CalFilter> mFilters; + + // various housekeeping variables. + bool mModified; // flag indicating if calendar is modified + bool mReadOnly; // flag indicating if calendar is read-only + QDate mSaveSingleDate; + + Incidence *mSelectedIncidence; + Incidence *mMoveIncidence; + + KOTodoView *mTodoList; + KOEventEditor * mEventEditor; + KOTodoEditor * mTodoEditor; + KOEventViewerDialog * mEventViewerDialog; + void keyPressEvent ( QKeyEvent *e) ; + //QMap<Incidence*,KOIncidenceEditor*> mDialogList; +}; + + +class CalendarViewVisitor : public Incidence::Visitor +{ + public: + CalendarViewVisitor() : mView( 0 ) {} + + bool act( Incidence *incidence, CalendarView *view ) + { + mView = view; + return incidence->accept( *this ); + } + + protected: + CalendarView *mView; +}; + +class ShowIncidenceVisitor : public CalendarViewVisitor +{ + protected: + bool visit( Event *event ) { mView->showEvent( event ); return true; } + bool visit( Todo *todo ) { mView->showTodo( todo ); return true; } + bool visit( Journal * j ) { mView->showJournal( j );return true; } +}; + +class EditIncidenceVisitor : public CalendarViewVisitor +{ + protected: + bool visit( Event *event ) { mView->editEvent( event ); return true; } + bool visit( Todo *todo ) { mView->editTodo( todo ); return true; } + bool visit( Journal *j ) { mView->editJournal( j); return true; } +}; + +class DeleteIncidenceVisitor : public CalendarViewVisitor +{ + protected: + bool visit( Event *event ) { mView->deleteEvent( event ); return true; } + bool visit( Todo *todo ) { mView->deleteTodo( todo ); return true; } + bool visit( Journal * j) {mView->deleteJournal( j ); return true; } +}; + +#endif diff --git a/korganizer/calendarview.moc b/korganizer/calendarview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/calendarview.moc diff --git a/korganizer/calendarviewbase.moc b/korganizer/calendarviewbase.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/calendarviewbase.moc diff --git a/korganizer/calprintbase.cpp b/korganizer/calprintbase.cpp new file mode 100644 index 0000000..af32ebc --- a/dev/null +++ b/korganizer/calprintbase.cpp @@ -0,0 +1,1304 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 1998 Preston Brown + Copyright (c) 2003 Reinhold Kainhofer <reinhold@kainhofer.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qpainter.h> +#include <qlayout.h> +#include <qframe.h> +#include <qlabel.h> +#include <qptrlist.h> +#include <qintdict.h> +#include <qfontmetrics.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kcalendarsystem.h> +#include <kprinter.h> + +#include <libkcal/todo.h> +#include <libkcal/event.h> +#include <libkcal/calendar.h> + +#include "koprefs.h" +#include "koglobals.h" +#ifndef KORG_NOPLUGINS +#include "kocore.h" +#endif +#include "cellitem.h" + +#include "calprintbase.h" + +#ifndef KORG_NOPRINTER +//#include "calprintbase.moc" + +int CalPrintBase::mHeaderHeight=90; +int CalPrintBase::mSubHeaderHeight=20; +int CalPrintBase::mMargin=36; + + + +class CalPrintBase::TodoParentStart +{ + public: + TodoParentStart( QRect pt = QRect(), bool page = true ) + : mRect( pt ), mSamePage( page ) {} + + QRect mRect; + bool mSamePage; +}; + +class PrintCellItem : public KOrg::CellItem +{ + public: + PrintCellItem( Event *event, const QDate &day ) + : mEvent( event ), mDay( day ) + { + } + + Event *event() const { return mEvent; } + + QString label() const { return mEvent->summary(); } + + bool overlaps( KOrg::CellItem *o ) const + { + PrintCellItem *other = static_cast<PrintCellItem *>( o ); + + QDateTime start = event()->dtStart(); + QDateTime end = event()->dtEnd(); + if ( event()->doesRecur() ) { + start.setDate( mDay ); + end.setDate( mDay ); + } + QDateTime otherStart = other->event()->dtStart(); + QDateTime otherEnd = other->event()->dtEnd(); + if ( other->event()->doesRecur() ) { + otherStart.setDate( mDay ); + otherEnd.setDate( mDay ); + } + +#if 0 + kdDebug() << "PrintCellItem::overlaps() " << event()->summary() + << " <-> " << other->event()->summary() << endl; + kdDebug() << " start : " << start.toString() << endl; + kdDebug() << " end : " << end.toString() << endl; + kdDebug() << " otherStart: " << otherStart.toString() << endl; + kdDebug() << " otherEnd : " << otherEnd.toString() << endl; +#endif + + return !( otherStart >= end || otherEnd <= start ); + } + + private: + Event *mEvent; + QDate mDay; +}; + +void setCategoryColors( QPainter &p, Incidence *incidence) +{ + QColor bgColor; + QStringList categories = incidence->categories(); + QString cat = categories.first(); + if (cat.isEmpty()) + bgColor = KOPrefs::instance()->mEventColor; + else + bgColor = *(KOPrefs::instance()->categoryColor(cat)); + QColor textColor = Qt::black;//getTextColor(bgColor); + p.setPen( textColor ); + p.setBrush( bgColor ); +} + + + +CalPrintBase::CalPrintBase( KPrinter *printer, Calendar *cal, KConfig *cfg ) + : QObject(), mPrinter( printer ), mCalendar( cal ), mConfig( cfg ) +{ +} + +CalPrintBase::~CalPrintBase() +{ +} + + + +QWidget *CalPrintBase::configWidget( QWidget *w ) +{ + QFrame *wdg = new QFrame( w ); + QVBoxLayout *layout = new QVBoxLayout( wdg ); + + QLabel *title = new QLabel( description(), wdg ); + QFont titleFont( title->font() ); + titleFont.setPointSize( 20 ); + titleFont.setBold( true ); + title->setFont( titleFont ); + + layout->addWidget( title ); + layout->addWidget( new QLabel( longDescription(), wdg ) ); + layout->addSpacing( 20 ); + layout->addWidget( new QLabel( i18n("This printing style does not " + "have any configuration options."), + wdg ) ); + layout->addStretch(); + return wdg; +} +#include <qapplication.h> +void CalPrintBase::doPrint() +{ + QPainter p; + + mPrinter->setColorMode( (mUseColors)?(KPrinter::Color):(KPrinter::GrayScale)); + //#define DUMMY_PRINTER +#ifdef DUMMY_PRINTER + + static QWidget* dummy = 0; + if ( ! dummy ) + dummy = new QWidget( ); + else { + delete dummy; + dummy = new QWidget( ); + + } + dummy->resize( 1024, 1024 ); + dummy->repaint(); + dummy->show(); + dummy->raise(); + dummy->setBackgroundColor( Qt::white); + qApp->processEvents(); + p.begin(dummy); +#else + p.begin(mPrinter); +#endif + // the painter initially begins at 72 dpi per the Qt docs. + // we want half-inch margins. + p.setViewport(mMargin, mMargin, + p.viewport().width()-mMargin, + p.viewport().height()-mMargin); + int pageWidth = p.viewport().width(); + int pageHeight = p.viewport().height(); + + print(p, pageWidth, pageHeight); + + p.end(); +} + +void CalPrintBase::doLoadConfig() +{ + if ( mConfig ) { + mConfig->setGroup(description()); + //KConfigGroupSaver saver( mConfig, description() ); + mConfig->sync(); + QDateTime currDate( QDate::currentDate() ); + mFromDate = mConfig->readDateTimeEntry( "FromDate", &currDate ).date(); + mToDate = mConfig->readDateTimeEntry( "ToDate" ).date(); + mUseColors = mConfig->readBoolEntry( "UseColors", false ); + loadConfig(); + } else { + qDebug("no config in CalPrintBase::doLoadConfig "); + } +} + +void CalPrintBase::doSaveConfig() +{ + if ( mConfig ) { + mConfig->setGroup(description()); + // KConfigGroupSaver saver( mConfig, description() ); + saveConfig(); + mConfig->writeEntry( "FromDate", QDateTime( mFromDate ) ); + mConfig->writeEntry( "ToDate", QDateTime( mToDate ) ); + mConfig->writeEntry( "UseColors", mUseColors ); + mConfig->sync(); + } else { + qDebug("no config in CalPrintBase::doSveConfig "); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void CalPrintBase::drawHeader( QPainter &p, QString title, + const QDate &month1, const QDate &month2, + int x, int y, int width, int height ) +{ + p.drawRect(x, y, width, height); + // p.fillRect( x+1, y+1, +// width-2,height-2, +// QBrush(Dense7Pattern) ); + + QString myOwner(mCalendar->getOwner()); + + int right=x+width; + + // print previous month for month view, print current for todo, day and week + int smallMonthWidth=width/4-10; + if (smallMonthWidth>100) smallMonthWidth=100; + if (month2.isValid()) { + right -= (10+smallMonthWidth); + drawSmallMonth(p, QDate(month2.year(), month2.month(), 1), + right, y+2, smallMonthWidth, height-4); + right-=10; + } + if (month1.isValid()) { + right -= (10+smallMonthWidth); + drawSmallMonth(p, QDate(month1.year(), month1.month(), 1), + right, y+2, smallMonthWidth, height-4); + right-=10; + } + + // Print the titles... + QFont font("helvetica", 18, QFont::Bold); + p.setFont(font); + QRect textRect( x+5, y+5, right-10-x, height-10 ); + p.drawText( textRect, Qt::AlignLeft | Qt::AlignTop | Qt::WordBreak, title ); +} + + +void CalPrintBase::drawSmallMonth(QPainter &p, const QDate &qd, + int x, int y, int width, int height) +{ + bool firstCol = true; + QDate monthDate(QDate(qd.year(), qd.month(), 1)); + QDate monthDate2; + int month = monthDate.month(); + + // draw the title + p.setFont(QFont("helvetica", 7, QFont::Bold)); + // int lineSpacing = p.fontMetrics().lineSpacing(); + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + p.drawText(x, y, width, height/4, AlignCenter, calSys->monthName( qd ) ); + + int cellWidth = width/7; + int cellHeight = height/8; + QString tmpStr; + + // correct begin of week + int weekdayCol = weekdayColumn( qd.dayOfWeek() ); + monthDate2 = monthDate.addDays(-weekdayCol); + + // draw days of week + p.setFont(QFont("helvetica", 7, QFont::Bold)); + for (int col = 0; col < 7; col++) { + // tmpStr.sprintf("%c",(const char*)monthDate2.dayName(monthDate2.dayOfWeek())); + tmpStr=calSys->weekDayName( monthDate2 )[0].upper(); + p.drawText(x+col*cellWidth, y+height/4, cellWidth, cellHeight, + AlignCenter, tmpStr); + monthDate2 = monthDate2.addDays(1); + } + + // draw separator line + p.drawLine(x, y+height/4+cellHeight, x+width, y+height/4+cellHeight); + + for (int row = 0; row < 5; row++) { + for (int col = 0; col < 7; col++) { + if (monthDate.month() != month) + break; + if (firstCol) { + firstCol = true; + col = weekdayColumn( monthDate.dayOfWeek() ); + } + p.drawText( x+col*cellWidth, + y+height/4+cellHeight+(row*cellHeight), + cellWidth, cellHeight, AlignCenter, + tmpStr.setNum(monthDate.day()) ); + monthDate = monthDate.addDays(1); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// + +/* + * This routine draws a header box over the main part of the calendar + * containing the days of the week. + */ +void CalPrintBase::drawDaysOfWeek(QPainter &p, + const QDate &fromDate, const QDate &toDate, + int x, int y, int width, int height) +{ + int cellWidth = width/(fromDate.daysTo( toDate )+1); + int currx=x; + QDate cellDate(fromDate); + + while (cellDate<=toDate) { + drawDaysOfWeekBox(p, cellDate, currx, y, cellWidth, height); + currx+=cellWidth; + cellDate = cellDate.addDays(1); + } +} + + +void CalPrintBase::drawDaysOfWeekBox(QPainter &p, const QDate &qd, + int x, int y, int width, int height) +{ + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + + p.setFont( QFont( "helvetica", 10, QFont::Bold ) ); + p.drawRect( x, y, width, height ); +// p.fillRect( x+1, y+1, +// width-2, height-2, +// QBrush( Dense7Pattern ) ); + p.drawText( x+5, y, width-10, height, AlignCenter | AlignVCenter, + calSys->weekDayName( qd ) ); +} + + +void CalPrintBase::drawTimeLine(QPainter &p, + const QTime &fromTime, const QTime &toTime, + int x, int y, int width, int height) +{ + p.drawRect(x, y, width, height); + + int totalsecs=fromTime.secsTo(toTime); + float minlen=(float)height*60./(float)totalsecs; + float cellHeight=(60.*(float)minlen); + float currY=y; + + QTime curTime( fromTime ); + QTime endTime( toTime ); + if ( fromTime.minute() > 30 ) + curTime = QTime( fromTime.hour()+1, 0, 0 ); + else if ( fromTime.minute() > 0 ) { + curTime = QTime( fromTime.hour(), 30, 0 ); + float yy = currY + minlen*(float)fromTime.secsTo( curTime )/60.; + p.drawLine( x+width/2, (int)yy, x+width, (int)yy ); + curTime = QTime( fromTime.hour()+1, 0, 0 ); + } + currY += ( fromTime.secsTo(curTime)*minlen/60 ); + + while ( curTime < endTime ) { + p.drawLine( x, (int)currY, x+width, (int)currY ); + int newY=(int)(currY+cellHeight/2.); + QString numStr; + if (newY < y+height) { + p.drawLine(x+width/2, (int)newY, x+width, (int)newY); + // draw the time: + if ( !KGlobal::locale()->use12Clock() ) { + numStr.setNum(curTime.hour()); + if (cellHeight > 30) { + p.setFont(QFont("helvetica", 16, QFont::Bold)); + } else { + p.setFont(QFont("helvetica", 12, QFont::Bold)); + } + p.drawText(x+2, (int)currY+2, width/2-2, (int)cellHeight, + AlignTop|AlignRight, numStr); + p.setFont(QFont("helvetica", 10, QFont::Normal)); + p.drawText(x+width/2, (int)currY+2, width/2+2, (int)(cellHeight/2)-3, + AlignTop | AlignLeft, "00"); + } else { + QTime time( curTime.hour(), 0 ); + numStr = KGlobal::locale()->formatTime( time ); + p.setFont(QFont("helvetica", 14, QFont::Bold)); + p.drawText(x+2, (int)currY+2, width-4, (int)cellHeight/2-3, + AlignTop|AlignLeft, numStr); + } + currY+=cellHeight; + } // enough space for half-hour line and time + if (curTime.secsTo(endTime)>3600) + curTime=curTime.addSecs(3600); + else curTime=endTime; + } // currTime<endTime +} + + +/////////////////////////////////////////////////////////////////////////////// + +/** prints the all-day box for the agenda print view. if expandable is set, + height is the cell height of a single cell, and the returned height will + be the total height used for the all-day events. If !expandable, only one + cell will be used, and multiple events are concatenated using ", ". +*/ +void CalPrintBase::drawAllDayBox(QPainter &p, Event::List &eventList, + const QDate &qd, bool expandable, + int x, int y, int width, int &height) +{ + Event::List::Iterator it, itold; + + int offset=y; + + //p.setBrush(QBrush(Dense7Pattern)); + QPen oldPen(p.pen()); + QColor oldBgColor(p.backgroundColor()); + QBrush oldBrush(p.brush()); + QString multiDayStr; + + it = eventList.begin(); +#ifndef KORG_NOPLUGINS + QString hstring(KOCore::self()->holiday(qd)); + if (!hstring.isEmpty()) { + Event*holiday=new Event(); + holiday->setDtStart(qd); + holiday->setDtEnd(qd); + holiday->setFloats(true); + holiday->setCategories(i18n("Holiday")); + eventList.prepend(holiday); + } +#endif + Event *currEvent = 0; + // First, print all floating events + while( it!=eventList.end() ) { + currEvent=*it; + itold=it; + ++it; + if ( currEvent->doesFloat() ) { + // set the colors according to the categories + QString text = currEvent->summary() ; + if ( ! currEvent->location().isEmpty() ) + text += " ("+currEvent->location()+")"; + if (expandable) { + if (mUseColors) + setCategoryColors(p, currEvent); + + p.drawRect( x, offset, width, height ); + + p.drawText( x+5, offset+5, width-10, height-10, + AlignCenter | AlignVCenter | AlignJustify | WordBreak, + text ); + // reset the colors + p.setBrush( oldBrush ); + p.setPen( oldPen ); + p.setBackgroundColor(oldBgColor); + + offset += height; + } else { + //if (!multiDayStr.isEmpty()) multiDayStr+=", "; + multiDayStr += text+"\n"; + } + eventList.remove( itold ); + } + } + + if (!expandable) { + p.drawRect(x, offset, width, height); + if (!multiDayStr.isEmpty()) { + // p.fillRect(x+1, offset+1, width-2, height-2, QBrush(Dense5Pattern) ); + p.drawText( x+5, offset+5, width-10, height-10, + AlignLeft | AlignTop | AlignJustify , + multiDayStr); + } + } else { + height=offset-y; + } +} + + +void CalPrintBase::drawAgendaDayBox( QPainter &p, Event::List &events, + const QDate &qd, bool expandable, + QTime &fromTime, QTime &toTime, + int x, int y, int width, int height ) +{ + p.drawRect( x, y, width, height ); + + Event *event; + + if ( expandable ) { + // Adapt start/end times to include complete events + Event::List::ConstIterator it; + for ( it = events.begin(); it != events.end(); ++it ) { + event = *it; + if ( event->dtStart().time() < fromTime ) + fromTime = event->dtStart().time(); + if ( event->dtEnd().time() > toTime ) + toTime = event->dtEnd().time(); + } + } + + // Show at least one hour + if ( fromTime.secsTo( toTime ) < 3600 ) { + fromTime = QTime( fromTime.hour(), 0, 0 ); + toTime = fromTime.addSecs( 3600 ); + } + + // calculate the height of a cell and of a minute + int totalsecs = fromTime.secsTo( toTime ); + float minlen = height * 60. / totalsecs; + float cellHeight = 60. * minlen; + float currY = y; + + // print grid: + QTime curTime( QTime( fromTime.hour(), 0, 0 ) ); + currY += fromTime.secsTo( curTime ) * minlen / 60; + + while ( curTime < toTime && curTime.isValid() ) { + if ( currY > y ) p.drawLine( x, int( currY ), x + width, int( currY ) ); + currY += cellHeight / 2; + if ( ( currY > y ) && ( currY < y + height ) ) { + QPen oldPen( p.pen() ); + p.setPen( QColor( 192, 192, 192 ) ); + p.drawLine( x, int( currY ), x + width, int( currY ) ); + p.setPen( oldPen ); + } // enough space for half-hour line + if ( curTime.secsTo( toTime ) > 3600 ) + curTime = curTime.addSecs( 3600 ); + else curTime = toTime; + currY += cellHeight / 2; + } + + QDateTime startPrintDate = QDateTime( qd, fromTime ); + QDateTime endPrintDate = QDateTime( qd, toTime ); + + // Calculate horizontal positions and widths of events taking into account + // overlapping events + + QPtrList<KOrg::CellItem> cells; + cells.setAutoDelete( true ); + + Event::List::ConstIterator itEvents; + for( itEvents = events.begin(); itEvents != events.end(); ++itEvents ) { + cells.append( new PrintCellItem( *itEvents, qd ) ); + } + + QPtrListIterator<KOrg::CellItem> it1( cells ); + for( it1.toFirst(); it1.current(); ++it1 ) { + KOrg::CellItem *placeItem = it1.current(); + + KOrg::CellItem::placeItem( cells, placeItem ); + } + + QPen oldPen = p.pen(); + QColor oldBgColor = p.backgroundColor(); + QBrush oldBrush = p.brush(); + + p.setFont( QFont( "helvetica", 10 ) ); + //p.setBrush( QBrush( Dense7Pattern ) ); + + for( it1.toFirst(); it1.current(); ++it1 ) { + PrintCellItem *placeItem = static_cast<PrintCellItem *>( it1.current() ); + + drawAgendaItem( placeItem, p, qd, startPrintDate, endPrintDate, minlen, x, + y, width ); + + p.setBrush( oldBrush ); + p.setPen( oldPen ); + p.setBackgroundColor( oldBgColor ); + } + + p.setBrush( QBrush( NoBrush ) ); +} + + +void CalPrintBase::drawAgendaItem( PrintCellItem *item, QPainter &p, + const QDate &qd, + const QDateTime &startPrintDate, + const QDateTime &endPrintDate, + float minlen, int x, int y, int width ) +{ + Event *event = item->event(); + + // set the colors according to the categories + if ( mUseColors ) setCategoryColors( p, event ); + else p.setBrush( Qt::white ); + // start/end of print area for event + QDateTime startTime = event->dtStart(); + QDateTime endTime = event->dtEnd(); + if ( event->doesRecur() ) { + startTime.setDate( qd ); + endTime.setDate( qd ); + } + if ( ( startTime < endPrintDate && endTime > startPrintDate ) || + ( endTime > startPrintDate && startTime < endPrintDate ) ) { + if ( startTime < startPrintDate ) startTime = startPrintDate; + if ( endTime > endPrintDate ) endTime = endPrintDate; + int eventLength = int( startTime.secsTo( endTime ) / 60. * minlen ); + int currentyPos = int( y + startPrintDate.secsTo( startTime ) * + minlen / 60. ); + int currentWidth = width / item->subCells(); + int currentX = x + item->subCell() * currentWidth; + QString text = KGlobal::locale()->formatTime(event->dtStart().time())+ + "-"+KGlobal::locale()->formatTime(event->dtEnd().time())+ + " "+event->summary(); + if ( !event->location().isEmpty() ) + text += " (" +event->location()+")"; + // p.save(); + QPen pe = p.pen(); + pe.setWidth( 2 ); + p.setPen( pe ); + p.drawRect( currentX, currentyPos+1, currentWidth+1, eventLength+1 ); + p.drawText( currentX+3, currentyPos+2, currentWidth-5, eventLength-3, + AlignLeft | AlignTop | AlignJustify | WordBreak, + text); + // p.restore(); + } +} + +void CalPrintBase::drawDayBox(QPainter &p, const QDate &qd, + int x, int y, int width, int height, + bool fullDate) +{ + QString dayNumStr; + QString ampm; + const KLocale*local = KGlobal::locale(); + + + // This has to be localized + if (fullDate) { + /*int index; + dayNumStr= qd.toString(); + index = dayNumStr.find(' '); + dayNumStr.remove(0, index); + index = dayNumStr.findRev(' '); + dayNumStr.truncate(index);*/ + + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + dayNumStr = i18n("weekday month date", "%1 %2 %3") + .arg( calSys->weekDayName( qd ) ) + .arg( calSys->monthName( qd ) ) + .arg( qd.day() ); +// dayNumStr = local->formatDate(qd); + } else { + dayNumStr = QString::number( qd.day() ); + } + + p.eraseRect( x, y, width, height ); + p.drawRect( x, y, width, height ); + // p.fillRect( x+1, y+1, width-2,height, QBrush(Dense7Pattern) ); + p.drawRect( x, y, width, mSubHeaderHeight ); + //p.fillRect( x+1, y+1, width-2, mSubHeaderHeight-2, QBrush(Dense7Pattern) ); + QString hstring; +#ifndef KORG_NOPLUGINS + hstring=KOCore::self()->holiday(qd); +#endif + + if (!hstring.isEmpty()) { + p.setFont( QFont( "helvetica", 8, QFont::Bold, true ) ); + + p.drawText( x+5, y, width-25, mSubHeaderHeight, AlignLeft | AlignVCenter, + hstring ); + } + p.setFont(QFont("helvetica", 10, QFont::Bold)); + p.drawText(x+5, y, width-10, mSubHeaderHeight, AlignRight | AlignVCenter, + dayNumStr); + Event::List eventList; + eventList.fill( mCalendar->events( qd, true )); + Todo::List todos; + todos.fill( mCalendar->todos( qd )); + QString outStr; + p.setFont( QFont( "helvetica", 8 ) ); + int lineSpacing = p.fontMetrics().lineSpacing(); + + int textY=mSubHeaderHeight+3; // gives the relative y-coord of the next printed entry + Event::List::ConstIterator it; + int entryCount = eventList.count() +todos.count(); + if ( p.fontMetrics().lineSpacing()* entryCount > height-textY ) { + if ( (p.fontMetrics().lineSpacing()-1) * entryCount > height-textY ) { + p.setFont( QFont( "helvetica", 7 ) ); + if ( (p.fontMetrics().lineSpacing()-1) * entryCount > height-textY ) + p.setFont( QFont( "helvetica", 6 ) ); + } + lineSpacing = p.fontMetrics().lineSpacing()-1; + } + // qDebug("fm %d %d %d ",p.fontMetrics().height(), eventList.count() , height-textY ); + for( it = eventList.begin(); it != eventList.end() && textY<height; ++it ) { + Event *currEvent = *it; + if (currEvent->doesFloat() || currEvent->isMultiDay()) + outStr = currEvent->summary(); + + else { + if ( fullDate ) { + outStr = KGlobal::locale()->formatTime( currEvent->dtStart().time())+ + "-"+KGlobal::locale()->formatTime( currEvent->dtEnd().time())+ + " "+ currEvent->summary(); + if ( ! currEvent->location().isEmpty() ) + outStr += " (" + currEvent->location()+")"; + } else { + QTime t1 = currEvent->dtStart().time(); + + outStr = local->formatTime(t1); + outStr += " " + currEvent->summary(); + } + + } // doesFloat + + p.drawText(x+5, y+textY, width-10, lineSpacing, + AlignLeft|AlignBottom, outStr); + textY+=lineSpacing; + } + + if ( textY<height ) { + + Todo::List::ConstIterator it2; + for( it2 = todos.begin(); it2 != todos.end() && textY<height; ++it2 ) { + Todo *todo = *it2; + QString text; + if (todo->hasDueDate()) { + if (!todo->doesFloat()) { + text += KGlobal::locale()->formatTime(todo->dtDue().time()); + text += " "; + } + } + text += i18n("To-Do: %1").arg(todo->summary()); + + p.drawText(x+5, y+textY, width-10, lineSpacing, + AlignLeft|AlignBottom, text); + textY+=lineSpacing; + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// + +void CalPrintBase::drawWeek(QPainter &p, const QDate &qd, + int x, int y, int width, int height) +{ + QDate weekDate = qd; + bool portrait = ( mPrinter->orientation() == KPrinter::Portrait ); + int cellWidth, cellHeight; + int vcells; + if (portrait) { + cellWidth = width/2; + vcells=3; + } else { + cellWidth = width/6; + vcells=1; + } + cellHeight = height/vcells; + + // correct begin of week + int weekdayCol = weekdayColumn( qd.dayOfWeek() ); + weekDate = qd.addDays( -weekdayCol ); + + for (int i = 0; i < 7; i++, weekDate = weekDate.addDays(1)) { + if (i<5) { + drawDayBox(p, weekDate, x+cellWidth*(int)(i/vcells), y+cellHeight*(i%vcells), + cellWidth, cellHeight, true); + } else if (i==5) { + drawDayBox(p, weekDate, x+cellWidth*(int)(i/vcells), y+cellHeight*(i%vcells), + cellWidth, cellHeight/2, true); + } else if (i==6) { + drawDayBox(p, weekDate, x+cellWidth*(int)((i-1)/vcells), + y+cellHeight*((i-1)%vcells)+cellHeight/2, cellWidth, cellHeight/2, true); + } + } // for i through all weekdays +} + + +void CalPrintBase::drawTimeTable(QPainter &p, + const QDate &fromDate, const QDate &toDate, + QTime &fromTime, QTime &toTime, + int x, int y, int width, int height) +{ + // timeline is 1.5 hours: + int alldayHeight = (int)( 3600.*height/(fromTime.secsTo(toTime)+3600.) ); + int timelineWidth = 60; + int cellWidth = (int)( (width-timelineWidth)/(fromDate.daysTo(toDate)+1) ); + int currY=y; + int currX=x; + + drawDaysOfWeek( p, fromDate, toDate, x+timelineWidth, currY, width-timelineWidth, mSubHeaderHeight); + currY+=mSubHeaderHeight; + drawTimeLine( p, fromTime, toTime, x, currY+alldayHeight, + timelineWidth, height-mSubHeaderHeight-alldayHeight ); + + currX=x+timelineWidth; + // draw each day + QDate curDate(fromDate); + while (curDate<=toDate) {Event::List eventList; + eventList.fill( mCalendar->events(curDate, true)); + drawAllDayBox( p, eventList, curDate, false, currX, currY, cellWidth, alldayHeight); + drawAgendaDayBox( p, eventList, curDate, false, fromTime, toTime, currX, + currY+alldayHeight, cellWidth, height-mSubHeaderHeight-alldayHeight ); + currX+=cellWidth; + curDate=curDate.addDays(1); + } + +} + + +/////////////////////////////////////////////////////////////////////////////// + +void CalPrintBase::drawMonth(QPainter &p, const QDate &qd, bool weeknumbers, + int x, int y, int width, int height) +{ + + int yoffset = mSubHeaderHeight; + int xoffset = 0; + + QDate monthDate(QDate(qd.year(), qd.month(), 1)); + QDate monthFirst(monthDate); + QDate monthLast(monthDate.addMonths(1).addDays(-1)); + + + int weekdayCol = weekdayColumn( monthDate.dayOfWeek() ); + monthDate = monthDate.addDays(-weekdayCol); + + int rows=(weekdayCol + qd.daysInMonth() - 1)/7 +1; + int cellHeight = (height-yoffset) / rows; + + if (weeknumbers) { + QFont oldFont(p.font()); + QFont newFont(p.font()); + newFont.setPointSize(7); + p.setFont(newFont); + xoffset += 18; + QDate weekDate(monthDate); + for (int row = 0; row<rows; row++) { + int calWeek = weekDate.weekNumber(); + QRect rc(x, y+yoffset+cellHeight*row, xoffset-1, cellHeight); + p.drawText( rc, AlignRight|AlignVCenter, QString::number(calWeek) ); + weekDate = weekDate.addDays(7); + } + p.setFont(oldFont); + } + + drawDaysOfWeek( p, monthDate, monthDate.addDays(6), x+xoffset, y, width-xoffset, mSubHeaderHeight ); + int cellWidth = (width-xoffset) / 7; + + QColor back = p.backgroundColor(); + bool darkbg = false; + for (int row = 0; row < rows; row++) { + for (int col = 0; col < 7; col++) { + // show days from previous/next month with a grayed background + if ( (monthDate < monthFirst) || (monthDate > monthLast) ) { + p.setBackgroundColor( QColor( 240, 240, 240) ); + darkbg = true; + } + drawDayBox(p, monthDate, x+xoffset+col*cellWidth, y+yoffset+row*cellHeight, cellWidth, cellHeight); + if ( darkbg ) { + p.setBackgroundColor( back ); + darkbg = false; + } + monthDate = monthDate.addDays(1); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////// + +void CalPrintBase::drawTodo( bool completed, int &count, Todo * item, QPainter &p, bool connectSubTodos, + bool desc, int pospriority, int possummary, int posDueDt, int level, + int x, int &y, int width, int &height, int pageHeight, + TodoParentStart *r ) +{ + if ( !completed && item->isCompleted() ) + return; + QString outStr; +// int fontHeight = 10; + const KLocale *local = KGlobal::locale(); + int priority=item->priority(); + int posdue=posDueDt; + if (posdue<0) posdue=x+width; + QRect rect; + TodoParentStart startpt; + // This list keeps all starting points of the parent todos so the connection + // lines of the tree can easily be drawn (needed if a new page is started) + static QPtrList<TodoParentStart> startPoints; + if (level<1) { + startPoints.clear(); + } + + // size of item + outStr=item->summary(); + if ( ! item->location().isEmpty() ) + outStr += " ("+item->location()+")"; + if ( item->hasDueDate() && posDueDt>=0 ) { + outStr += " [" +local->formatDate(item->dtDue().date(),true)+"]"; + } + int left = possummary+(level*10); + rect = p.boundingRect(left, y, (posdue-left-5),-1, WordBreak, outStr); + if ( !item->description().isEmpty() && !desc ) { + outStr = item->description(); + rect = p.boundingRect( left+20, rect.bottom()+5, width-(left+10-x), -1, + WordBreak, outStr ); + } + // if too big make new page + if ( rect.bottom() > y+height) { + // first draw the connection lines from parent todos: + if (level > 0 && connectSubTodos) { + TodoParentStart *rct; + for ( rct = startPoints.first(); rct; rct = startPoints.next() ) { + int start; + int center = rct->mRect.left() + (rct->mRect.width()/2); + int to = p.viewport().bottom(); + + // draw either from start point of parent or from top of the page + if (rct->mSamePage) + start = rct->mRect.bottom() + 1; + else + start = p.viewport().top(); + p.moveTo( center, start ); + p.lineTo( center, to ); + rct->mSamePage=false; + } + } + y=0; + height=pageHeight-y; + mPrinter->newPage(); + } + + // If this is a sub-item, r will not be 0, and we want the LH side of the priority line up + //to the RH side of the parent item's priority + if (r && pospriority >= 0 ) { + pospriority = r->mRect.right() + 1; + } + + // Priority + outStr.setNum(priority); + rect = p.boundingRect(pospriority, y + 10, 5, -1, AlignCenter, outStr); + // Make it a more reasonable size + rect.setWidth(19); + rect.setHeight(19); + if ( priority > 0 && pospriority>=0 ) { + p.drawText(rect, AlignCenter, outStr); + p.drawRect(rect); + // cross out the rectangle for completed items + if ( item->isCompleted() ) { + p.drawLine( rect.topLeft(), rect.bottomRight() ); + p.drawLine( rect.topRight(), rect.bottomLeft() ); + } + } + startpt.mRect = rect; //save for later + + // Connect the dots + if (level > 0 && connectSubTodos) { + int bottom; + int center( r->mRect.left() + (r->mRect.width()/2)+1 ); + if (r->mSamePage ) + bottom = r->mRect.bottom();//lutz + 1; + else + bottom = 0; + int to( rect.top() + (rect.height()/2)+1 ); + int endx( rect.left() ); + p.moveTo(center, bottom); + p.lineTo(center, to); + p.lineTo(endx, to); + } + + // if completed, use strike out font + QFont ft=p.font(); + ft.setStrikeOut( item->isCompleted() ); + p.setFont( ft ); + // summary + outStr=item->summary(); + if ( ! item->location().isEmpty() ) + outStr += " ("+item->location()+")"; + if ( item->hasDueDate() && posDueDt>=0 ) { + outStr += " [" +local->formatDate(item->dtDue().date(),true)+"]"; + } + rect = p.boundingRect( left, rect.top(), (posdue-(left + rect.width() + 5)), + -1, WordBreak, outStr); + QRect newrect; + p.drawText( rect, WordBreak, outStr, -1, &newrect ); + ft.setStrikeOut(false); + p.setFont(ft); + + // due + // if ( item->hasDueDate() && posDueDt>=0 ) { +// outStr = local->formatDate(item->dtDue().date(),true); +// rect = p.boundingRect(posdue, y, x+width, -1, AlignTop|AlignLeft, outStr); +// p.drawText(rect, AlignTop|AlignLeft, outStr); +// } + + if ( !item->description().isEmpty() && desc ) { + y=newrect.bottom() + 5; + outStr = item->description(); + rect = p.boundingRect( left+20, y, x+width-(left+10), -1, + WordBreak, outStr ); + p.drawText( rect, WordBreak, outStr, -1, &newrect ); + } + + // Set the new line position + y=newrect.bottom() + 10; //set the line position + + // If the item has subitems, we need to call ourselves recursively + Incidence::List l;l.fill( item->relations()); + Incidence::List::ConstIterator it; + startPoints.append( &startpt ); + for( it = l.begin(); it != l.end(); ++it ) { + count++; + drawTodo( completed, count, static_cast<Todo *>( *it ), p, connectSubTodos, + desc, pospriority, possummary, posDueDt, level+1, + x, y, width, height, pageHeight, &startpt); + } + startPoints.remove(&startpt); +} + +int CalPrintBase::weekdayColumn( int weekday ) +{ + return ( weekday + 7 - KGlobal::locale()->weekStartDay() ) % 7; +} + +void CalPrintBase::drawSplitWeek( QPainter &p, const QDate &fd, + const QDate &td ) +{ + QDate curDay, fromDay, toDay, curWeek, fromWeek, toWeek; + + mPrinter->setOrientation(KPrinter::Portrait); + + int minus = 0; + if (KGlobal::locale()->weekStartsMonday()) { + // correct to monday + fromWeek = fd.addDays(-(fd.dayOfWeek()-1)); + // correct to sunday + toWeek = td.addDays(7-fd.dayOfWeek()); + minus = 1; + } else { + // correct to sunday + fromWeek = fd.addDays(-(fd.dayOfWeek()%7)); + // correct to saturday + toWeek = td.addDays(6-td.dayOfWeek()); + } + + fromDay = fd; + curDay = fd; + toDay = td; + p.setFont( QFont("Helvetica") ); + // the painter initially begins at 72 dpi per the Qt docs. + int pageWidth = p.viewport().width(); + int pageHeight = p.viewport().height(); + int margin=0; + mHeaderHeight = 110; + mSubHeaderHeight = 20; + + p.setViewport(margin, margin, + p.viewport().width()-margin, + p.viewport().height()-margin); + + curWeek = fromWeek.addDays(6); + + int columnWidth = int( pageWidth / 4.5 ); + + do { + + // if ( (curDay.dayOfWeek()-1)%7 < 3 ) + switch((curDay.dayOfWeek()-minus)%7){ + case 0: + drawSplitTimes( p, pageWidth, columnWidth, pageHeight ); + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 0.5 ) ); + break; + case 1: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 1.5 ) ); + break; + case 2: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 2.5 ) ); + break; + case 3: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 3.5 ) ); + mPrinter->newPage(); + break; + case 4: + drawSplitTimes( p, int( pageWidth * ( 3.5/ 4.5 ) ), columnWidth, + pageHeight ); + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 0.5 ) ); + drawSplitHeaderRight( p, curWeek.addDays( -6 ), curWeek, + curWeek, pageWidth, mHeaderHeight ); + break; + case 5: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 1.5 ) ); + break; + case 6: + drawSplitDay( p, curDay, columnWidth, pageHeight, + int( columnWidth * 2.5 ) ); + if ( curDay < toDay ) + mPrinter->newPage(); + curWeek = curWeek.addDays( 7 ); + break; + } + curDay = curDay.addDays(1); + + } while (curDay <= toDay); + +} + +void CalPrintBase::drawSplitHeaderRight( QPainter &p, const QDate &fd, + const QDate &td, + const QDate &, + int width, int ) +{ + int tempStore = mSubHeaderHeight; + mSubHeaderHeight+= mSubHeaderHeight; + KLocale *local = KGlobal::locale(); + QFont font("helvetica", 18, QFont::Bold); + QPen penA( black,0); + QPen penB( black,3); + p.setFont(font); + int lineSpacing = p.fontMetrics().lineSpacing(); + QString title; + QString myOwner(mCalendar->getOwner()); + if ( fd.month() == td.month() ) { + title = local->monthName(fd.month(), false) + ' ' + QString::number(fd.day()) + ' ' + + '-' + ' ' + QString::number(td.day()); + } else { + title = local->monthName(fd.month(), false) + ' ' + QString::number(fd.day()) + ' ' + + '-' + ' ' + local->monthName(td.month(), false) + ' ' + QString::number(td.day()); + } + +// Grrrrrrr! why can't I set the font to a serif font?!?!? + QFont serifFont("Helvetica", 30); +// serifFont.setFamily("Serif"); +// serifFont.setWeight(87); +// serifFont.setItalic(true); + p.setFont(serifFont); + QFontInfo info(p.font()); + + lineSpacing = p.fontMetrics().lineSpacing(); + p.drawText(0, lineSpacing * 0, width, lineSpacing, AlignRight |AlignTop, title ); + + title.truncate(0); + + p.setPen(penB ); + p.drawLine(200, lineSpacing * 1, width, lineSpacing * 1); + p.setPen(penA ); + + p.setFont(QFont("Helvetica", 20, QFont::Bold, TRUE)); + title += QString::number(fd.year()); + p.drawText(0, lineSpacing * 1, width, lineSpacing, AlignRight |AlignTop, title ); + mSubHeaderHeight = tempStore ; +} + +void CalPrintBase::drawSplitDay( QPainter &p, const QDate &qd, int width, + int height, int offsetLeft ) +{ + int tempStore = mSubHeaderHeight; + mSubHeaderHeight+= mSubHeaderHeight; + int startHour = KOPrefs::instance()->mDayBegins; + int endHour = 20; + int offset = mHeaderHeight + mSubHeaderHeight + 10; + Event::List eventList; eventList.fill( mCalendar->events( qd, true )); + Event::List::Iterator it; + Event *currEvent; + KLocale *local = KGlobal::locale(); + QString dayName; + + dayName = local->weekDayName(qd.dayOfWeek()) + ' ' + ' ' + QString::number(qd.day()); + //p.setBrush(QBrush(black)); +// width+1 to make sure there's a continuous, black bar across the top. + p.setPen( QPen(Qt::black,2)); + p.drawRect(offsetLeft, mHeaderHeight + 5, width +1, mSubHeaderHeight); + p.setPen( Qt::black); + p.setFont(QFont("helvetica", 12, QFont::Bold, true)); + p.drawText(offsetLeft, mHeaderHeight + 5, + width, mSubHeaderHeight, AlignHCenter | AlignVCenter, + dayName); + + p.setPen( QPen(Qt::black,2)); + p.setFont(QFont("helvetica", 12)); + p.setBrush(Qt::white); + it = eventList.begin(); + int allDays = 0; + /* + while( it != eventList.end() ) { + Event *currEvent = *it; + if ( currEvent->doesFloat() ) { + p.drawRect( offsetLeft, offset, width, 35 ); + p.drawText( offsetLeft + 5, offset + 10, width - 10, 30, + AlignLeft | AlignTop, currEvent->summary() ); + offset += 40; + allDays++; + it = eventList.remove( it ); + } else { + ++it; + } + } + */ + //p.setBrush(QBrush()); + int tmpEnd; + for ( it = eventList.begin(); it != eventList.end(); ++it ) { + Event *currEvent = *it; + tmpEnd = currEvent->dtEnd().time().hour(); + if (currEvent->dtEnd().time().minute() > 0) + tmpEnd++; + if (tmpEnd > endHour) + endHour = tmpEnd; + } + int hours = endHour - startHour; + int cellHeight = (height-offset) / hours; // hour increments. + + p.setFont(QFont("helvetica", 12)); + //p.setBrush(QBrush(Dense7Pattern)); + p.setBrush(Qt::white); + for ( it = eventList.begin(); it != eventList.end(); ++it ) { + Event *currEvent = *it; + int startTime = currEvent->dtStart().time().hour(); + int endTime = currEvent->dtEnd().time().hour(); + float minuteInc = cellHeight / 60.0; + if ((startTime >= startHour) && (endTime <= (startHour + hours))) { + startTime -= startHour; + int startMinuteOff = (int) (minuteInc * + currEvent->dtStart().time().minute()); + QString text = currEvent->summary() ; + if ( ! currEvent->location().isEmpty() ) + text += "\n("+currEvent->location()+")"; + int endMinuteOff = (int) (minuteInc * currEvent->dtEnd().time().minute()); + int cheight = (int) (minuteInc * + currEvent->dtStart().secsTo(currEvent->dtEnd()) / 60 ); + p.drawRect(offsetLeft+2, 1+offset+startMinuteOff+startTime*cellHeight, + width-4, cheight); + p.drawText(offsetLeft+12, offset+startMinuteOff+startTime*cellHeight+5, width-24, + cheight-10, AlignHCenter | AlignTop, text); + } + } + p.setBrush(QBrush(NoBrush)); + mSubHeaderHeight = tempStore ; +} + +void CalPrintBase::drawSplitTimes( QPainter &p, int width, int timeWidth, + int height ) +{ + int tempStore = mSubHeaderHeight; + mSubHeaderHeight+= mSubHeaderHeight; + int startHour = KOPrefs::instance()->mDayBegins; + int endHour = 20; + int offset = mHeaderHeight + mSubHeaderHeight + 10; + int hours = endHour - startHour; + int cellHeight = (height-offset) / hours; // hour increments. + + QString numStr; + for (int i = 0; i < hours; i++) { + p.setPen(QPen(black,1)); + p.drawLine(0, offset+i*cellHeight, width, offset+i*cellHeight); + p.setPen(QPen(gray,0)); + p.drawLine(37, offset+i*cellHeight+(cellHeight/2), + width, offset+i*cellHeight+(cellHeight/2)); + p.setPen(QPen(black,0)); + + if ( !KGlobal::locale()->use12Clock() ) { + numStr.setNum(i+startHour); + if (cellHeight > 40) { + p.setFont(QFont("helvetica", 16, QFont::Bold)); + } else { + p.setFont(QFont("helvetica", 14, QFont::Bold)); + } + p.drawText(0, offset+i*cellHeight, 33, cellHeight/2, + AlignTop|AlignRight, numStr); + p.setFont(QFont("helvetica", 12, QFont::Bold)); + p.drawText(37, offset+i*cellHeight, 45, cellHeight/2, + AlignTop | AlignLeft, "00"); + } else { + QTime time( i + startHour, 0 ); + numStr = KGlobal::locale()->formatTime( time ); + p.setFont(QFont("helvetica", 12, QFont::Bold)); + p.drawText(4, offset+i*cellHeight, 70, cellHeight/2, + AlignTop|AlignLeft, numStr); + } + } mSubHeaderHeight = tempStore ; +} + +#endif diff --git a/korganizer/calprintbase.h b/korganizer/calprintbase.h new file mode 100644 index 0000000..7409143 --- a/dev/null +++ b/korganizer/calprintbase.h @@ -0,0 +1,379 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 1998 Preston Brown + Copyright (c) 2003 Reinhold Kainhofer <reinhold@kainhofer.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef CALPRINTBASE_H +#define CALPRINTBASE_H +// #define KORG_NOPRINTER + +#ifndef KORG_NOPRINTER + +#include <qwidget.h> +#include <qdatetime.h> +#include <kprinter.h> +#include <kconfig.h> +#include <libkcal/event.h> + +class PrintCellItem; + +namespace KCal { +class Calendar; +class Todo; +} + +using namespace KCal; + +/** + Base class for KOrganizer printing classes. Each sub class represents one + calendar print format. +*/ +class CalPrintBase : public QObject +{ + Q_OBJECT + public: + /** + Constructor + + \param pr KPrinter object used to print. + \param cal Calendar to be printed. + \param cfg KConfig object for reading/writing printing configuration + */ + CalPrintBase( KPrinter *pr, Calendar *cal, KConfig *cfg ); + virtual ~CalPrintBase(); + + /** + Returns short description of print format. + */ + virtual QString description() = 0; + /** + Returns long description of print format. + */ + virtual QString longDescription() = 0; + + /** + Returns widget for configuring the print format. + */ + virtual QWidget *configWidget( QWidget * ); + + /** + Actually do the printing. + + \param p QPainter the print result is painted to + \param width Width of printable area + \param height Height of printable area + */ + virtual void print( QPainter &p, int width, int height ) = 0; + /** + Start printing. + */ + virtual void doPrint(); + + /** + Orientation of printout. Default is Portrait. If your plugin wants + to use some other orientation as default (e.g. depending on some + config settings), implement this function in your subclass and + return the desired orientation. + */ + virtual KPrinter::Orientation orientation() { return KPrinter::Portrait; } + + /** + Load print format configuration from config file. + */ + virtual void loadConfig() = 0; + /** + Write print format configuration to config file. + */ + virtual void saveConfig() = 0; + + /** + Load complete config. This also calls loadConfig() of the derived class. + */ + void doLoadConfig(); + /** + Save complete config. This also calls saveConfig() of the derived class. + */ + void doSaveConfig(); + + + public slots: + /** + Read settings from configuration widget and apply them to current object. + */ + virtual void readSettingsWidget() {} + /** + Set configuration widget to reflect settings of current object. + */ + virtual void setSettingsWidget() {} + + /** + Set date range which should be printed. + */ + virtual void setDateRange( const QDate &from, const QDate &to ) + { + mFromDate = from; + mToDate = to; + } + + protected: + int weekdayColumn( int weekday ); + + QDate mFromDate; + QDate mToDate; + bool mUseColors; + + public: + /** + Internal class representing the start of a todo. + */ + class TodoParentStart; + + protected: + /** + Draw the gray header bar of the printout to the QPainter. + It prints the given text and optionally one or two small + month views, as specified by the two QDate. The printed + text can also contain a line feed. + If month2 is invalid, only the month that contains month1 + is printed. + E.g. the filofax week view draws just the current month, + while the month view draws the previous and the next month. + \param p QPainter of the printout + \param title The string printed as the title of the page + (e.g. the date, date range or todo list title) + \param month1 Date specifying the month for the left one of + the small month views in the title bar. If left + empty, only month2 will be printed (or none, + it that is invalid as well). + \param month2 Date specifying the month for the right one of + the small month views in the title bar. If left + empty, only month1 will be printed (or none, + it that is invalid as well). + \param x x-coordinate of the upper left coordinate of the title bar + \param y y-coordinate of the upper left coordinate of the title bar + \param width width of the title bar + \param height height of the title bar + */ + void drawHeader( QPainter &p, QString title, + const QDate &month1, const QDate &month2, + int x, int y, int width, int height ); + /** + Draw a small calendar with the days of a month into the given area. + Used for example in the title bar of the sheet. + \param p QPainter of the printout + \param qd Arbitrary Date within the month to be printed. + \param x x-coordinate of the upper left coordinate of the small calendar + \param y y-coordinate of the upper left coordinate of the small calendar + \param width width of the small calendar + \param height height of the small calendar + */ + void drawSmallMonth( QPainter &p, const QDate &qd, + int x, int y, int width, int height ); + + /** + Draw a horizontal bar with the weekday names of the given date range + in the given area of the painter. + This is used for the weekday-bar on top of the timetable view and the month view. + \param p QPainter of the printout + \param fromDate First date of the printed dates + \param toDate Last date of the printed dates + */ + void drawDaysOfWeek( QPainter &p, + const QDate &fromDate, const QDate &toDate, + int x, int y, int width, int height ); + /** + Draw a single weekday name in a box inside the given area of the painter. + This is called in a loop by drawDaysOfWeek. + \param p QPainter of the printout + \param qd Date of the printed day + */ + void drawDaysOfWeekBox( QPainter &p, const QDate &qd, + int x, int y, int width, int height ); + /** + Draw a (vertical) time scale from time fromTime to toTime inside the given area of the painter. + Every hour will have a one-pixel line over the whole width, every + half-hour the line will only span the left half of the width. + This is used in the day and timetable print styles + \param p QPainter of the printout + \param fromTime Start time of the time range to display + \param toTime End time of the time range to display + */ + void drawTimeLine( QPainter &p, + const QTime &fromTime, const QTime &toTime, + int x, int y, int width, int height ); + /** + Draw the all-day box for the agenda print view (the box on top which + doesn't have a time on the time scale associated). If expandable is set, + height is the cell height of a single cell, and the returned height will + be the total height used for the all-day events. If !expandable, only one + cell will be used, and multiple events are concatenated using ", ". + \param p QPainter of the printout + \param eventList The list of all-day events that are supposed to be printed + inside this box + \param qd The date of the currently printed day + \param expandable If true, height is the height of one single cell, the printout + will use as many cells as events in the list and return the total height + needed for all of them. If false, height specifies the total height + allowed for all events, and the events are displayed in one cell, + with their summaries concatenated by ", ". + */ + void drawAllDayBox( QPainter &p, Event::List &eventList, + const QDate &qd, bool expandable, + int x, int y, int width, int &height ); + /** + Draw the agenda box for the day print style (the box showing all events of that day). + Also draws a grid with half-hour spacing of the grid lines. + \param p QPainter of the printout + \param eventList The list of the events that are supposed to be printed + inside this box + \param qd The date of the currently printed day + \param expandable If true, the start and end times are adjusted to include + the whole range of all events of that day, not just of the given time range. + The height of the box will not be affected by this (but the height + of one hour will be scaled down so that the whole range fits into + the box. fromTime and toTime receive the actual time range printed + by this function). + \param fromTime Start of the time range to be printed. Might be adjusted + to include all events if expandable==true + \param toTime End of the time range to be printed. Might be adjusted + to include all events if expandable==true + */ + void drawAgendaDayBox( QPainter &p, Event::List &eventList, + const QDate &qd, bool expandable, + QTime &fromTime, QTime &toTime, + int x, int y, int width, int height); + + void drawAgendaItem( PrintCellItem *item, QPainter &p, const QDate &, + const QDateTime &startPrintDate, + const QDateTime &endPrintDate, + float minlen, int x, int y, int width ); + /** + Draw the box containing a list of all events of the given day (with their times, + of course). Used in the Filofax and the month print style. + \param p QPainter of the printout + \param qd The date of the currently printed day. All events of the calendar + that appear on that day will be printed. + \param fullDate Whether the title bar of the box should contain the full + date string or just a short. + */ + void drawDayBox( QPainter &p, const QDate &qd, + int x, int y, int width, int height, + bool fullDate = false ); + /** + Draw the week (filofax) table of the week containing the date qd. The first + three days of the week will be shown in the first column (using drawDayBox), + the remaining four in the second column, where the last two days of the week + (typically Saturday and Sunday) only get half the height of the other day boxes. + \param p QPainter of the printout + \param qd Arbitrary date within the week to be printed. + */ + void drawWeek( QPainter &p, const QDate &qd, + int x, int y, int width, int height ); + /** + Draw the timetable view of the given time range from fromDate to toDate. + On the left side the time scale is printed (using drawTimeLine), then each + day gets one column (printed using drawAgendaDayBox), + and the events are displayed as boxes (like in korganizer's day/week view). + The first cell of each column contains the all-day events (using + drawAllDayBox with expandable=false). + The given time range cannot be expanded to include all events. + \param p QPainter of the printout + \param fromDate First day to be included in the page + \param toDate Last day to be included in the page + \param fromTime Start time of the displayed time range + \param toTime End time of the displayed time range + */ + void drawTimeTable( QPainter &p, const QDate &fromDate, const QDate &toDate, + QTime &fromTime, QTime &toTime, + int x, int y, int width, int height ); + + /** + Draw the month table of the month containing the date qd. Each day gets one + box (using drawDayBox) that contains a list of all events on that day. They are arranged + in a matrix, with the first column being the first day of the + week (so it might display some days of the previous and the next month). + Above the matrix there is a bar showing the weekdays (drawn using drawDaysOfWeek). + \param p QPainter of the printout + \param qd Arbitrary date within the month to be printed. + \param weeknumbers Whether the week numbers are printed left of each row of the matrix + */ + void drawMonth( QPainter &p, const QDate &qd, bool weeknumbers, + int x, int y, int width, int height ); + + /** + Draws single todo item and its (intented) subitems, optionally connects them by a tree-like line, + and optionally shows due date, summary, description and priority. + \param count The number of the currently printed todo (count will be incremented for each drawn item) + \param item The item to be printed. It's subitems are recursively + drawn, so drawTodo should only be called on the + items of the highest level. + \param p QPainter of the printout + \param connectSubTodos Whether subtodos shall be connected with their parent by a line (tree-like). + \param desc Whether to print the whole description of the item (the summary is always printed). + \param pospriority x-coordinate where the priority is supposed to be printed. If <0, no priority will be printed. + \param possummary x-coordinate where the summary of the item is supposed to be printed. + \param posDueDt x-coordinate where the due date is supposed to the be printed. If <0, no due date will be printed. + \param level Level of the current item in the todo hierarchy (0 means highest + level of printed items, 1 are their subtodos, etc.) + \param x x-coordinate of the upper left coordinate of the first item + \param y y-coordinate of the upper left coordinate of the first item + \param width width of the whole todo list + \param height Space left on the first page of the todo list + \param pageHeight Total height allowed for the todo list on a page. The first page uses height, + but at each line break the current position is reset to 0 and the + height is set to pageHeight. + \param r Internal (used when printing sub items to give information about its parent) + */ + void drawTodo( bool completed, int &count, Todo * item, QPainter &p, bool connectSubTodos, + bool desc, int pospriority, int possummary, int posDueDt, + int level, int x, int &y, int width, int &height, + int pageHeight, TodoParentStart *r = 0 ); + + void drawSplitWeek( QPainter &p, const QDate &fd, const QDate &td ); + void drawSplitHeaderRight( QPainter &p, const QDate &fd, const QDate &td, + const QDate &cd, int width, int height ); + void drawSplitDay( QPainter &p, const QDate &qd, int width, int height, + int offsetLeft ); + void drawSplitTimes( QPainter &p, int width, int timeWidth, int height ); + + /** + Determines the column of the given weekday ( 1=Monday, 7=Sunday ), taking the + start of the week setting into account as given in kcontrol. + \param weekday Index of the weekday + */ + int weekDayColumn( int weekday ); + + KPrinter *mPrinter; + Calendar *mCalendar; + KConfig *mConfig; + //QWidget *mConfigWidget; + + protected: + // TODO_RK: move these to the appropriate subclasses or set them globally. + static int mSubHeaderHeight; + static int mHeaderHeight; + static int mMargin; +}; + +#endif + +#endif diff --git a/korganizer/calprintdayconfig_base.ui b/korganizer/calprintdayconfig_base.ui new file mode 100644 index 0000000..2625593 --- a/dev/null +++ b/korganizer/calprintdayconfig_base.ui @@ -0,0 +1,252 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>CalPrintDayConfig_Base</class> +<comment>Configuration page for the print day mode.</comment> +<author>Reinhold Kainhofer <reinhold@kainhofer.com></author> +<widget class="QWidget"> + <property name="name"> + <cstring>CalPrintDay_Base</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>407</width> + <height>175</height> + </rect> + </property> + <property name="caption"> + <string>CalPrintDay_Base</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>mDateRangeGroup</cstring> + </property> + <property name="title"> + <string>Date && Time Range</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>mToDateLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&End date:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mToDate</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>mFromDateLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Start date:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mFromDate</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>mFromTimeLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Start &time:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mFromTime</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>mToTimeLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>End ti&me:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mToTime</cstring> + </property> + </widget> + <widget class="QTimeEdit" row="1" column="1"> + <property name="name"> + <cstring>mFromTime</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>3</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="time"> + <time> + <hour>0</hour> + <minute>8</minute> + <second>0</second> + </time> + </property> + </widget> + <widget class="QTimeEdit" row="1" column="3"> + <property name="name"> + <cstring>mToTime</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>3</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="time"> + <time> + <hour>18</hour> + <minute>0</minute> + <second>0</second> + </time> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>mIncludeAllEvents</cstring> + </property> + <property name="text"> + <string>E&xtend time range to include all events</string> + </property> + </widget> + <widget class="KDateEdit" row="0" column="3"> + <property name="name"> + <cstring>mToDate</cstring> + </property> + <property name="focusPolicy"> + <enum>StrongFocus</enum> + </property> + </widget> + <widget class="KDateEdit" row="0" column="1"> + <property name="name"> + <cstring>mFromDate</cstring> + </property> + <property name="focusPolicy"> + <enum>StrongFocus</enum> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>mIncludeTodos</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Include to&dos that are due on the printed day(s)</string> + </property> + <property name="accel"> + <string>Alt+D</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>mColors</cstring> + </property> + <property name="text"> + <string>&Use colors</string> + </property> + <property name="accel"> + <string>Alt+U</string> + </property> + </widget> + <spacer> + <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>51</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>KDateEdit</class> + <header location="local">libkdepim/kdateedit.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="826">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000030149444154789cb59531681b5718c77f0e377c070e3c810a3a70e0041eac51852e0a19e45134830a1d9a4c69a04bc8928e990a693a640e1d0c8642b08742321894c1507991b484c890902bb8701a047760c3bd21701fe4201dde49b6a41a32b8df72dcbbeffdbefffbbfefbd5b1b0c07cce266ebe667ae2006c3c1dada0cdc3be87d6e6c35b0d692a409d9c7ec8b20d65ae29398d19b1114e7e3de4ce98b3f5e10dc0053cf0951b4506496e1b964bf7ce6c585d9054c62d01d617ca48be0596553cf496d8f2c8b01c5f795fc93904e85ec4c01a152857a5d9175d0b2805c872080f18595ccc1499a10a225d4e2fbc2877786fe81253ab6c04c8d106e09db5d43ab0d146e5c64d1a23938fb98a185cea1c33eecfd9eba49eb427dcb201e245365f2b7b2fb5b4a3a31dcb927178afe07d86901df870fefa4842aed6f6b74ba42e52b4014d580e1eb9cbd9d94de7e4aad16d2f9be02d805f0b5e532f927a1ffcacea1777f122a8105b164a7c25faf323a5d9f1f1fd600e1e5bec59e2d4b5c7ef5209d0ad17b8b31864e57c0b3e0815ac3ee33253ab664a770ff5185d1a1cb8d2267d3e58aa1dc7d2508cbe597d0e74fdd269aaaf0f52d414c4ea3e9762c996869e42560d7a72e41c4799a2586e74f95e8d8151481fa86efbe7b3398ac58b1a2b8527589f15451ad303ac2293542ad6648a796278f13a27185e4c4754310facb98c53a79e19a3fdc1426ff28c3d7399d1f7cb25343eb96106cf83c790ce9c4f2eb831855c55485663327992eb6dc8a6259874ed700b0b793323cccb9ffa842b30d6133e3e75fea989ac15a8b16ca76b746b0b92278d919774c5b6d48a78697fb29bbcf52468742a32120909c24e899ce67beed5be2db01e22d1e9485bb620e47f9ee9e606a21bd3f5d3744c7e7c54d55e87443867d8b554515ac5db4620e8e4f62263170fd1cdee90aad7640141992891b0f367c9adfe4049bb07d3b7022bd8c687c0978f46684ee084150b65ac1fcca94591b7a90a496e4c095164fb016a2b192a497795cc0f84817aebe25f7bf70ccc54a575c555c03f78ffa5fc0570d1f0c076bff0232285a0901e2257b0000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kdateedit.h</includehint> + <includehint>kdateedit.h</includehint> +</includehints> +</UI> diff --git a/korganizer/calprinter.cpp b/korganizer/calprinter.cpp new file mode 100644 index 0000000..6b5b0fe --- a/dev/null +++ b/korganizer/calprinter.cpp @@ -0,0 +1,299 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1998 Preston Brown + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qvbuttongroup.h> +#include <qwidgetstack.h> +#include <qradiobutton.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qvbox.h> +#include <qsplitter.h> + +#include <kprinter.h> +#include <kglobal.h> +#include <ksimpleconfig.h> +#include <kmessagebox.h> +#include <kdebug.h> +//#include <kdeversion.h> + +#include "koprefsdialog.h" + +#include "calprinter.h" +#ifndef KORG_NOPRINTER +//#include "calprinter.moc" + +#include "calprintplugins.h" + +CalPrinter::CalPrinter( QWidget *parent, Calendar *calendar ) + : QObject( parent, "CalPrinter" ) +{ + mCalendar = calendar; + mParent = parent; + mPrinter = new KPrinter; + mPrinter->setOrientation( KPrinter::Portrait ); + mConfig = new KConfig(locateLocal("config","korganizer_printing.rc" )); + //KSimpleConfig( "korganizer_printing.rc" ); + + init( mPrinter, calendar ); +} + +CalPrinter::~CalPrinter() +{ + kdDebug() << "~CalPrinter()" << endl; + + CalPrintBase *plug = mPrintPlugins.first(); + while ( plug ) { + plug->doSaveConfig(); + plug = mPrintPlugins.next(); + } + mConfig->sync(); + delete mConfig; + delete mPrintDialog; + delete mPrinter; +} + +void CalPrinter::init( KPrinter *printer, Calendar *calendar ) +{ + mPrintPlugins.setAutoDelete( true ); + mPrintPlugins.append( new CalPrintDay( printer, calendar, mConfig ) ); + mPrintPlugins.append( new CalPrintWeek( printer, calendar, mConfig ) ); + mPrintPlugins.append( new CalPrintMonth( printer, calendar, mConfig ) ); + mPrintPlugins.append( new CalPrintTodos( printer, calendar, mConfig ) ); + + // TODO_RK: Add a plugin interface here + mPrintDialog = new CalPrintDialog( mPrintPlugins, mPrinter, mParent ); + + CalPrintBase *plug = mPrintPlugins.first(); + while ( plug ) { + connect( mPrintDialog, SIGNAL( okClicked() ), + plug, SLOT( readSettingsWidget() ) ); + + plug->doLoadConfig(); + + plug = mPrintPlugins.next(); + } +} + +void CalPrinter::setupPrinter() +{ + KMessageBox::sorry( mParent, i18n("Not implemented.") ); +#if 0 + KOPrefsDialog *optionsDlg = new KOPrefsDialog(mParent); + optionsDlg->readConfig(); + optionsDlg->showPrinterTab(); + connect(optionsDlg, SIGNAL(configChanged()), + mParent, SLOT(updateConfig())); + optionsDlg->show(); +#endif +} + +void CalPrinter::setDateRange( const QDate &fd, const QDate &td ) +{ + CalPrintBase *plug = mPrintPlugins.first(); + while ( plug ) { + plug->setDateRange( fd, td ); + plug = mPrintPlugins.next(); + } +} + +void CalPrinter::preview( PrintType type, const QDate &fd, const QDate &td ) +{ + mPrintDialog->setPreview( true ); + mPrintDialog->setPrintType( int( type ) ); + setDateRange( fd, td ); + + if ( mPrintDialog->exec() == QDialog::Accepted ) { + doPrint( mPrintDialog->selectedPlugin(), true ); + } +} + +void CalPrinter::print( PrintType type, const QDate &fd, const QDate &td ) +{ + mPrintDialog->resize( 640, 380 ); + mPrintDialog->setPreview( false ); + mPrintDialog->setPrintType( int( type ) ); + setDateRange( fd, td ); + + if ( mPrintDialog->exec() == QDialog::Accepted ) { + doPrint( mPrintDialog->selectedPlugin(), false ); + } +} + +void CalPrinter::doPrint( CalPrintBase *selectedStyle, bool preview ) +{ + // FIXME: add a better caption to the Printingdialog + //mPrinter->setPreviewOnly( preview ); + if ( preview || mPrinter->setup( mParent ) ) { + switch ( mPrintDialog->orientation() ) { + case eOrientPlugin: + mPrinter->setOrientation( selectedStyle->orientation()); + break; + case eOrientPortrait: + mPrinter->setOrientation( KPrinter::Portrait ); + break; + case eOrientLandscape: + mPrinter->setOrientation( KPrinter::Landscape ); + break; + case eOrientPrinter: + default: + break; + } + selectedStyle->doPrint(); + } + //mPrinter->setPreviewOnly( false ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void CalPrinter::updateConfig() +{ +} + + +/****************************************************************************/ + +CalPrintDialog::CalPrintDialog( QPtrList<CalPrintBase> plugins, KPrinter *p, + QWidget *parent, const char *name ) + : KDialogBase( parent, name, /*modal*/true, i18n("Print"), Ok | Cancel ), + mPrinter( p ), mPrintPlugins( plugins ) +{ + QVBox *page = new QVBox(this);//makeVBoxMainWidget(); + setMainWidget( page ); + QHBox *printerLayout = new QHBox( page ); + + mPrinterLabel = new QLabel( printerLayout ); + QPushButton *setupButton = new QPushButton( i18n("&Setup Printer..."), + printerLayout ); + setupButton->setSizePolicy( QSizePolicy( + (QSizePolicy::SizeType)4, (QSizePolicy::SizeType)0, + 0, 0, setupButton->sizePolicy().hasHeightForWidth() ) ); + + QSplitter *splitter = new QSplitter( page ); + splitter->setOrientation( QSplitter::Horizontal ); + + mTypeGroup = new QVButtonGroup( i18n("View Type"), splitter, "buttonGroup" ); + // use the minimal width possible = max width of the radio buttons, not extensible +/* mTypeGroup->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)4, + (QSizePolicy::SizeType)5, 0, 0, + mTypeGroup->sizePolicy().hasHeightForWidth() ) );*/ + + QWidget *splitterRight = new QWidget( splitter, "splitterRight" ); + QGridLayout *splitterRightLayout = new QGridLayout( splitterRight ); + splitterRightLayout->setMargin( marginHint() ); + splitterRightLayout->setSpacing( spacingHint() ); + + mConfigArea = new QWidgetStack( splitterRight, "configWidgetStack" ); + splitterRightLayout->addMultiCellWidget( mConfigArea, 0,0, 0,1 ); + + QLabel *orientationLabel = new QLabel( i18n("Page &orientation:"), + splitterRight, "orientationLabel" ); + splitterRightLayout->addWidget( orientationLabel, 1, 0 ); + + mOrientationSelection = new QComboBox( splitterRight, "orientationCombo" ); + mOrientationSelection->insertItem( i18n("Use Default of Selected Style") ); + mOrientationSelection->insertItem( i18n("Use Default Setting of Printer") ); + mOrientationSelection->insertItem( i18n("Portrait") ); + mOrientationSelection->insertItem( i18n("Landscape") ); + splitterRightLayout->addWidget( mOrientationSelection, 1, 1 ); + + // signals and slots connections + connect( setupButton, SIGNAL( clicked() ), SLOT( setupPrinter() ) ); + connect( mTypeGroup, SIGNAL( clicked( int ) ), SLOT( setPrintType( int ) ) ); + + // buddies + orientationLabel->setBuddy( mOrientationSelection ); + + CalPrintBase *plug = mPrintPlugins.first(); + QRadioButton *radioButton; + int id = 0; + while ( plug ) { + radioButton = new QRadioButton( plug->description(), mTypeGroup ); + mTypeGroup->insert( radioButton, id ); + //radioButton->setMinimumHeight( radioButton->sizeHint().height() - 5 ); + + mConfigArea->addWidget( plug->configWidget( mConfigArea ), id ); + + plug = mPrintPlugins.next(); + id++; + } + + // setMinimumSize( minimumSizeHint() ); + //resize( minimumSizeHint() ); +} + +CalPrintDialog::~CalPrintDialog() +{ +} + +void CalPrintDialog::setupPrinter() +{ + if ( mPrinter->setup( this ) ) { + setPrinterLabel(); + } +} + +void CalPrintDialog::setPreview(bool preview) +{ + + setButtonText(KDialogBase::Ok, preview ? i18n("&Preview") : i18n("&Print...") ); + + mPreviewText = preview ? i18n("<qt>Preview for printer <b>%1</b></qt>") + : i18n( "<qt>Printing on printer <b>%1</b></qt>"); + setPrinterLabel(); +} + +void CalPrintDialog::setPrinterLabel() +{ + QString printerName( mPrinter->printerName() ); + if ( printerName.isEmpty() ) + mPrinterLabel->setText( mPreviewText.arg( i18n("[Unconfigured]") ) ); + else + mPrinterLabel->setText( mPreviewText.arg( printerName ) ); +} + +void CalPrintDialog::setPrintType( int i ) +{ + // TODO: Make a safe correlation between type and the radio button + + mTypeGroup->setButton( i ); + mConfigArea->raiseWidget( i ); +} + +CalPrintBase *CalPrintDialog::selectedPlugin() +{ + int pos = mTypeGroup->id( mTypeGroup->selected() ); + if ( pos < 0 ) return 0; + CalPrintBase *retval = mPrintPlugins.at( pos ); + return retval; +} + +void CalPrintDialog::slotOk() +{ + mOrientation = (CalPrinter::ePrintOrientation)mOrientationSelection->currentItem(); + KDialogBase::slotOk(); + emit okClicked(); +} + +#endif diff --git a/korganizer/calprinter.h b/korganizer/calprinter.h new file mode 100644 index 0000000..7b58f4f --- a/dev/null +++ b/korganizer/calprinter.h @@ -0,0 +1,142 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 1998 Preston Brown + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _CALPRINTER_H +#define _CALPRINTER_H + +// #define KORG_NOPRINTER + +#ifndef KORG_NOPRINTER + +#include <qptrlist.h> + +#include <kdialogbase.h> + +#include <korganizer/baseview.h> + +#include "calprintbase.h" + +using namespace KCal; + +class QVButtonGroup; +class QWidgetStack; +class KPrinter; +class CalPrintDialog; +class KConfig; +class QComboBox; +class QLabel; + + +/** + CalPrinter is a class for printing Calendars. It can print in several + different formats (day, week, month). It also provides a way for setting + up the printer and remembering these preferences. +*/ +class CalPrinter : public QObject, public KOrg::CalPrinterBase +{ + Q_OBJECT + + public: + enum ePrintOrientation { + eOrientPlugin=0, + eOrientPrinter, + eOrientPortrait, + eOrientLandscape + }; + public: + /** + \param par parent widget for dialogs + \param cal calendar to be printed + */ + CalPrinter( QWidget *par, Calendar *cal ); + virtual ~CalPrinter(); + + void init( KPrinter *printer, Calendar *calendar ); + + void setupPrinter(); + + /** + Set date range to be printed. + + \param start Start date + \param end End date + */ + void setDateRange( const QDate &start, const QDate &end ); + + public slots: + void updateConfig(); + + private slots: + void doPrint( CalPrintBase *selectedStyle, bool preview ); + + public: + void preview( PrintType type, const QDate &fd, const QDate &td ); + void print( PrintType type, const QDate &fd, const QDate &td ); + + protected: + QPtrList<CalPrintBase> mPrintPlugins; + + private: + KPrinter *mPrinter; + Calendar *mCalendar; + QWidget *mParent; + KConfig *mConfig; + + CalPrintDialog *mPrintDialog; +}; + +class CalPrintDialog : public KDialogBase +{ + Q_OBJECT + public: + CalPrintDialog( QPtrList<CalPrintBase> plugins, KPrinter *p, + QWidget *parent = 0, const char *name = 0 ); + virtual ~CalPrintDialog(); + CalPrintBase *selectedPlugin(); + CalPrinter::ePrintOrientation orientation() { return mOrientation; } + + public slots: + void setPrintType( int ); + void setPreview( bool ); + + protected slots: + void slotOk(); + void setupPrinter(); + void setPrinterLabel(); +signals: + void okClicked(); + private: + KPrinter *mPrinter; + QVButtonGroup *mTypeGroup; + QWidgetStack *mConfigArea; + QPtrList<CalPrintBase> mPrintPlugins; + QLabel *mPrinterLabel; + QString mPreviewText; + QComboBox *mOrientationSelection; + + CalPrinter::ePrintOrientation mOrientation; +}; + +#endif + +#endif diff --git a/korganizer/calprinter.moc b/korganizer/calprinter.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/calprinter.moc diff --git a/korganizer/calprintmonthconfig_base.ui b/korganizer/calprintmonthconfig_base.ui new file mode 100644 index 0000000..734a559 --- a/dev/null +++ b/korganizer/calprintmonthconfig_base.ui @@ -0,0 +1,172 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>CalPrintMonthConfig_Base</class> +<comment>Configuration page for the print day mode.</comment> +<author>Reinhold Kainhofer <reinhold@kainhofer.com></author> +<widget class="QWidget"> + <property name="name"> + <cstring>CalPrintMonth_Base</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>357</width> + <height>112</height> + </rect> + </property> + <property name="caption"> + <string>CalPrintMonth_Base</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <spacer row="4" 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>21</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>mDateRangeGroup</cstring> + </property> + <property name="title"> + <string>Date && Time Range</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>mFromDateLabel</cstring> + </property> + <property name="text"> + <string>&Start month:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mFromDate</cstring> + </property> + </widget> + <widget class="KDateEdit"> + <property name="name"> + <cstring>mFromDate</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>3</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="focusPolicy"> + <enum>StrongFocus</enum> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>mToDateLabel</cstring> + </property> + <property name="text"> + <string>&End month:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mToDate</cstring> + </property> + </widget> + <widget class="KDateEdit"> + <property name="name"> + <cstring>mToDate</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>3</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="focusPolicy"> + <enum>StrongFocus</enum> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>mIncludeTodos</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Include to&dos that are due on the printed day(s)</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>mWeekNumbers</cstring> + </property> + <property name="text"> + <string>Print week &numbers</string> + </property> + </widget> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>KDateEdit</class> + <header location="local">libkdepim/kdateedit.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="826">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000030149444154789cb59531681b5718c77f0e377c070e3c810a3a70e0041eac51852e0a19e45134830a1d9a4c69a04bc8928e990a693a640e1d0c8642b08742321894c1507991b484c890902bb8701a047760c3bd21701fe4201dde49b6a41a32b8df72dcbbeffdbefffbbfefbd5b1b0c07cce266ebe667ae2006c3c1dada0cdc3be87d6e6c35b0d692a409d9c7ec8b20d65ae29398d19b1114e7e3de4ce98b3f5e10dc0053cf0951b4506496e1b964bf7ce6c585d9054c62d01d617ca48be0596553cf496d8f2c8b01c5f795fc93904e85ec4c01a152857a5d9175d0b2805c872080f18595ccc1499a10a225d4e2fbc2877786fe81253ab6c04c8d106e09db5d43ab0d146e5c64d1a23938fb98a185cea1c33eecfd9eba49eb427dcb201e245365f2b7b2fb5b4a3a31dcb927178afe07d86901df870fefa4842aed6f6b74ba42e52b4014d580e1eb9cbd9d94de7e4aad16d2f9be02d805f0b5e532f927a1ffcacea1777f122a8105b164a7c25faf323a5d9f1f1fd600e1e5bec59e2d4b5c7ef5209d0ad17b8b31864e57c0b3e0815ac3ee33253ab664a770ff5185d1a1cb8d2267d3e58aa1dc7d2508cbe597d0e74fdd269aaaf0f52d414c4ea3e9762c996869e42560d7a72e41c4799a2586e74f95e8d8151481fa86efbe7b3398ac58b1a2b8527589f15451ad303ac2293542ad6648a796278f13a27185e4c4754310facb98c53a79e19a3fdc1426ff28c3d7399d1f7cb25343eb96106cf83c790ce9c4f2eb831855c55485663327992eb6dc8a6259874ed700b0b793323cccb9ffa842b30d6133e3e75fea989ac15a8b16ca76b746b0b92278d919774c5b6d48a78697fb29bbcf52468742a32120909c24e899ce67beed5be2db01e22d1e9485bb620e47f9ee9e606a21bd3f5d3744c7e7c54d55e87443867d8b554515ac5db4620e8e4f62263170fd1cdee90aad7640141992891b0f367c9adfe4049bb07d3b7022bd8c687c0978f46684ee084150b65ac1fcca94591b7a90a496e4c095164fb016a2b192a497795cc0f84817aebe25f7bf70ccc54a575c555c03f78ffa5fc0570d1f0c076bff0232285a0901e2257b0000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kdateedit.h</includehint> + <includehint>kdateedit.h</includehint> +</includehints> +</UI> diff --git a/korganizer/calprintplugins.cpp b/korganizer/calprintplugins.cpp new file mode 100644 index 0000000..bc35ca4 --- a/dev/null +++ b/korganizer/calprintplugins.cpp @@ -0,0 +1,669 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 1998 Preston Brown + Copyright (c) 2003 Reinhold Kainhofer <reinhold@kainhofer.com> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qpainter.h> +#include <qdatetimeedit.h> +#include <qdatetime.h> +#include <qcheckbox.h> +#include <qlineedit.h> +#include <qbuttongroup.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> +#include <kprinter.h> +#include <kconfig.h> +#include <kcalendarsystem.h> + +#include <libkcal/todo.h> +#include <libkcal/calendar.h> + +#include <libkdepim/kdateedit.h> + +#include "koprefs.h" +#include "koglobals.h" +#include "calprintplugins.h" +#ifndef KORG_NOPRINTER + +//#include "calprintplugins.moc" + +#define LEFT_DISTANCE 45 + +/************************************************************** + * Print Day + **************************************************************/ + +CalPrintDay::CalPrintDay( KPrinter *printer, Calendar *cal, KConfig *cfg ) + : CalPrintBase( printer, cal, cfg ) +{ +} + +CalPrintDay::~CalPrintDay() +{ +} + +QWidget *CalPrintDay::configWidget( QWidget *w ) +{ + mConfigWidget = new CalPrintDayConfig_Base( w ); + setSettingsWidget(); + return mConfigWidget; +} + +void CalPrintDay::readSettingsWidget() +{ + CalPrintDayConfig_Base *cfg = mConfigWidget; + if ( cfg ) { + mFromDate = cfg->mFromDate->date(); + mToDate = cfg->mToDate->date(); + + mStartTime = cfg->mFromTime->time(); + mEndTime = cfg->mToTime->time(); + mIncludeAllEvents = cfg->mIncludeAllEvents->isChecked(); + + mIncludeTodos = cfg->mIncludeTodos->isChecked(); + mUseColors = cfg->mColors->isChecked(); + } +} + +void CalPrintDay::setSettingsWidget() +{ + CalPrintDayConfig_Base *cfg =( mConfigWidget ); + if ( cfg ) { + cfg->mFromDate->setDate( mFromDate ); + cfg->mToDate->setDate( mToDate ); + + cfg->mFromTime->setTime( mStartTime ); + cfg->mToTime->setTime( mEndTime ); + cfg->mIncludeAllEvents->setChecked( mIncludeAllEvents ); + + cfg->mIncludeTodos->setChecked( mIncludeTodos ); + cfg->mColors->setChecked( mUseColors ); + } +} + +void CalPrintDay::loadConfig() +{ + if ( mConfig ) { + QDate dt; + QTime tm1 = QTime( KOPrefs::instance()->mDayBegins, 0,0 ); + QDateTime startTm( dt, tm1 ); + QDateTime endTm( dt, tm1.addSecs( 12 * 60 * 60 ) ); + mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time(); + mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time(); + mIncludeTodos = mConfig->readBoolEntry( "Include todos", false ); + mIncludeAllEvents = mConfig->readBoolEntry( "Include all events", false ); + } + setSettingsWidget(); +} + +void CalPrintDay::saveConfig() +{ + readSettingsWidget(); + if ( mConfig ) { + mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) ); + mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) ); + mConfig->writeEntry( "Include todos", mIncludeTodos ); + mConfig->writeEntry( "Include all events", mIncludeAllEvents ); + } +} + +void CalPrintDay::setDateRange( const QDate& from, const QDate& to ) +{ + CalPrintBase::setDateRange( from, to ); + CalPrintDayConfig_Base *cfg = mConfigWidget ; + if ( cfg ) { + cfg->mFromDate->setDate( from ); + cfg->mToDate->setDate( to ); + } +} + +void CalPrintDay::print( QPainter &p, int width, int height ) +{ + QDate curDay( mFromDate ); + int yoffset = 0, xoffset = 0; + if ( width > height ) { + yoffset += LEFT_DISTANCE; + } else { + xoffset += LEFT_DISTANCE; + } + width -= xoffset; + height -= yoffset; + do { + int x = 0; + int y = 0; + + + int currHeight=( height - y ) / 20; + QTime curStartTime( mStartTime ); + QTime curEndTime( mEndTime ); + if ( curStartTime.secsTo( curEndTime ) <= 3600 ) { + if ( curStartTime.hour() == 0 ) { + curStartTime = QTime( 0, 0, 0 ); + curEndTime = curStartTime.addSecs( 3600 ); + } else if ( curEndTime.hour() == 23 ) { + curEndTime=QTime( 23, 59, 59 ); + if ( curStartTime > QTime( 23, 0, 0 ) ) { + curStartTime = QTime( 23, 0, 0 ); + } + } else { + curStartTime = curStartTime.addSecs( -1200 ); + } + curEndTime = curEndTime.addSecs( 1200 ); + } + + KLocale *local = KGlobal::locale(); + drawHeader( p, local->formatDate( curDay, false ), + curDay, QDate(), xoffset, yoffset, width, mHeaderHeight ); + + y += mHeaderHeight + 5; + x = 80; + Event::List eventList; eventList.fill( mCalendar->events( curDay, true )); + + p.setFont( QFont( "helvetica", 10 ) ); + currHeight = p.fontMetrics().lineSpacing()*3/2; + drawAllDayBox( p, eventList, curDay, true, x+xoffset, y+yoffset, width - x, currHeight ); + y += currHeight; + drawAgendaDayBox( p, eventList, curDay, mIncludeAllEvents, + curStartTime, curEndTime, x+xoffset, y+yoffset, width - x, height - y ); + drawTimeLine( p, curStartTime, curEndTime, xoffset, y+yoffset, x - 5, height - y ); + curDay = curDay.addDays( 1 ); + if ( curDay <= mToDate ) mPrinter->newPage(); + } while ( curDay <= mToDate ); +} + + + +/************************************************************** + * Print Week + **************************************************************/ + +CalPrintWeek::CalPrintWeek(KPrinter *printer, Calendar *cal, KConfig *cfg) + :CalPrintBase(printer,cal,cfg) +{ +} + +CalPrintWeek::~CalPrintWeek() +{ +} + +QWidget *CalPrintWeek::configWidget( QWidget *w ) +{ + mConfigWidget = new CalPrintWeekConfig_Base( w ); + setSettingsWidget(); + return mConfigWidget; +} + +void CalPrintWeek::readSettingsWidget() +{ + CalPrintWeekConfig_Base *cfg =( mConfigWidget ); + if ( cfg ) { + mFromDate = cfg->mFromDate->date(); + mToDate = cfg->mToDate->date(); + + mWeekPrintType = (eWeekPrintType)( cfg->mPrintType->id( + cfg->mPrintType->selected() ) ); + + mStartTime = cfg->mFromTime->time(); + mEndTime = cfg->mToTime->time(); + + mIncludeTodos = cfg->mIncludeTodos->isChecked(); + mUseColors = cfg->mColors->isChecked(); + } +} + +void CalPrintWeek::setSettingsWidget() +{ + CalPrintWeekConfig_Base *cfg =( mConfigWidget ); + if ( cfg ) { + cfg->mFromDate->setDate( mFromDate ); + cfg->mToDate->setDate( mToDate ); + + cfg->mPrintType->setButton( mWeekPrintType ); + + cfg->mFromTime->setTime( mStartTime ); + cfg->mToTime->setTime( mEndTime ); + + cfg->mIncludeTodos->setChecked( mIncludeTodos ); + cfg->mColors->setChecked( mUseColors ); + } +} + +void CalPrintWeek::loadConfig() +{ + if ( mConfig ) { + QDate dt; + QTime tm1 = QTime( KOPrefs::instance()->mDayBegins, 0,0); + QDateTime startTm( dt, tm1 ); + QDateTime endTm( dt, tm1.addSecs( 43200 ) ); + mStartTime = mConfig->readDateTimeEntry( "Start time", &startTm ).time(); + mEndTime = mConfig->readDateTimeEntry( "End time", &endTm ).time(); + mIncludeTodos = mConfig->readBoolEntry( "Include todos", false ); + mWeekPrintType =(eWeekPrintType)( mConfig->readNumEntry( "Print type", (int)Filofax ) ); + } + setSettingsWidget(); +} + +void CalPrintWeek::saveConfig() +{ + readSettingsWidget(); + if ( mConfig ) { + mConfig->writeEntry( "Start time", QDateTime( QDate(), mStartTime ) ); + mConfig->writeEntry( "End time", QDateTime( QDate(), mEndTime ) ); + mConfig->writeEntry( "Include todos", mIncludeTodos ); + mConfig->writeEntry( "Print type", int( mWeekPrintType ) ); + } +} + +KPrinter::Orientation CalPrintWeek::orientation() +{ + if ( mWeekPrintType == Filofax || mWeekPrintType == SplitWeek ) return KPrinter::Portrait; + else return KPrinter::Landscape; +} + +void CalPrintWeek::setDateRange( const QDate &from, const QDate &to ) +{ + CalPrintBase::setDateRange( from, to ); + CalPrintWeekConfig_Base *cfg =( mConfigWidget ); + if ( cfg ) { + cfg->mFromDate->setDate( from ); + cfg->mToDate->setDate( to ); + } +} + +void CalPrintWeek::print( QPainter &p, int width, int height ) +{ + QDate curWeek, fromWeek, toWeek; + int yoffset = 0, xoffset = 0; + //width = height -1;//test only + if ( width > height ) { + yoffset += LEFT_DISTANCE; + } else { + xoffset += LEFT_DISTANCE; + } + width -= xoffset; + height -= yoffset; + // correct begin and end to first and last day of week + int weekdayCol = weekdayColumn( mFromDate.dayOfWeek() ); + fromWeek = mFromDate.addDays( -weekdayCol ); + weekdayCol = weekdayColumn( mFromDate.dayOfWeek() ); + toWeek = mToDate.addDays( 6 - weekdayCol ); + + curWeek = fromWeek.addDays( 6 ); + KLocale *local = KGlobal::locale(); + + switch ( mWeekPrintType ) { + case Filofax: + do { + QString line1( local->formatDate( curWeek.addDays( -6 ) ) ); + QString line2( local->formatDate( curWeek ) ); + drawHeader( p, line1 + "\n" + line2, curWeek.addDays( -6 ), QDate(), + 0+xoffset, 0+yoffset, width, mHeaderHeight ); + int top = mHeaderHeight + 10; + drawWeek( p, curWeek, 0+xoffset, top+yoffset, width, height - top ); + curWeek = curWeek.addDays( 7 ); + if ( curWeek <= toWeek ) + mPrinter->newPage(); + } while ( curWeek <= toWeek ); + break; + + case Timetable: + default: + do { + QString line1( local->formatDate( curWeek.addDays( -6 ) ) ); + QString line2( local->formatDate( curWeek ) ); + //int hh = int(mHeaderHeight * 2./3.); + int hh = mHeaderHeight; + if ( yoffset ) + drawHeader( p, i18n("date from - to", "%1 - %2").arg( line1 ).arg( line2 ), + curWeek, QDate(), 0+xoffset, 0+yoffset, width, hh ); + else + drawHeader( p, i18n("date from - to", "%1 -\n%2").arg( line1 ).arg( line2 ), + curWeek, QDate(), 0+xoffset, 0+yoffset, width, hh ); + drawTimeTable( p, fromWeek, curWeek, + mStartTime, mEndTime, 0+xoffset, hh + 5+yoffset, + width, height - hh - 5 ); + fromWeek = fromWeek.addDays( 7 ); + curWeek = fromWeek.addDays( 6 ); + if ( curWeek <= toWeek ) + mPrinter->newPage(); + } while ( curWeek <= toWeek ); + break; + + case SplitWeek: + drawSplitWeek( p, fromWeek, toWeek ); + break; + } +} + + + + +/************************************************************** + * Print Month + **************************************************************/ + +CalPrintMonth::CalPrintMonth( KPrinter *printer, Calendar *cal, KConfig *cfg ) + : CalPrintBase( printer, cal, cfg ) +{ +} + +CalPrintMonth::~CalPrintMonth() +{ +} + +QWidget *CalPrintMonth::configWidget( QWidget *w ) +{ + mConfigWidget = new CalPrintMonthConfig_Base( w ); + return mConfigWidget; +} + +void CalPrintMonth::readSettingsWidget() +{ + CalPrintMonthConfig_Base *cfg =( mConfigWidget ); + if ( cfg ) { + mFromDate = cfg->mFromDate->date(); + mToDate = cfg->mToDate->date(); + + mWeekNumbers = cfg->mWeekNumbers->isChecked(); + + mIncludeTodos = cfg->mIncludeTodos->isChecked(); +// mUseColors = cfg->mColors->isChecked(); + } +} + +void CalPrintMonth::setSettingsWidget() +{ + CalPrintMonthConfig_Base *cfg =( mConfigWidget ); + if ( cfg ) { + cfg->mFromDate->setDate( mFromDate ); + cfg->mToDate->setDate( mToDate ); + + cfg->mWeekNumbers->setChecked( mWeekNumbers ); + + cfg->mIncludeTodos->setChecked( mIncludeTodos ); +// cfg->mColors->setChecked( mUseColors ); + } +} + +void CalPrintMonth::loadConfig() +{ + if ( mConfig ) { + mWeekNumbers = mConfig->readBoolEntry( "Print week numbers", true ); + mIncludeTodos = mConfig->readBoolEntry( "Include todos", false ); + } + setSettingsWidget(); +} + +void CalPrintMonth::saveConfig() +{ + readSettingsWidget(); + if ( mConfig ) { + mConfig->writeEntry( "Print week numbers", mWeekNumbers ); + mConfig->writeEntry( "Include todos", mIncludeTodos ); + } +} + +void CalPrintMonth::setDateRange( const QDate &from, const QDate &to ) +{ + CalPrintBase::setDateRange( from, to ); + CalPrintMonthConfig_Base *cfg =( mConfigWidget ); + if ( cfg ) { + cfg->mFromDate->setDate( from ); + cfg->mToDate->setDate( to ); + } +} + +void CalPrintMonth::print( QPainter &p, int width, int height ) +{ + QDate curMonth, fromMonth, toMonth; + /* + if ( width > height ) { + // for debug only + int te = height; + height = width; + width = te; + } + */ + int yoffset = 0, xoffset = 0; + if ( width > height ) { + yoffset += LEFT_DISTANCE; + } else { + xoffset += LEFT_DISTANCE; + } + width -= xoffset; + height -= yoffset; + fromMonth = mFromDate.addDays( -( mFromDate.day() - 1 ) ); + toMonth = mToDate.addDays( mToDate.daysInMonth() - mToDate.day() ); + + curMonth = fromMonth; + do { + QString title( i18n("monthname year", "%1 %2") ); + title = title.arg( KOGlobals::self()->calendarSystem()->monthName( curMonth ) ) + .arg( curMonth.year() ); + QDate tmp( fromMonth ); + int weekdayCol = weekdayColumn( tmp.dayOfWeek() ); + tmp = tmp.addDays( -weekdayCol ); + + drawHeader( p, title, + curMonth.addMonths( -1 ), curMonth.addMonths( 1 ), + xoffset, yoffset, width, mHeaderHeight ); + drawMonth( p, curMonth, mWeekNumbers, xoffset, mHeaderHeight + 5+yoffset, + width, height - mHeaderHeight - 5 ); + curMonth = curMonth.addDays( curMonth.daysInMonth() ); + if ( curMonth <= toMonth ) mPrinter->newPage(); + } while ( curMonth <= toMonth ); + +} + + + + +/************************************************************** + * Print Todos + **************************************************************/ + +CalPrintTodos::CalPrintTodos( KPrinter *printer, Calendar *cal, KConfig *cfg ) + : CalPrintBase( printer, cal, cfg ) +{ +} + +CalPrintTodos::~CalPrintTodos() +{ +} + +QWidget *CalPrintTodos::configWidget( QWidget *w ) +{ + mConfigWidget = new CalPrintTodoConfig_Base( w ); + return mConfigWidget; +} + +void CalPrintTodos::readSettingsWidget() +{ + CalPrintTodoConfig_Base *cfg =( mConfigWidget ); + if ( cfg ) { + mPageTitle = cfg->mTitle->text(); + + mTodoPrintType = (eTodoPrintType)( cfg->mPrintType->id( + cfg->mPrintType->selected() ) ); + + mFromDate = cfg->mFromDate->date(); + mToDate = cfg->mToDate->date(); + + mIncludeDescription = cfg->mDescription->isChecked(); + mIncludePriority = cfg->mPriority->isChecked(); + mIncludeDueDate = cfg->mDueDate->isChecked(); + mConnectSubTodos = cfg->mConnectSubTodos->isChecked(); + } +} + +void CalPrintTodos::setSettingsWidget() +{ + CalPrintTodoConfig_Base *cfg =( mConfigWidget ); + if ( cfg ) { + cfg->mTitle->setText( mPageTitle ); + + cfg->mPrintType->setButton( mTodoPrintType ); + + cfg->mFromDate->setDate( mFromDate ); + cfg->mToDate->setDate( mToDate ); + + cfg->mDescription->setChecked( mIncludeDescription ); + cfg->mPriority->setChecked( mIncludePriority ); + cfg->mDueDate->setChecked( mIncludeDueDate ); + cfg->mConnectSubTodos->setChecked( mConnectSubTodos ); + } +} + +void CalPrintTodos::loadConfig() +{ + if ( mConfig ) { + mPageTitle = mConfig->readEntry( "Page title", i18n("Todo list") ); + mTodoPrintType = (eTodoPrintType)mConfig->readNumEntry( "Print type", (int)TodosAll ); + mIncludeDescription = mConfig->readBoolEntry( "Include description", true ); + mIncludePriority = mConfig->readBoolEntry( "Include priority", true ); + mIncludeDueDate = mConfig->readBoolEntry( "Include due date", true ); + mConnectSubTodos = mConfig->readBoolEntry( "Connect subtodos", true ); + mTodoPrintType = (eTodoPrintType) mConfig->readNumEntry( "Printing type", 0 ); + } + setSettingsWidget(); +} + +void CalPrintTodos::saveConfig() +{ + readSettingsWidget(); + if ( mConfig ) { + mConfig->writeEntry( "Page title", mPageTitle ); + mConfig->writeEntry( "Print type", int( mTodoPrintType ) ); + mConfig->writeEntry( "Include description", mIncludeDescription ); + mConfig->writeEntry( "Include priority", mIncludePriority ); + mConfig->writeEntry( "Include due date", mIncludeDueDate ); + mConfig->writeEntry( "Connect subtodos", mConnectSubTodos ); + mConfig->writeEntry( "Printing type", mTodoPrintType ); + } +} + +void CalPrintTodos::print( QPainter &p, int width, int height ) +{ + bool printCompleted = true; + if ( mTodoPrintType == 1 ) + printCompleted = false; + int yoffset = 0, xoffset = 0; + //width = height -1;//test only + if ( width > height ) { + yoffset += LEFT_DISTANCE; + } else { + xoffset += LEFT_DISTANCE; + } + width -= xoffset; + height -= yoffset; + + int pospriority = 5+xoffset; + int possummary = 70+xoffset; + int posdue = width - 145; + int lineSpacing = 15; + int fontHeight = 10; + + + drawHeader( p, mPageTitle, mFromDate, QDate(), + 0+xoffset, 0+yoffset, width, mHeaderHeight ); + + int mCurrentLinePos = mHeaderHeight + 5+yoffset; + QString outStr; + + p.setFont( QFont( "helvetica", 10 ) ); + lineSpacing = p.fontMetrics().lineSpacing(); + mCurrentLinePos += lineSpacing; + // draw the headers + p.setFont( QFont("helvetica", 10, QFont::Bold ) ); + if ( mIncludePriority ) { + outStr += i18n("Priority"); + p.drawText( pospriority, mCurrentLinePos - 2, outStr); + } else { + possummary = 10; + pospriority = -1; + } + + outStr.truncate( 0 ); + outStr += i18n("Summary"); + if ( mIncludeDueDate ) + outStr += i18n(" (Due)"); + + p.drawText( possummary, mCurrentLinePos - 2, outStr ); + + if ( mIncludeDueDate ) { + // outStr.truncate( 0 ); +// outStr += i18n("Due"); +// p.drawText( posdue, mCurrentLinePos - 2, outStr ); + } else { + posdue = -1; + } + + p.setFont( QFont( "helvetica", 10 ) ); + + fontHeight = p.fontMetrics().height(); + + Todo::List todoList; +// if (mTodoPrintType==TodosSelected) { +// todoList.append(selectedTodoo); +// } else { + todoList.fill(mCalendar->todos()); +// } + // TODO_RK: filter out todos + + int count = 0; + for( int cprior = 1; cprior <= 6; cprior++ ) { + Todo::List::ConstIterator it; + for( it = todoList.begin(); it != todoList.end(); ++it ) { + Todo *currEvent = *it; + + // Filter out the subitems. + if ( currEvent->relatedTo() ) { + continue; + } + + QDate start = currEvent->dtStart().date(); + // if it is not to start yet, skip. + // if ( ( !start.isValid() ) && ( start >= mToDate ) ) { + // continue; + //} + // priority + int priority = currEvent->priority(); + // 6 is the lowest priority (the unspecified one) + if ( ( priority != cprior ) || + ( ( cprior == 6 ) && ( priority == 0 ) ) ) { + continue; + } + count++; + int todoHeight = height - mCurrentLinePos; + drawTodo( printCompleted, count, currEvent, p, mConnectSubTodos, + mIncludeDescription, pospriority, possummary, posdue, 0, + 0, mCurrentLinePos, width, todoHeight, height ); + } + } +} + + +#endif diff --git a/korganizer/calprintplugins.h b/korganizer/calprintplugins.h new file mode 100644 index 0000000..7c56131 --- a/dev/null +++ b/korganizer/calprintplugins.h @@ -0,0 +1,151 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 1998 Preston Brown + Copyright (c) 2003 Reinhold Kainhofer <reinhold@kainhofer.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef CALPRINTPLUGINS_H +#define CALPRINTPLUGINS_H + + +#include <klocale.h> +#include "calprintbase.h" +#include "calprintdayconfig_base.h" +#include "calprintweekconfig_base.h" +#include "calprintmonthconfig_base.h" +#include "calprinttodoconfig_base.h" + +#ifndef KORG_NOPRINTER +namespace KCal { +class Calendar; +} + +using namespace KCal; + +class CalPrintDay : public CalPrintBase +{ + Q_OBJECT + public: + CalPrintDay(KPrinter *printer, Calendar *cal, KConfig *cfg); + virtual ~CalPrintDay(); + virtual QString description() { return i18n("Print day"); } + virtual QString longDescription() { return i18n("Prints all events of a single day on one page"); } + virtual QWidget *configWidget( QWidget* ); + + public slots: + void print(QPainter &p, int width, int height); + virtual void readSettingsWidget(); + virtual void setSettingsWidget(); + virtual void loadConfig(); + virtual void saveConfig(); + virtual void setDateRange( const QDate& from, const QDate& to ); + + protected: + QTime mStartTime, mEndTime; + bool mIncludeTodos; + bool mIncludeAllEvents; + CalPrintDayConfig_Base *mConfigWidget; +}; + +class CalPrintWeek : public CalPrintBase +{ + Q_OBJECT + public: + CalPrintWeek(KPrinter *printer, Calendar *cal, KConfig *cfg); + virtual ~CalPrintWeek(); + virtual QString description() { return i18n("Print week"); } + virtual QString longDescription() { return i18n("Prints all events of one week on one page"); } + virtual QWidget *configWidget(QWidget*); + virtual KPrinter::Orientation orientation(); + + public slots: + void print(QPainter &p, int width, int height); + virtual void readSettingsWidget(); + virtual void setSettingsWidget(); + virtual void loadConfig(); + virtual void saveConfig(); + virtual void setDateRange( const QDate& from, const QDate& to ); + + protected: + enum eWeekPrintType { Filofax=0, Timetable, SplitWeek } mWeekPrintType; + QTime mStartTime, mEndTime; + bool mIncludeTodos; + CalPrintWeekConfig_Base *mConfigWidget; +}; + +class CalPrintMonth : public CalPrintBase +{ + Q_OBJECT + public: + CalPrintMonth(KPrinter *printer, Calendar *cal, KConfig *cfg); + virtual ~CalPrintMonth(); + virtual QString description() { return i18n("Print month"); } + virtual QString longDescription() { return i18n("Prints all events of one month on one page"); } + virtual QWidget *configWidget(QWidget*); + virtual KPrinter::Orientation orientation() { return KPrinter::Landscape; } + + public slots: + void print(QPainter &p, int width, int height); + virtual void readSettingsWidget(); + virtual void setSettingsWidget(); + virtual void loadConfig(); + virtual void saveConfig(); + virtual void setDateRange( const QDate& from, const QDate& to ); + + protected: + bool mWeekNumbers; + bool mIncludeTodos; + CalPrintMonthConfig_Base *mConfigWidget; +}; + +class CalPrintTodos : public CalPrintBase +{ + Q_OBJECT + public: + CalPrintTodos(KPrinter *printer, Calendar *cal, KConfig *cfg); + virtual ~CalPrintTodos(); + virtual QString description() { return i18n("Print todos"); } + virtual QString longDescription() { return i18n("Prints all todos in a (tree-like) list"); } + virtual QWidget *configWidget(QWidget*); + + public slots: + void print(QPainter &p, int width, int height); + virtual void readSettingsWidget(); + virtual void setSettingsWidget(); + virtual void loadConfig(); + virtual void saveConfig(); + + protected: + QString mPageTitle; + + enum eTodoPrintType { + TodosAll = 0, TodosUnfinished, TodosDueRange + } mTodoPrintType; + + bool mIncludeDescription; + bool mIncludePriority; + bool mIncludeDueDate; + bool mConnectSubTodos; + CalPrintTodoConfig_Base *mConfigWidget ; +}; + +#endif +#endif diff --git a/korganizer/calprinttodoconfig_base.ui b/korganizer/calprinttodoconfig_base.ui new file mode 100644 index 0000000..010a489 --- a/dev/null +++ b/korganizer/calprinttodoconfig_base.ui @@ -0,0 +1,239 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>CalPrintTodoConfig_Base</class> +<comment>Configuration page for the print day mode.</comment> +<author>Reinhold Kainhofer <reinhold@kainhofer.com></author> +<widget class="QWidget"> + <property name="name"> + <cstring>CalPrintTodoConfig_Base</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>361</width> + <height>271</height> + </rect> + </property> + <property name="caption"> + <string>CalPrintTodoConfig_Base</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>mDescription</cstring> + </property> + <property name="text"> + <string>Include &description of the item</string> + </property> + </widget> + <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>mDueDate</cstring> + </property> + <property name="text"> + <string>Include d&ue date of the item</string> + </property> + </widget> + <widget class="QCheckBox" row="3" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>mPriority</cstring> + </property> + <property name="text"> + <string>Include &priority of the item</string> + </property> + </widget> + <widget class="QButtonGroup" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>mPrintType</cstring> + </property> + <property name="title"> + <string>Items to Print</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="4" column="1"> + <property name="name"> + <cstring>mFromDateLabel</cstring> + </property> + <property name="text"> + <string>&From:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mFromDate</cstring> + </property> + </widget> + <widget class="QLabel" row="4" column="3"> + <property name="name"> + <cstring>mToDateLabel</cstring> + </property> + <property name="text"> + <string>&To:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mToDate</cstring> + </property> + </widget> + <spacer row="4" column="5"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>21</height> + </size> + </property> + </spacer> + <spacer row="4" column="0"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="5"> + <property name="name"> + <cstring>mPrintAll</cstring> + </property> + <property name="text"> + <string>Print &all todo items</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0" rowspan="1" colspan="5"> + <property name="name"> + <cstring>mPrintUnfinished</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Print only &uncompleted items</string> + </property> + <property name="accel"> + <string>Alt+U</string> + </property> + </widget> + <widget class="QDateEdit" row="4" column="4"> + <property name="name"> + <cstring>mToDate</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="order"> + <enum>DMY</enum> + </property> + </widget> + <widget class="QDateEdit" row="4" column="2"> + <property name="name"> + <cstring>mFromDate</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="order"> + <enum>DMY</enum> + </property> + </widget> + <widget class="QRadioButton" row="3" column="0" rowspan="1" colspan="5"> + <property name="name"> + <cstring>mPrintDueRange</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Only items due in the &range:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>mTitle</cstring> + </property> + <property name="text"> + <string>Todo List</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>mTitleLabel</cstring> + </property> + <property name="text"> + <string>&Title:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mTitle</cstring> + </property> + </widget> + <widget class="QCheckBox" row="5" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>mConnectSubTodos</cstring> + </property> + <property name="text"> + <string>Co&nnect subtodos with its parent</string> + </property> + </widget> + <spacer row="6" 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>0</height> + </size> + </property> + </spacer> + </grid> +</widget> +<connections> + <connection> + <sender>mPrintDueRange</sender> + <signal>toggled(bool)</signal> + <receiver>mFromDate</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>mPrintDueRange</sender> + <signal>toggled(bool)</signal> + <receiver>mToDate</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/korganizer/calprintweekconfig_base.ui b/korganizer/calprintweekconfig_base.ui new file mode 100644 index 0000000..c770239 --- a/dev/null +++ b/korganizer/calprintweekconfig_base.ui @@ -0,0 +1,318 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>CalPrintWeekConfig_Base</class> +<comment>Configuration page for the print week mode.</comment> +<author>Reinhold Kainhofer <reinhold@kainhofer.com></author> +<widget class="QWidget"> + <property name="name"> + <cstring>CalPrintWeek_Base</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>374</width> + <height>252</height> + </rect> + </property> + <property name="caption"> + <string>CalPrintWeek_Base</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <spacer row="4" 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>21</width> + <height>27</height> + </size> + </property> + </spacer> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>mDateRangeGroup</cstring> + </property> + <property name="title"> + <string>Date && Time Range</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>mToDateLabel</cstring> + </property> + <property name="text"> + <string>&End date:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mToDate</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>mFromDateLabel</cstring> + </property> + <property name="text"> + <string>&Start date:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mFromDate</cstring> + </property> + </widget> + <widget class="KDateEdit" row="0" column="1"> + <property name="name"> + <cstring>mFromDate</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>3</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="focusPolicy"> + <enum>StrongFocus</enum> + </property> + </widget> + <widget class="KDateEdit" row="0" column="3"> + <property name="name"> + <cstring>mToDate</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>3</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="focusPolicy"> + <enum>StrongFocus</enum> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox" row="3" column="0"> + <property name="name"> + <cstring>mColors</cstring> + </property> + <property name="text"> + <string>Use &colors</string> + </property> + </widget> + <widget class="QButtonGroup" row="1" column="0"> + <property name="name"> + <cstring>mPrintType</cstring> + </property> + <property name="title"> + <string>Type of View</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="6"> + <property name="name"> + <cstring>mPrintTypeButton1</cstring> + </property> + <property name="text"> + <string>Print as &Filofax page</string> + </property> + <property name="accel"> + <string>Alt+F</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0" rowspan="1" colspan="6"> + <property name="name"> + <cstring>mPrintTypeButton2</cstring> + </property> + <property name="text"> + <string>Print as &timetable view:</string> + </property> + <property name="accel"> + <string>Alt+T</string> + </property> + </widget> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>mFromTimeLabel</cstring> + </property> + <property name="text"> + <string>Start &time:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mFromTime</cstring> + </property> + </widget> + <widget class="QTimeEdit" row="2" column="2"> + <property name="name"> + <cstring>mFromTime</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="time"> + <time> + <hour>0</hour> + <minute>8</minute> + <second>0</second> + </time> + </property> + </widget> + <widget class="QLabel" row="2" column="3"> + <property name="name"> + <cstring>mToTimeLabel</cstring> + </property> + <property name="text"> + <string>End ti&me:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mToTime</cstring> + </property> + </widget> + <widget class="QTimeEdit" row="2" column="4"> + <property name="name"> + <cstring>mToTime</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="time"> + <time> + <hour>16</hour> + <minute>0</minute> + <second>0</second> + </time> + </property> + </widget> + <spacer row="2" column="5"> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QRadioButton" row="3" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>radioButton3</cstring> + </property> + <property name="text"> + <string>Print as split week view</string> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>mIncludeTodos</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Include to&dos that are due on the printed day(s)</string> + </property> + </widget> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>KDateEdit</class> + <header location="local">libkdepim/kdateedit.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="826">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000030149444154789cb59531681b5718c77f0e377c070e3c810a3a70e0041eac51852e0a19e45134830a1d9a4c69a04bc8928e990a693a640e1d0c8642b08742321894c1507991b484c890902bb8701a047760c3bd21701fe4201dde49b6a41a32b8df72dcbbeffdbefffbbfefbd5b1b0c07cce266ebe667ae2006c3c1dada0cdc3be87d6e6c35b0d692a409d9c7ec8b20d65ae29398d19b1114e7e3de4ce98b3f5e10dc0053cf0951b4506496e1b964bf7ce6c585d9054c62d01d617ca48be0596553cf496d8f2c8b01c5f795fc93904e85ec4c01a152857a5d9175d0b2805c872080f18595ccc1499a10a225d4e2fbc2877786fe81253ab6c04c8d106e09db5d43ab0d146e5c64d1a23938fb98a185cea1c33eecfd9eba49eb427dcb201e245365f2b7b2fb5b4a3a31dcb927178afe07d86901df870fefa4842aed6f6b74ba42e52b4014d580e1eb9cbd9d94de7e4aad16d2f9be02d805f0b5e532f927a1ffcacea1777f122a8105b164a7c25faf323a5d9f1f1fd600e1e5bec59e2d4b5c7ef5209d0ad17b8b31864e57c0b3e0815ac3ee33253ab664a770ff5185d1a1cb8d2267d3e58aa1dc7d2508cbe597d0e74fdd269aaaf0f52d414c4ea3e9762c996869e42560d7a72e41c4799a2586e74f95e8d8151481fa86efbe7b3398ac58b1a2b8527589f15451ad303ac2293542ad6648a796278f13a27185e4c4754310facb98c53a79e19a3fdc1426ff28c3d7399d1f7cb25343eb96106cf83c790ce9c4f2eb831855c55485663327992eb6dc8a6259874ed700b0b793323cccb9ffa842b30d6133e3e75fea989ac15a8b16ca76b746b0b92278d919774c5b6d48a78697fb29bbcf52468742a32120909c24e899ce67beed5be2db01e22d1e9485bb620e47f9ee9e606a21bd3f5d3744c7e7c54d55e87443867d8b554515ac5db4620e8e4f62263170fd1cdee90aad7640141992891b0f367c9adfe4049bb07d3b7022bd8c687c0978f46684ee084150b65ac1fcca94591b7a90a496e4c095164fb016a2b192a497795cc0f84817aebe25f7bf70ccc54a575c555c03f78ffa5fc0570d1f0c076bff0232285a0901e2257b0000000049454e44ae426082</data> + </image> +</images> +<connections> + <connection> + <sender>mPrintTypeButton2</sender> + <signal>toggled(bool)</signal> + <receiver>mFromTime</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>mPrintTypeButton2</sender> + <signal>toggled(bool)</signal> + <receiver>mToTime</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kdateedit.h</includehint> + <includehint>kdateedit.h</includehint> +</includehints> +</UI> diff --git a/korganizer/categoryeditdialog.moc b/korganizer/categoryeditdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/categoryeditdialog.moc diff --git a/korganizer/categoryselectdialog.moc b/korganizer/categoryselectdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/categoryselectdialog.moc diff --git a/korganizer/cellitem.cpp b/korganizer/cellitem.cpp new file mode 100644 index 0000000..61d06ac --- a/dev/null +++ b/korganizer/cellitem.cpp @@ -0,0 +1,98 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "cellitem.h" + +#include <klocale.h> +#include <kdebug.h> + +#include <qintdict.h> + +using namespace KOrg; + +QString CellItem::label() const +{ + return i18n("<undefined>"); +} + +QPtrList<CellItem> CellItem::placeItem( QPtrList<CellItem> cells, + CellItem *placeItem ) +{ + kdDebug(5855) << "Placing " << placeItem->label() << endl; + + QPtrList<KOrg::CellItem> conflictItems; + int maxSubCells = 0; + QIntDict<KOrg::CellItem> subCellDict; + + // Find all items which are in same cell + QPtrListIterator<KOrg::CellItem> it2( cells ); + for( it2.toFirst(); it2.current(); ++it2 ) { + KOrg::CellItem *item = it2.current(); + if ( item == placeItem ) continue; + + if ( item->overlaps( placeItem ) ) { + kdDebug(5855) << " Overlaps: " << item->label() << endl; + + conflictItems.append( item ); + if ( item->subCells() > maxSubCells ) maxSubCells = item->subCells(); + subCellDict.insert( item->subCell(), item ); + } + } + + if ( conflictItems.count() > 0 ) { + // Look for unused sub cell and insert item + int i; + for( i = 0; i < maxSubCells; ++i ) { + kdDebug(5855) << " Trying subcell " << i << endl; + if ( !subCellDict.find( i ) ) { + kdDebug(5855) << " Use subcell " << i << endl; + placeItem->setSubCell( i ); + break; + } + } + if ( i == maxSubCells ) { + kdDebug(5855) << " New subcell " << i << endl; + placeItem->setSubCell( maxSubCells ); + maxSubCells++; // add new item to number of sub cells + } + + kdDebug(5855) << " Sub cells: " << maxSubCells << endl; + + // Write results to item to be placed + conflictItems.append( placeItem ); + placeItem->setSubCells( maxSubCells ); + + QPtrListIterator<KOrg::CellItem> it3( conflictItems ); + for( it3.toFirst(); it3.current(); ++it3 ) { + (*it3)->setSubCells( maxSubCells ); + } + // Todo: Adapt subCells of items conflicting with conflicting items + } else { + kdDebug(5855) << " no conflicts" << endl; + placeItem->setSubCell( 0 ); + placeItem->setSubCells( 1 ); + } + + return conflictItems; +} diff --git a/korganizer/cellitem.h b/korganizer/cellitem.h new file mode 100644 index 0000000..72773d0 --- a/dev/null +++ b/korganizer/cellitem.h @@ -0,0 +1,66 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KORG_CELLITEM_H +#define KORG_CELLITEM_H + +#include <qstring.h> +#include <qptrlist.h> + +namespace KOrg { + +class CellItem +{ + public: + CellItem() + : mSubCells( 0 ), mSubCell( -1 ) + { + } + + void setSubCells( int v ) { mSubCells = v; } + int subCells() const { return mSubCells; } + + void setSubCell( int v ) { mSubCell = v; } + int subCell() const { return mSubCell; } + + virtual bool overlaps( CellItem *other ) const = 0; + + virtual QString label() const; + + /** + Place item \arg placeItem into stripe containing items \arg cells in a + way that items don't overlap. + + \return Placed items + */ + static QPtrList<CellItem> placeItem( QPtrList<CellItem> cells, + CellItem *placeItem ); + + private: + int mSubCells; + int mSubCell; +}; + +} + +#endif diff --git a/korganizer/customlistviewitem.h b/korganizer/customlistviewitem.h new file mode 100644 index 0000000..94e5bce --- a/dev/null +++ b/korganizer/customlistviewitem.h @@ -0,0 +1,38 @@ +#ifndef CUSTOMLISTVIEWITEM_H +#define CUSTOMLISTVIEWITEM_H + +#include <qmap.h> +#include <qstring.h> +#include <klistview.h> + +template<class T> +class CustomListViewItem : public KListViewItem +{ + public: + CustomListViewItem( T data, KListView *parent ) : + KListViewItem( parent ), mData( data ) { updateItem(); }; + ~CustomListViewItem() {}; + + void updateItem() {}; + + T data() const { return mData; } + + QString key(int column, bool) const + { + QMap<int,QString>::ConstIterator it = mKeyMap.find(column); + if (it == mKeyMap.end()) return text(column); + else return *it; + } + + void setSortKey(int column,const QString &key) + { + mKeyMap.insert(column,key); + } + + private: + T mData; + + QMap<int,QString> mKeyMap; +}; + +#endif diff --git a/korganizer/datenavigator.cpp b/korganizer/datenavigator.cpp new file mode 100644 index 0000000..8d35c42 --- a/dev/null +++ b/korganizer/datenavigator.cpp @@ -0,0 +1,287 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "datenavigator.h" + +#include "koglobals.h" + +#include <kcalendarsystem.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> + +using namespace KCal; + +DateNavigator::DateNavigator( QObject *parent, const char *name , KOViewManager * v) + : QObject( parent, name ) +{ + mViewManager = v; + mSelectedDates.append( QDate::currentDate() ); +} + +DateNavigator::~DateNavigator() +{ +} + +void DateNavigator::slotMonthSelect( int m ) +{ + QDate firstSelected = mSelectedDates.first(); + int weekDay = firstSelected.dayOfWeek(); + int diff = m - firstSelected.month() ; + firstSelected = KOGlobals::self()->calendarSystem()->addMonths( firstSelected, diff ); + + if ( mSelectedDates.first().day() == 1 && mSelectedDates.count() > 27 ) + selectMonthByDate( firstSelected ); + else + selectWeekByDay( weekDay, firstSelected ); + +} + +void DateNavigator::slotDaySelect( QDate d ) +{ + QDate firstSelected = mSelectedDates.first(); + int weekDay = firstSelected.dayOfWeek(); + //int diff = firstSelected.daysTo( d ) ; + firstSelected = firstSelected.addDays( firstSelected .daysTo( d ) ); + + selectWeekByDay( weekDay, firstSelected ); + +} + +void DateNavigator::selectMonthByDate( const QDate & firstSelected ) +{ + + int monthDay = firstSelected.day(); + QDate date = firstSelected.addDays( 1-monthDay ); + selectDates( date , date.daysInMonth ()); + +} +void DateNavigator::selectMonth() +{ + + QDate date =mSelectedDates.first(); + selectMonthByDate( date ); +} + +DateList DateNavigator::selectedDates() +{ + return mSelectedDates; +} + +int DateNavigator::datesCount() const +{ + return mSelectedDates.count(); +} + +void DateNavigator::selectDates( const DateList& dateList ) +{ + if (dateList.count() > 0) { + mSelectedDates = dateList; + emitSelected(); + } +} + +void DateNavigator::selectDate( const QDate &date ) +{ + QDate d = date; + + if ( !d.isValid() ) { + d = QDate::currentDate(); + } + + mSelectedDates.clear(); + mSelectedDates.append( d ); + + emitSelected(); +} + +void DateNavigator::selectDates( int count ) +{ + + QDate d = mSelectedDates.first(); + selectDates( d, count ); +} + +void DateNavigator::selectDates( const QDate &d, int count ) +{ + DateList dates; + + int i; + for( i = 0; i < count; ++i ) { + dates.append( d.addDays( i ) ); + } + + mSelectedDates = dates; + + emitSelected(); +} + +void DateNavigator::selectWeekByDay( int weekDay, const QDate &d ) +{ + // qDebug("selectWeekByDay( %d %s ", weekDay, d.toString().latin1()); + int dateCount = mSelectedDates.count(); + bool weekStart = ( weekDay == KGlobal::locale()->weekStartDay() ); + if ( weekDay == 1 && dateCount == 5 ) selectWorkWeek( d ); + else if ( weekStart && dateCount == 7 ) selectWeek( d ); + else selectDates( d, dateCount ); +} + +void DateNavigator::selectWeek() +{ + QDate d = mSelectedDates.first(); + selectWeek( d ); +} +void DateNavigator::selectWeek( int num ) +{ + int year = mSelectedDates.first().year(); + if ( mSelectedDates.first().dayOfYear() > 300 && num < 10 ) + ++year; + if ( mSelectedDates.first().dayOfYear() < 70 && num > 40 ) + --year; + QDate d = QDate ( year, 1,1); + while ( d.dayOfWeek() != 4 ) + d = d.addDays( 1 ); + selectWeek( d.addDays ( (num-1) *7 ) ); +} +void DateNavigator::selectWeek( const QDate &d ) +{ + int dayOfWeek = KOGlobals::self()->calendarSystem()->dayOfWeek( d ); + + int weekStart = KGlobal::locale()->weekStartDay(); + QDate firstDate = d.addDays( weekStart - dayOfWeek ); + + if ( weekStart != 1 && dayOfWeek < weekStart ) { + firstDate = firstDate.addDays(-7 ); + } + + + selectDates( firstDate, 7 ); +} + +void DateNavigator::selectWorkWeek() +{ + QDate d = mSelectedDates.first(); + selectWorkWeek( d ); +} + +void DateNavigator::selectWorkWeek( const QDate &d ) +{ + int dayOfWeek = KOGlobals::self()->calendarSystem()->dayOfWeek( d ); + + QDate firstDate = d.addDays( 1 - dayOfWeek ); + + int weekStart = KGlobal::locale()->weekStartDay(); + if ( weekStart != 1 && dayOfWeek >= weekStart ) { + firstDate = firstDate.addDays( 7 ); + } + + selectDates( firstDate, 5 ); +} + +void DateNavigator::selectToday() +{ + QDate d = QDate::currentDate(); + + int dateCount = mSelectedDates.count(); + + if ( dateCount == 5 ) selectWorkWeek( d ); + else if ( dateCount == 7 ) selectWeek( d ); + else selectDates( d, dateCount ); +} + +void DateNavigator::selectPreviousYear() +{ + QDate firstSelected = mSelectedDates.first(); + int weekDay = firstSelected.dayOfWeek(); + firstSelected = KOGlobals::self()->calendarSystem()->addYears( firstSelected, -1 ); + + selectWeekByDay( weekDay, firstSelected ); +} + +void DateNavigator::selectPreviousMonth() +{ + QDate firstSelected = mSelectedDates.first(); + int weekDay = firstSelected.dayOfWeek(); + firstSelected = KOGlobals::self()->calendarSystem()->addMonths( firstSelected, -1 ); + + + if ( mSelectedDates.first().day() == 1 && mSelectedDates.count() > 27 ) + selectMonthByDate( firstSelected ); + else + selectWeekByDay( weekDay, firstSelected ); +} + +void DateNavigator::selectNextMonth() +{ + QDate firstSelected = mSelectedDates.first(); + int weekDay = firstSelected.dayOfWeek(); + + firstSelected = KOGlobals::self()->calendarSystem()->addMonths( firstSelected, 1 ); + + if ( mSelectedDates.first().day() == 1 && mSelectedDates.count() > 27 ) + selectMonthByDate( firstSelected ); + else + selectWeekByDay( weekDay, firstSelected ); + +} + +void DateNavigator::selectNextYear() +{ + QDate firstSelected = mSelectedDates.first(); + int weekDay = firstSelected.dayOfWeek(); + firstSelected = KOGlobals::self()->calendarSystem()->addYears( firstSelected, 1 ); + + selectWeekByDay( weekDay, firstSelected ); +} + +void DateNavigator::selectPrevious() +{ + int offset = -7; + if ( datesCount() == 1 ) { + offset = -1; + } + if ( mViewManager ) + if ( mViewManager->showsNextDays() ) + offset = -datesCount(); + selectDates( mSelectedDates.first().addDays( offset ), datesCount() ); +} + +void DateNavigator::selectNext() +{ + int offset = 7; + if ( datesCount() == 1 ) { + offset = 1; + } + if ( mViewManager ) + if ( mViewManager->showsNextDays() ) + offset = datesCount(); + selectDates( mSelectedDates.first().addDays( offset ), datesCount() ); +} + +void DateNavigator::emitSelected() +{ + emit datesSelected( mSelectedDates ); +} + +#include "datenavigator.moc" diff --git a/korganizer/datenavigator.h b/korganizer/datenavigator.h new file mode 100644 index 0000000..747e3d3 --- a/dev/null +++ b/korganizer/datenavigator.h @@ -0,0 +1,89 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef DATENAVIGATOR_H +#define DATENAVIGATOR_H + +#include <libkcal/incidencebase.h> + +#include <qobject.h> +#include "koviewmanager.h" + +/** + This class controls date navigation. All requests to move the views to another + date are sent to the DateNavigator. The DateNavigator processes the new + selection of dates and emits the required signals for the views. +*/ +class DateNavigator : public QObject +{ + Q_OBJECT + public: + DateNavigator( QObject *parent = 0, const char *name = 0 , KOViewManager * v = 0); + ~DateNavigator(); + + KCal::DateList selectedDates(); + + int datesCount() const; + + public slots: + void selectDates( const KCal::DateList & ); + void selectDate( const QDate & ); + + void selectDates( int count ); + void selectDates( const QDate &, int count ); + + void selectWeek(); + void selectWeek( int weeknum ); + void selectWeek( const QDate & ); + + void selectWorkWeek(); + void selectWorkWeek( const QDate & ); + + void selectWeekByDay( int weekDay, const QDate & ); + + void selectToday(); + + void selectPreviousYear(); + void selectPreviousMonth(); + void selectNextMonth(); + void selectNextYear(); + + void selectMonth(); + void selectMonthByDate( const QDate & ); + + void selectPrevious(); + void selectNext(); + void slotMonthSelect( int ); + void slotDaySelect( QDate d ); + + signals: + void datesSelected( const KCal::DateList & ); + + protected: + void emitSelected(); + + private: + KOViewManager * mViewManager; + KCal::DateList mSelectedDates; +}; + +#endif diff --git a/korganizer/datenavigator.moc b/korganizer/datenavigator.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/datenavigator.moc diff --git a/korganizer/docprefs.cpp b/korganizer/docprefs.cpp new file mode 100644 index 0000000..f849aaa --- a/dev/null +++ b/korganizer/docprefs.cpp @@ -0,0 +1,64 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <stdlib.h> + +#include "docprefs.h" + +KSimpleConfig *DocPrefs::mConfig = 0; + +DocPrefs::DocPrefs( const QString &type ) +{ + if ( !mConfig ) { + mConfig = new KSimpleConfig( locateLocal( "config", "docprefs." + type ) ); + } +} + +DocPrefs::~DocPrefs() +{ + mConfig->sync(); +} + +void DocPrefs::setDoc( const QString &identifier ) +{ + mDocId = identifier; +} + +QString DocPrefs::doc() const +{ + return mDocId; +} + +bool DocPrefs::readBoolEntry( const QString &id ) const +{ + mConfig->setGroup( mDocId ); + bool result = mConfig->readBoolEntry( id, false ); +// kdDebug() << "DocPrefs::readEntry(): " << id << " : " << (result ? "True" : "False" ) << endl; + return result; +} + +void DocPrefs::writeEntry( const QString &id, bool value ) +{ +// kdDebug() << "DocPrefs::writeEntry(): " << id << " : " << (value ? "True" : "False" ) << endl; + mConfig->setGroup( mDocId ); + mConfig->writeEntry( id, value ); +} diff --git a/korganizer/docprefs.h b/korganizer/docprefs.h new file mode 100644 index 0000000..88751fe --- a/dev/null +++ b/korganizer/docprefs.h @@ -0,0 +1,44 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef DOCPREFS_H +#define DOCPREFS_H + +#include <qstring.h> + +class KSimpleConfig; + +class DocPrefs +{ + public: + DocPrefs( const QString &type="general" ); + ~DocPrefs(); + + void setDoc( const QString &identifier ); + QString doc() const; + + bool readBoolEntry( const QString &identifier ) const; + void writeEntry( const QString &identifier, bool value ); + + private: + static KSimpleConfig *mConfig; + + QString mDocId; +}; + +#endif diff --git a/korganizer/filteredit_base.cpp b/korganizer/filteredit_base.cpp new file mode 100644 index 0000000..21a0954 --- a/dev/null +++ b/korganizer/filteredit_base.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** Form implementation generated from reading ui file 'filteredit_base.ui' +** +** Created: Di Mai 4 15:30:31 2004 +** by: The User Interface Compiler ($Id$) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#include "filteredit_base.h" + +#include <qvariant.h> +#include <qpushbutton.h> +#include <qframe.h> +#include <qbuttongroup.h> +#include <qradiobutton.h> +#include <qlistbox.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a FilterEdit_base as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + */ +FilterEdit_base::FilterEdit_base( QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) +{ + if ( !name ) + setName( "FilterEdit_base" ); + FilterEdit_baseLayout = new QVBoxLayout( this, 0, 0, "FilterEdit_baseLayout"); + + mCriteriaFrame = new QFrame( this, "mCriteriaFrame" ); + mCriteriaFrame->setFrameShape( QFrame::StyledPanel ); + mCriteriaFrame->setFrameShadow( QFrame::Raised ); + mCriteriaFrameLayout = new QGridLayout( mCriteriaFrame, 1, 1, 3, 2, "mCriteriaFrameLayout"); + + ButtonGroup1 = new QButtonGroup( mCriteriaFrame, "ButtonGroup1" ); + ButtonGroup1->setColumnLayout(0, Qt::Vertical ); + ButtonGroup1->layout()->setSpacing( 6 ); + ButtonGroup1->layout()->setMargin( 11 ); + ButtonGroup1Layout = new QVBoxLayout( ButtonGroup1->layout() ); + ButtonGroup1Layout->setAlignment( Qt::AlignTop ); + + mCatShowCheck = new QRadioButton( ButtonGroup1, "mCatShowCheck" ); + ButtonGroup1Layout->addWidget( mCatShowCheck ); + + mCatHideCheck = new QRadioButton( ButtonGroup1, "mCatHideCheck" ); + ButtonGroup1Layout->addWidget( mCatHideCheck ); + + mCatList = new QListBox( ButtonGroup1, "mCatList" ); + ButtonGroup1Layout->addWidget( mCatList ); + + mCatEditButton = new QPushButton( ButtonGroup1, "mCatEditButton" ); + ButtonGroup1Layout->addWidget( mCatEditButton ); + + mCriteriaFrameLayout->addWidget( ButtonGroup1, 0, 0 ); + + layout1 = new QHBoxLayout( 0, 0, 0, "layout1"); + + textLabel1 = new QLabel( mCriteriaFrame, "textLabel1" ); + layout1->addWidget( textLabel1 ); + + mRecurringCheck = new QCheckBox( mCriteriaFrame, "mRecurringCheck" ); + layout1->addWidget( mRecurringCheck ); + + mCompletedCheck = new QCheckBox( mCriteriaFrame, "mCompletedCheck" ); + layout1->addWidget( mCompletedCheck ); + + mCriteriaFrameLayout->addLayout( layout1, 1, 0 ); + + layout2 = new QHBoxLayout( 0, 0, 0, "layout2"); + + textLabel2 = new QLabel( mCriteriaFrame, "textLabel2" ); + layout2->addWidget( textLabel2 ); + + mPublicCheck = new QCheckBox( mCriteriaFrame, "mPublicCheck" ); + layout2->addWidget( mPublicCheck ); + + mPrivateCheck = new QCheckBox( mCriteriaFrame, "mPrivateCheck" ); + layout2->addWidget( mPrivateCheck ); + + mConfidentialCheck = new QCheckBox( mCriteriaFrame, "mConfidentialCheck" ); + mConfidentialCheck->setChecked( FALSE ); + layout2->addWidget( mConfidentialCheck ); + + mCriteriaFrameLayout->addLayout( layout2, 2, 0 ); + FilterEdit_baseLayout->addWidget( mCriteriaFrame ); + languageChange(); + resize( QSize(284, 241).expandedTo(minimumSizeHint()) ); + clearWState( WState_Polished ); +} + +/* + * Destroys the object and frees any allocated resources + */ +FilterEdit_base::~FilterEdit_base() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void FilterEdit_base::languageChange() +{ + setCaption( tr( "FilterEditor" ) ); + ButtonGroup1->setTitle( tr( "Categories" ) ); + mCatShowCheck->setText( tr( "Show only selected" ) ); + mCatHideCheck->setText( tr( "Show all but selected" ) ); + mCatEditButton->setText( tr( "Edit Selection..." ) ); + textLabel1->setText( tr( "Hide" ) ); + mRecurringCheck->setText( tr( "recurring events" ) ); + mCompletedCheck->setText( tr( "completed to-dos" ) ); + textLabel2->setText( tr( "Show" ) ); + mPublicCheck->setText( tr( "public" ) ); + mPrivateCheck->setText( tr( "private" ) ); + mConfidentialCheck->setText( tr( "confidential" ) ); +} + +void FilterEdit_base::updateFilter() +{ + qWarning( "FilterEdit_base::updateFilter(): Not implemented yet" ); +} + diff --git a/korganizer/filteredit_base.cpp.emb b/korganizer/filteredit_base.cpp.emb new file mode 100644 index 0000000..9e32851 --- a/dev/null +++ b/korganizer/filteredit_base.cpp.emb @@ -0,0 +1,97 @@ +/**************************************************************************** +** Form implementation generated from reading ui file 'filteredit_base.ui' +** +** Created: Do Jan 22 23:56:40 2004 +** by: The User Interface Compiler ($Id$) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#include "filteredit_base.h" + +#include <qvariant.h> +#include <qpushbutton.h> +#include <qframe.h> +#include <qbuttongroup.h> +#include <qradiobutton.h> +#include <qlistbox.h> +#include <qcheckbox.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a FilterEdit_base as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + */ +FilterEdit_base::FilterEdit_base( QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) +{ + if ( !name ) + setName( "FilterEdit_base" ); + FilterEdit_baseLayout = new QVBoxLayout( this, 0, 0, "FilterEdit_baseLayout"); + + mCriteriaFrame = new QFrame( this, "mCriteriaFrame" ); + mCriteriaFrame->setFrameShape( QFrame::StyledPanel ); + mCriteriaFrame->setFrameShadow( QFrame::Raised ); + mCriteriaFrameLayout = new QVBoxLayout( mCriteriaFrame, 11, 6, "mCriteriaFrameLayout"); + + ButtonGroup1 = new QButtonGroup( mCriteriaFrame, "ButtonGroup1" ); + ButtonGroup1->setColumnLayout(0, Qt::Vertical ); + ButtonGroup1->layout()->setSpacing( 6 ); + ButtonGroup1->layout()->setMargin( 11 ); + ButtonGroup1Layout = new QVBoxLayout( ButtonGroup1->layout() ); + ButtonGroup1Layout->setAlignment( Qt::AlignTop ); + + mCatShowCheck = new QRadioButton( ButtonGroup1, "mCatShowCheck" ); + ButtonGroup1Layout->addWidget( mCatShowCheck ); + + mCatHideCheck = new QRadioButton( ButtonGroup1, "mCatHideCheck" ); + ButtonGroup1Layout->addWidget( mCatHideCheck ); + + mCatList = new QListBox( ButtonGroup1, "mCatList" ); + ButtonGroup1Layout->addWidget( mCatList ); + + mCatEditButton = new QPushButton( ButtonGroup1, "mCatEditButton" ); + ButtonGroup1Layout->addWidget( mCatEditButton ); + mCriteriaFrameLayout->addWidget( ButtonGroup1 ); + + mRecurringCheck = new QCheckBox( mCriteriaFrame, "mRecurringCheck" ); + mCriteriaFrameLayout->addWidget( mRecurringCheck ); + + mCompletedCheck = new QCheckBox( mCriteriaFrame, "mCompletedCheck" ); + mCriteriaFrameLayout->addWidget( mCompletedCheck ); + FilterEdit_baseLayout->addWidget( mCriteriaFrame ); + languageChange(); + resize( QSize(196, 257).expandedTo(minimumSizeHint()) ); + clearWState( WState_Polished ); +} + +/* + * Destroys the object and frees any allocated resources + */ +FilterEdit_base::~FilterEdit_base() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void FilterEdit_base::languageChange() +{ + setCaption( tr( "FilterEditor" ) ); + ButtonGroup1->setTitle( tr( "Categories" ) ); + mCatShowCheck->setText( tr( "Show only selected" ) ); + mCatHideCheck->setText( tr( "Show all but selected" ) ); + mCatEditButton->setText( tr( "Edit Selection..." ) ); + mRecurringCheck->setText( tr( "Hide recurring events" ) ); + mCompletedCheck->setText( tr( "Hide completed to-dos" ) ); +} + +void FilterEdit_base::updateFilter() +{ + qWarning( "FilterEdit_base::updateFilter(): Not implemented yet" ); +} + diff --git a/korganizer/filteredit_base.h b/korganizer/filteredit_base.h new file mode 100644 index 0000000..664598a --- a/dev/null +++ b/korganizer/filteredit_base.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** Form interface generated from reading ui file 'filteredit_base.ui' +** +** Created: Di Mai 4 15:24:50 2004 +** by: The User Interface Compiler ($Id$) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#ifndef FILTEREDIT_BASE_H +#define FILTEREDIT_BASE_H + +#include <qvariant.h> +#include <qwidget.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QSpacerItem; +class QFrame; +class QButtonGroup; +class QRadioButton; +class QListBox; +class QListBoxItem; +class QPushButton; +class QLabel; +class QCheckBox; + +class FilterEdit_base : public QWidget +{ + Q_OBJECT + +public: + FilterEdit_base( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~FilterEdit_base(); + + QFrame* mCriteriaFrame; + QButtonGroup* ButtonGroup1; + QRadioButton* mCatShowCheck; + QRadioButton* mCatHideCheck; + QListBox* mCatList; + QPushButton* mCatEditButton; + QLabel* textLabel1; + QCheckBox* mRecurringCheck; + QCheckBox* mCompletedCheck; + QLabel* textLabel2; + QCheckBox* mPublicCheck; + QCheckBox* mPrivateCheck; + QCheckBox* mConfidentialCheck; + +public slots: + virtual void updateFilter(); + +protected: + QVBoxLayout* FilterEdit_baseLayout; + QGridLayout* mCriteriaFrameLayout; + QVBoxLayout* ButtonGroup1Layout; + QHBoxLayout* layout1; + QHBoxLayout* layout2; + +protected slots: + virtual void languageChange(); + +}; + +#endif // FILTEREDIT_BASE_H diff --git a/korganizer/filteredit_base.h.emb b/korganizer/filteredit_base.h.emb new file mode 100644 index 0000000..8befd6b --- a/dev/null +++ b/korganizer/filteredit_base.h.emb @@ -0,0 +1,57 @@ +/**************************************************************************** +** Form interface generated from reading ui file 'filteredit_base.ui' +** +** Created: Do Jan 22 23:56:38 2004 +** by: The User Interface Compiler ($Id$) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#ifndef FILTEREDIT_BASE_H +#define FILTEREDIT_BASE_H + +#include <qvariant.h> +#include <qwidget.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QFrame; +class QButtonGroup; +class QRadioButton; +class QListBox; +class QListBoxItem; +class QPushButton; +class QCheckBox; + +class FilterEdit_base : public QWidget +{ + Q_OBJECT + +public: + FilterEdit_base( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~FilterEdit_base(); + + QFrame* mCriteriaFrame; + QButtonGroup* ButtonGroup1; + QRadioButton* mCatShowCheck; + QRadioButton* mCatHideCheck; + QListBox* mCatList; + QPushButton* mCatEditButton; + QCheckBox* mRecurringCheck; + QCheckBox* mCompletedCheck; + +public slots: + virtual void updateFilter(); + +protected: + QVBoxLayout* FilterEdit_baseLayout; + QVBoxLayout* mCriteriaFrameLayout; + QVBoxLayout* ButtonGroup1Layout; + +protected slots: + virtual void languageChange(); + +}; + +#endif // FILTEREDIT_BASE_H diff --git a/korganizer/filteredit_base.ui b/korganizer/filteredit_base.ui new file mode 100644 index 0000000..b7cbb59 --- a/dev/null +++ b/korganizer/filteredit_base.ui @@ -0,0 +1,201 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>FilterEdit_base</class> +<widget class="QWidget"> + <property name="name"> + <cstring>FilterEdit_base</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>284</width> + <height>241</height> + </rect> + </property> + <property name="caption"> + <string>FilterEditor</string> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QFrame"> + <property name="name"> + <cstring>mCriteriaFrame</cstring> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>3</number> + </property> + <property name="spacing"> + <number>2</number> + </property> + <widget class="QButtonGroup" row="0" column="0"> + <property name="name"> + <cstring>ButtonGroup1</cstring> + </property> + <property name="title"> + <string>Categories</string> + </property> + <vbox> + <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>mCatShowCheck</cstring> + </property> + <property name="text"> + <string>Show only selected</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mCatHideCheck</cstring> + </property> + <property name="text"> + <string>Show all but selected</string> + </property> + </widget> + <widget class="QListBox"> + <property name="name"> + <cstring>mCatList</cstring> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>mCatEditButton</cstring> + </property> + <property name="text"> + <string>Edit Selection...</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Hide</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>mRecurringCheck</cstring> + </property> + <property name="text"> + <string>recurring events</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>mCompletedCheck</cstring> + </property> + <property name="text"> + <string>completed to-dos</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="2" column="0"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Show</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>mPublicCheck</cstring> + </property> + <property name="text"> + <string>public</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>mPrivateCheck</cstring> + </property> + <property name="text"> + <string>private</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>mConfidentialCheck</cstring> + </property> + <property name="text"> + <string>confidential</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </hbox> + </widget> + </grid> + </widget> + </vbox> +</widget> +<slots> + <slot>updateFilter()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/korganizer/filtereditdialog.cpp b/korganizer/filtereditdialog.cpp new file mode 100644 index 0000000..2943e41 --- a/dev/null +++ b/korganizer/filtereditdialog.cpp @@ -0,0 +1,270 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> +#include <qpushbutton.h> +#include <qcombobox.h> +#include <qcheckbox.h> +#include <qradiobutton.h> +#include <qlistbox.h> +#include <qapplication.h> + +#include <kdebug.h> +#include <klocale.h> +#include <klineeditdlg.h> +#include <kmessagebox.h> + +#include <libkdepim/categoryselectdialog.h> + +#include "koprefs.h" +#include "filteredit_base.h" + +#include "filtereditdialog.h" +#include "filtereditdialog.moc" + +// TODO: Make dialog work on a copy of the filters objects. + +class ComboFilterBox: public QComboBox +{ +public: + ComboFilterBox( QWidget *parent=0, const char *name=0) : + QComboBox( parent,name ) { } + void popupBox() { popup(); } + +}; + +FilterEditDialog::FilterEditDialog(QPtrList<CalFilter> *filters,QWidget *parent, + const char *name) : + KDialogBase(parent,name,true,i18n("Edit Calendar Filters"), + Ok|Apply|Cancel) +{ + mFilters = filters; + + QWidget *mainWidget = new QWidget(this); + setMainWidget(mainWidget); + + mSelectionCombo = new ComboFilterBox(mainWidget); + connect(mSelectionCombo,SIGNAL(activated(int)),SLOT(filterSelected())); + // mSelectionCombo->setEditable ( true ); + QPushButton *addButton = new QPushButton(i18n("Add Filter"),mainWidget); + connect(addButton,SIGNAL(clicked()),SLOT(slotAdd())); + addButton->setMaximumSize( addButton->sizeHint()); + mRemoveButton = new QPushButton( i18n("Remove"), mainWidget ); + connect( mRemoveButton, SIGNAL( clicked() ), SLOT( slotRemove() ) ); + mRemoveButton->setMaximumSize( mRemoveButton->sizeHint()); + + QPushButton *upButton = new QPushButton(i18n("Up"),mainWidget); + upButton->setMaximumSize( upButton->sizeHint()); + connect(upButton,SIGNAL(clicked()),SLOT(slotUp())); + + + mEditor = new FilterEdit_base(mainWidget); + + QGridLayout *topLayout = new QGridLayout(mainWidget,2,2); + topLayout->setSpacing(spacingHint()); + topLayout->addWidget(mSelectionCombo,0,0); + topLayout->addWidget(upButton,0,1); + topLayout->addWidget(addButton,0,2); + topLayout->addWidget(mRemoveButton,0,3); + topLayout->addMultiCellWidget(mEditor,1,1,0,3); + mSelectionCombo->setMaximumWidth ( QApplication::desktop()->width() - + addButton->maximumWidth() - + mRemoveButton->maximumWidth() - + upButton->maximumWidth() - + spacingHint() * 5 ); + connect(mEditor->mCatEditButton,SIGNAL(clicked()), + SLOT(editCategorySelection())); + + // Clicking cancel exits the dialog without saving + connect(this,SIGNAL(cancelClicked()),SLOT(reject())); + updateFilterList(); +} + +FilterEditDialog::~FilterEditDialog() +{ +} +void FilterEditDialog::slotUp() +{ + + if ( mFilters->count() <= 1 ) return; + if ( mSelectionCombo->currentItem() == 0 ) return; + int num = mSelectionCombo->currentItem(); + CalFilter* f = new CalFilter( ); + *f = *(mFilters->at( num )); + mFilters->remove( num ); + mFilters->insert( num-1, f ); + updateFilterList(); + mSelectionCombo->setCurrentItem( num-1 ); + readFilter(f); + //qApp->processEvents(); + //mSelectionCombo->popupBox(); +} +void FilterEditDialog::updateFilterList() +{ + mSelectionCombo->clear(); + + CalFilter *filter = mFilters->first(); + + if (!filter) { + enableButtonOK(false); + enableButtonApply(false); + } else { + while(filter) { + mSelectionCombo->insertItem(filter->name()); + filter = mFilters->next(); + } + CalFilter *f = mFilters->at(mSelectionCombo->currentItem()); + if (f) readFilter(f); + + enableButtonOK(true); + enableButtonApply(true); + } + + mRemoveButton->setEnabled( mFilters->count() > 1 ); +} + +void FilterEditDialog::slotDefault() +{ +} + +void FilterEditDialog::slotApply() +{ + CalFilter *f = mFilters->at(mSelectionCombo->currentItem()); + writeFilter(f); + emit filterChanged(); +} +void FilterEditDialog::accept() +{ + slotOk(); +} +void FilterEditDialog::slotOk() +{ + CalFilter *f = mFilters->at(mSelectionCombo->currentItem()); + writeFilter(f); + emit filterChanged(); + QDialog::accept(); +} + +void FilterEditDialog::slotAdd() +{ + KLineEditDlg dlg(i18n("Enter filter name:"), "New Filter", this); + dlg.setCaption(i18n("Add Filter")); + if (dlg.exec()) { + if ( dlg.text().length() > 0 ) { + mFilters->append(new CalFilter(dlg.text())); + updateFilterList(); + int num = mSelectionCombo->count() -1 ; + mSelectionCombo->setCurrentItem( num ); + readFilter(mFilters->at( num ) ); + } + } +} + +void FilterEditDialog::slotRemove() +{ + int currentItem = mSelectionCombo->currentItem(); + if ( currentItem < 0 ) return; + + // We need at least a default filter object. + if ( mFilters->count() <= 1 ) return; + + int result = KMessageBox::questionYesNo( this, + i18n("This item will be\npermanently deleted.") ); + + if ( result != KMessageBox::Yes ) { + return; + } + + mFilters->remove( currentItem ); + updateFilterList(); + emit filterChanged(); +} + +void FilterEditDialog::editCategorySelection() +{ + KPIM::CategorySelectDialog *dlg = new KPIM::CategorySelectDialog( + KOPrefs::instance(), this, "filterCatSelect", true ); + dlg->setSelected(mCategories); + + connect(dlg,SIGNAL(categoriesSelected(const QStringList &)), + SLOT(updateCategorySelection(const QStringList &))); + + dlg->exec(); +} + +void FilterEditDialog::updateCategorySelection(const QStringList &categories) +{ + mCategories = categories; + + mEditor->mCatList->clear(); + mEditor->mCatList->insertStringList(mCategories); +} + +void FilterEditDialog::filterSelected() +{ + CalFilter *f = mFilters->at(mSelectionCombo->currentItem()); + if (f) readFilter(f); +} + +void FilterEditDialog::readFilter(CalFilter *filter) +{ + int c = filter->criteria(); + + mEditor->mCompletedCheck->setChecked(c & CalFilter::HideCompleted); + mEditor->mRecurringCheck->setChecked(c & CalFilter::HideRecurring); + mEditor->mPublicCheck->setChecked(c & CalFilter::ShowPublic); + mEditor->mPrivateCheck->setChecked(c & CalFilter::ShowPrivate); + mEditor->mConfidentialCheck->setChecked(c & CalFilter::ShowConfidential); + + if (c & CalFilter::ShowCategories) { + mEditor->mCatShowCheck->setChecked(true); + } else { + mEditor->mCatHideCheck->setChecked(true); + } + + mEditor->mCatList->clear(); + mEditor->mCatList->insertStringList(filter->categoryList()); + mCategories = filter->categoryList(); + + setCaption( i18n("Filter position: ") + QString::number ( mSelectionCombo->currentItem()+1 )); +} + +void FilterEditDialog::writeFilter(CalFilter *filter) +{ + int c = 0; + + if (mEditor->mCompletedCheck->isChecked()) c |= CalFilter::HideCompleted; + if (mEditor->mRecurringCheck->isChecked()) c |= CalFilter::HideRecurring; + if (mEditor->mCatShowCheck->isChecked()) c |= CalFilter::ShowCategories; + if (mEditor->mPublicCheck->isChecked()) c |= CalFilter::ShowPublic; + if (mEditor->mPrivateCheck->isChecked()) c |= CalFilter::ShowPrivate; + if (mEditor->mConfidentialCheck->isChecked()) c |= CalFilter::ShowConfidential; + + filter->setCriteria(c); + + QStringList categoryList; + for(uint i=0;i<mEditor->mCatList->count();++i) { + categoryList.append(mEditor->mCatList->text(i)); + } + filter->setCategoryList(categoryList); +} diff --git a/korganizer/filtereditdialog.h b/korganizer/filtereditdialog.h new file mode 100644 index 0000000..42aa3da --- a/dev/null +++ b/korganizer/filtereditdialog.h @@ -0,0 +1,86 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001, 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _FILTEREDITDIALOG_H +#define _FILTEREDITDIALOG_H + +#include <qptrlist.h> + +#include <kdialogbase.h> + +#include <libkcal/calfilter.h> + +class QComboBox; +class ComboFilterBox; +class QPushButton; +class FilterEdit_base; + +using namespace KCal; + +/** + This is the class to add/edit a calendar filter. + + @short Creates a dialog box to create/edit a calendar filter + @author Cornelius Schumacher +*/ +class FilterEditDialog : public KDialogBase +{ + Q_OBJECT + public: + FilterEditDialog(QPtrList<CalFilter> *,QWidget *parent=0, const char *name=0); + virtual ~FilterEditDialog(); + + public slots: + void updateFilterList(); + + signals: + void filterChanged(); + + protected slots: + void slotDefault(); + void slotApply(); + void slotOk(); + void accept(); + + void slotAdd(); + void slotUp(); + void slotRemove(); + + void filterSelected(); + void editCategorySelection(); + void updateCategorySelection(const QStringList &categories); + + protected: + void readFilter(CalFilter *); + void writeFilter(CalFilter *); + + private: + QPtrList<CalFilter> *mFilters; + + ComboFilterBox *mSelectionCombo; + QPushButton *mRemoveButton; + FilterEdit_base *mEditor; + + QStringList mCategories; +}; + +#endif diff --git a/korganizer/filtereditdialog.moc b/korganizer/filtereditdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/filtereditdialog.moc diff --git a/korganizer/incomingdialog.cpp b/korganizer/incomingdialog.cpp new file mode 100644 index 0000000..490d21e --- a/dev/null +++ b/korganizer/incomingdialog.cpp @@ -0,0 +1,527 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <qlistview.h> +#include <qfile.h> +#include <qdir.h> +#include <qmap.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> + +#include <libkcal/incidence.h> +#include <libkcal/event.h> +#include <libkcal/calendar.h> +#include <libkcal/freebusy.h> +#include <libkcal/attendee.h> +#include <libkcal/calendarresources.h> +#include <libkcal/resourcecalendar.h> +#include <kresources/resourceselectdialog.h> + +#ifndef KORG_NOMAIL +#include "mailscheduler.h" +#else +#include <libkcal/dummyscheduler.h> +#endif + + +#include "incomingdialog.h" +#include "koeventviewerdialog.h" +#include "kocounterdialog.h" +#include "koprefs.h" + +#ifndef KORG_NOKABC +#include <kabc/stdaddressbook.h> +#define size count +#endif + + +ScheduleItemIn::ScheduleItemIn(QListView *parent,IncidenceBase *ev, + Scheduler::Method method,ScheduleMessage::Status status) + : QListViewItem(parent) +{ + mIncidence = ev; + mMethod = method; + mStatus = status; + setText(6,Scheduler::translatedMethodName(mMethod)+" "); + setText(7,ScheduleMessage::statusName(status)); +} + + +/* Visitor */ +ScheduleItemVisitor::ScheduleItemVisitor(ScheduleItemIn *item) +{ + mItem = item; +} + +ScheduleItemVisitor::~ScheduleItemVisitor() +{ +} + +bool ScheduleItemVisitor::visit(Event *e) +{ + mItem->setText(0,e->summary()); + mItem->setText(1,e->dtStartDateStr()); + if (e->doesFloat()) { + mItem->setText(2,i18n("no time ")); + mItem->setText(4,i18n("no time ")); + } + else { + mItem->setText(2,e->dtStartTimeStr()); + mItem->setText(4,e->dtEndTimeStr()); + } + if (e->hasEndDate()) { + mItem->setText(3,e->dtEndDateStr()); + } + else { + mItem->setText(3,""); + } + mItem->setText(5,e->organizer()+" "); + + return true; +} + +bool ScheduleItemVisitor::visit(Todo *e) +{ + mItem->setText(0,e->summary()); + if (e->hasStartDate()) { + mItem->setText(1,e->dtStartDateStr()); + if (!e->doesFloat()) { + mItem->setText(2,e->dtStartTimeStr()); + } + } + if (e->hasDueDate()) { + mItem->setText(1,e->dtDueDateStr()); + if (!e->doesFloat()) { + mItem->setText(2,e->dtDueTimeStr()); + } + } + mItem->setText(5,e->organizer()+" "); + + return true; +} + +bool ScheduleItemVisitor::visit(Journal *) +{ + return false; +} + + +/* + * Constructs a IncomingDialog which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +IncomingDialog::IncomingDialog(Calendar *calendar,OutgoingDialog *outgoing, + QWidget* parent,const char* name,bool modal,WFlags fl) : + IncomingDialog_base(parent,name,modal,fl) +{ + mCalendar = calendar; + mOutgoing = outgoing; +#ifndef KORG_NOMAIL + mScheduler = new MailScheduler(mCalendar); +#else + mScheduler = new DummyScheduler(mCalendar); +#endif + mMessageListView->setColumnAlignment(1,AlignHCenter); + mMessageListView->setColumnAlignment(2,AlignHCenter); + mMessageListView->setColumnAlignment(3,AlignHCenter); + mMessageListView->setColumnAlignment(4,AlignHCenter); + QObject::connect(mMessageListView,SIGNAL(doubleClicked(QListViewItem *)), + this,SLOT(showEvent(QListViewItem *))); + retrieve(); +} + +/* + * Destroys the object and frees any allocated resources + */ +IncomingDialog::~IncomingDialog() +{ + // no need to delete child widgets, Qt does it all for us +} + +void IncomingDialog::setOutgoingDialog(OutgoingDialog *outgoing) +{ + mOutgoing = outgoing; +} + +void IncomingDialog::retrieve() +{ + QPtrList <ScheduleMessage> messages = mScheduler->retrieveTransactions(); + + ScheduleMessage *message; + for(message = messages.first();message;message = messages.next()) { + IncidenceBase *inc = message->event(); + Scheduler::Method method = (Scheduler::Method)message->method(); + ScheduleMessage::Status status = message->status(); + + ScheduleItemIn *item = new ScheduleItemIn(mMessageListView,inc,method,status); + if(inc->type()!="FreeBusy") { + Incidence *incidence = static_cast<Incidence *>(inc); + ScheduleItemVisitor v(item); + if (!incidence->accept(v)) delete item; + } else { + FreeBusy *fb = static_cast<FreeBusy *>(item->event()); + item->setText(0, "FreeBusy"); + item->setText(1, KGlobal::locale()->formatDate( fb->dtStart().date() ) ); + item->setText(2, KGlobal::locale()->formatTime( fb->dtStart().time() ) ); + item->setText(3, KGlobal::locale()->formatDate( fb->dtEnd().date() ) ); + item->setText(4, KGlobal::locale()->formatTime( fb->dtEnd().time() ) ); + item->setText(5, fb->organizer()); + } + automaticAction(item); + } + emit numMessagesChanged(mMessageListView->childCount()); +} + +void IncomingDialog::acceptAllMessages() +{ + bool success = false; + + ScheduleItemIn *item = (ScheduleItemIn *)mMessageListView->firstChild(); + while(item) { + ScheduleItemIn *nextitem = (ScheduleItemIn *)(item->nextSibling()); + if (acceptMessage(item)) success = true; + item = nextitem; + } + + if (success) emit calendarUpdated(); +} + +void IncomingDialog::acceptMessage() +{ + ScheduleItemIn *item = (ScheduleItemIn *)mMessageListView->selectedItem(); + if (item) { + if (acceptMessage(item)) emit calendarUpdated(); + } +} + +bool IncomingDialog::acceptMessage(ScheduleItemIn *item) +{ + switch (item->method()) { + case Scheduler::Refresh: + return incomeRefresh(item); + break; + case Scheduler::Counter: + return incomeCounter(item); + break; + case Scheduler::Declinecounter: + return incomeDeclineCounter(item); + break; + case Scheduler::Add: + return incomeAdd(item); + break; + case Scheduler::Request: + return incomeRequest(item); + break; + default: + return incomeDefault(item); + } + return false; +} + +void IncomingDialog::rejectMessage() +{ + ScheduleItemIn *item = (ScheduleItemIn *)mMessageListView->selectedItem(); + if (item) { + mScheduler->deleteTransaction(item->event()); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + } +} + +void IncomingDialog::showEvent(QListViewItem *item) +{ + IncidenceBase *incidence = ((ScheduleItemIn *)item)->event(); + if( incidence && incidence->type() == "Event" ) { + Event *event = static_cast<Event *>(incidence); + KOEventViewerDialog *eventViewer = new KOEventViewerDialog(this); + eventViewer->setEvent(event); + eventViewer->show(); + } +} + +bool IncomingDialog::incomeRefresh(ScheduleItemIn *item) +{ + Event *ev = mCalendar->event(item->event()->uid()); + if (ev) { + //user interaction before?? + Attendee *att; + QPtrList<Attendee> attlist = ev->attendees(); + for (att=attlist.first(); att; att=attlist.next()) { + Event *event = new Event(*ev); + mOutgoing->addMessage(event,Scheduler::Request,att->email()); + delete(event); + } + mScheduler->deleteTransaction(item->event()); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return true; + } + mScheduler->deleteTransaction(item->event()); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return false; +} + +bool IncomingDialog::incomeCounter(ScheduleItemIn *item) +{ + IncidenceBase *incidence = ((ScheduleItemIn *)item)->event(); + // currently only events supportet - attetion at insertion below! + if ( incidence->type() != "Event" ) return false; + + Event *counterEvent = static_cast<Event *>( incidence ); + + Event *even = mCalendar->event(counterEvent->uid()); + + KOCounterDialog *eventViewer = new KOCounterDialog(this); + eventViewer->addText(i18n("counter proposal event","<b>Counter-event:</b><p>")); + eventViewer->addEvent(counterEvent); + eventViewer->addText("<hr>"); + eventViewer->addText(i18n("<b>Original event:</b><p>")); + if (even) eventViewer->addEvent(even); + else eventViewer->addText(i18n("A corresponding event is missing in your calendar!")); + eventViewer->addText("<hr>"); + eventViewer->addText(i18n("If this counter-event is a good proposal for your event, press 'Accept'. All Attendees will then get the new version of this event")); + eventViewer->show(); + + eventViewer->exec(); + if (eventViewer->result()) { + kdDebug() << "IncomingDialog::Counter:Accept" << endl; + int revision = 0; + if (even) { + revision = even->revision(); + mCalendar->deleteEvent(even); + } + mCalendar->addIncidence(counterEvent); + + even = mCalendar->event(item->event()->uid()); + if (even) { + if (revision < even->revision()) + even->setRevision(even->revision()+1); + else + even->setRevision(revision+1); + Event *ev = new Event(*even); + mOutgoing->addMessage(ev,Scheduler::Request); + delete(ev); + } + mScheduler->deleteTransaction(item->event()); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return true; + } else { + kdDebug() << "IncomingDialog::Counter:Decline" << endl; + //the counter-sender's email is missing... + //now every attendee gets an declinecounter :-( + mOutgoing->addMessage(counterEvent,Scheduler::Declinecounter); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + mScheduler->deleteTransaction(item->event()); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return true; + } + //mScheduler->deleteTransaction(item->event()); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return false; +} + +bool IncomingDialog::incomeDeclineCounter(ScheduleItemIn *item) +{ + Event *even = mCalendar->event(item->event()->uid()); + if (even) { + mOutgoing->addMessage(even,Scheduler::Refresh); + mScheduler->deleteTransaction(item->event()); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return true; + } + mScheduler->deleteTransaction(item->event()); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return false; +} + +bool IncomingDialog::incomeAdd(ScheduleItemIn *item) +{ + IncidenceBase *incidence = ((ScheduleItemIn *)item)->event(); + if (incidence->type() == "Event" ) { + Event *refr = static_cast<Event *>( incidence ); + mOutgoing->addMessage(refr,Scheduler::Refresh); + mScheduler->deleteTransaction( incidence ); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return true; + } + else { + kdDebug() << "IncomingDialog::incomeAdd - only Events are supportet yet" << endl; + mScheduler->deleteTransaction( incidence ); + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return false; + } +} + +bool IncomingDialog::incomeDefault(ScheduleItemIn *item) +{ + if (mScheduler->acceptTransaction(item->event(),item->method(),item->status())) { + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + return true; + } + else { + KMessageBox::error(this,i18n("Unable to accept the IMIP-message. It may be a problem with the email addresses.")); + kdDebug() << "IncomingDialog::acceptMessage(): Error!" << endl; + return false; + } + return false; +} + +bool IncomingDialog::incomeRequest(ScheduleItemIn *item) +{ + if (item->event()->type()=="FreeBusy") { + //handel freebusy request + IncidenceBase *inc = item->event(); + QDateTime start = inc->dtStart(); + QDateTime end = start.addDays(inc->duration()/86400); + + FreeBusy *freebusy = new FreeBusy(mCalendar, start, end); + freebusy->setOrganizer(inc->organizer()); + Attendee *att = new Attendee(KOPrefs::instance()->fullName(), + KOPrefs::instance()->email()); + freebusy->addAttendee(att); + + kdDebug() << "calendarview: schedule_publish_freebusy: startDate: " + << KGlobal::locale()->formatDateTime( start ) << " End Date: " + << KGlobal::locale()->formatDateTime( end ) << endl; + + if (mOutgoing->addMessage(freebusy,Scheduler::Reply)) { + delete item; + emit numMessagesChanged(mMessageListView->childCount()); + delete(freebusy); + return true; + } + return false; + } else { + return incomeDefault(item); + } + return false; +} + +bool IncomingDialog::automaticAction(ScheduleItemIn *item) +{ + bool autoAction = false; + IncidenceBase *inc = item->event(); + Scheduler::Method method = item->method(); + + if( inc->type()=="FreeBusy" ) { + if ( method==Scheduler::Request ) { + if ( KOPrefs::instance()->mIMIPAutoFreeBusy==KOPrefs::addressbookAuto ) { + // reply freebusy information + if ( checkOrganizerInAddressbook(inc->organizer()) ) { + incomeRequest(item); + } + } else return false; + } else { + + if ( method==Scheduler::Reply ) { + if ( KOPrefs::instance()->mIMIPAutoFreeBusy==KOPrefs::addressbookAuto ) { + // insert freebusy information + //if ( checkAttendeesInAddressbook(inc) ) + + } else return false; + } else { + if ( method==Scheduler::Publish) { + if ( KOPrefs::instance()->mIMIPAutoFreeBusy==KOPrefs::addressbookAuto ) { + // insert freebusy information + //if ( checkOrganizerInAddressbook(inc->organizer()) ) + + } + } else return false; + } + } + } + + if ( inc->type()=="Event" ) { + if ( method==Scheduler::Request || method==Scheduler::Publish ) { + if ( KOPrefs::instance()->mIMIPAutoInsertRequest==KOPrefs::addressbookAuto ) { + // insert event + if ( checkOrganizerInAddressbook(inc->organizer()) ) + autoAction = acceptMessage(item); + } else return false; + } else { + + if ( method==Scheduler::Reply ) { + if ( KOPrefs::instance()->mIMIPAutoInsertReply==KOPrefs::addressbookAuto ) { + // update event information + if ( checkAttendeesInAddressbook(inc) ) + autoAction = acceptMessage(item); + } else return false; + } else { + + if ( method==Scheduler::Refresh ) { + if ( KOPrefs::instance()->mIMIPAutoRefresh==KOPrefs::addressbookAuto ) { + // send refresh-information + if ( checkAttendeesInAddressbook(inc) ) + autoAction = acceptMessage(item); + else return false; + } else return false; + } else return false; + } + } + } + return autoAction; +} + +bool IncomingDialog::checkOrganizerInAddressbook(QString organizer) +{ + bool inBook = false; +#ifndef KORG_NOKABC + KABC::AddressBook *add_book = KABC::StdAddressBook::self(); + KABC::Addressee::List addressList; + addressList = add_book->findByEmail(organizer); + if ( addressList.size()>0 ) inBook = true; +#endif + return inBook; +} + +bool IncomingDialog::checkAttendeesInAddressbook(IncidenceBase *inc) +{ + bool inBook = false; +#ifndef KORG_NOKABC + KABC::AddressBook *add_book = KABC::StdAddressBook::self(); + KABC::Addressee::List addressList; + QPtrList <Attendee> attendees; + Attendee *att; + attendees = inc->attendees(); + for (att=attendees.first();att;att=attendees.next()) { + addressList = add_book->findByEmail(att->email()); + if (addressList.size()>0 ) inBook = true; + } +#endif + return inBook; +} + +#include "incomingdialog.moc" diff --git a/korganizer/incomingdialog.h b/korganizer/incomingdialog.h new file mode 100644 index 0000000..413ce6a --- a/dev/null +++ b/korganizer/incomingdialog.h @@ -0,0 +1,110 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef INCOMINGDIALOG_H +#define INCOMINGDIALOG_H + +#include <qlistview.h> + +#include <libkcal/calendar.h> +#include <libkcal/scheduler.h> + +#include "incomingdialog_base.h" +#include "outgoingdialog.h" + +using namespace KCal; + +class ScheduleItemIn : public QListViewItem +{ + public: + ScheduleItemIn(QListView *parent,IncidenceBase *ev,Scheduler::Method method, + ScheduleMessage::Status status); + virtual ~ScheduleItemIn() {} + + IncidenceBase *event() { return mIncidence; } + Scheduler::Method method() { return mMethod; } + ScheduleMessage::Status status() { return mStatus; } + + private: + IncidenceBase *mIncidence; + Scheduler::Method mMethod; + ScheduleMessage::Status mStatus; +}; + + +/** + This class provides the initialisation of a ScheduleItemIn for calendar + components using the Incidence::Visitor. +*/ +class ScheduleItemVisitor : public Incidence::Visitor +{ + public: + ScheduleItemVisitor(ScheduleItemIn *); + ~ScheduleItemVisitor(); + + bool visit(Event *); + bool visit(Todo *); + bool visit(Journal *); + + private: + ScheduleItemIn *mItem; +}; + + + +class IncomingDialog : public IncomingDialog_base +{ + Q_OBJECT + public: + IncomingDialog(Calendar *calendar,OutgoingDialog *outgoing, + QWidget* parent=0,const char* name=0,bool modal=false,WFlags fl=0); + ~IncomingDialog(); + + void setOutgoingDialog(OutgoingDialog *outgoing); + + signals: + void calendarUpdated(); + void numMessagesChanged(int); + public slots: + void retrieve(); + + protected slots: + void acceptAllMessages(); + void acceptMessage(); + void rejectMessage(); + void showEvent(QListViewItem *); + + protected: + bool acceptMessage(ScheduleItemIn *item); + bool incomeRefresh(ScheduleItemIn *item); + bool incomeCounter(ScheduleItemIn *item); + bool incomeDeclineCounter(ScheduleItemIn *item); + bool incomeAdd(ScheduleItemIn *item); + bool incomeRequest(ScheduleItemIn *item); + bool incomeDefault(ScheduleItemIn *item); + bool automaticAction(ScheduleItemIn *item); + + private: + bool checkAttendeesInAddressbook(IncidenceBase *inc); + bool checkOrganizerInAddressbook(QString organizer); + Calendar *mCalendar; + Scheduler *mScheduler; + OutgoingDialog *mOutgoing; +}; + +#endif // INCOMINGDIALOG_H diff --git a/korganizer/incomingdialog.moc b/korganizer/incomingdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/incomingdialog.moc diff --git a/korganizer/incomingdialog_base.cpp b/korganizer/incomingdialog_base.cpp new file mode 100644 index 0000000..91740a4 --- a/dev/null +++ b/korganizer/incomingdialog_base.cpp @@ -0,0 +1,137 @@ +#include <klocale.h> +/**************************************************************************** +** Form implementation generated from reading ui file '/build/kde/cvs/korge/kdepim/korganizer/incomingdialog_base.ui' +** +** Created: Sat Mar 29 22:31:27 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#include "incomingdialog_base.h" + +#include <qvariant.h> +#include <qheader.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a IncomingDialog_base as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +IncomingDialog_base::IncomingDialog_base( QWidget* parent, const char* name, bool modal, WFlags fl ) + : QDialog( parent, name, modal, fl ) + +{ + if ( !name ) + setName( "IncomingDialog_base" ); + IncomingDialog_baseLayout = new QGridLayout( this, 1, 1, 11, 6, "IncomingDialog_baseLayout"); + + PushButton4 = new QPushButton( this, "PushButton4" ); + + IncomingDialog_baseLayout->addWidget( PushButton4, 0, 1 ); + + PushButton7 = new QPushButton( this, "PushButton7" ); + PushButton7->setDefault( TRUE ); + + IncomingDialog_baseLayout->addWidget( PushButton7, 5, 1 ); + + mMessageListView = new QListView( this, "mMessageListView" ); + mMessageListView->addColumn( tr2i18n( "Summary" ) ); + mMessageListView->addColumn( tr2i18n( "Start Date" ) ); + mMessageListView->addColumn( tr2i18n( "Start Time" ) ); + mMessageListView->addColumn( tr2i18n( "End Date" ) ); + mMessageListView->addColumn( tr2i18n( "End Time" ) ); + mMessageListView->addColumn( tr2i18n( "Organizer" ) ); + mMessageListView->addColumn( tr2i18n( "Method" ) ); + mMessageListView->addColumn( tr2i18n( "Status" ) ); + mMessageListView->setAllColumnsShowFocus( FALSE ); + + IncomingDialog_baseLayout->addMultiCellWidget( mMessageListView, 0, 5, 0, 0 ); + + PushButton7_2 = new QPushButton( this, "PushButton7_2" ); + + IncomingDialog_baseLayout->addWidget( PushButton7_2, 3, 1 ); + + PushButton8 = new QPushButton( this, "PushButton8" ); + + IncomingDialog_baseLayout->addWidget( PushButton8, 1, 1 ); + + PushButton9 = new QPushButton( this, "PushButton9" ); + + IncomingDialog_baseLayout->addWidget( PushButton9, 2, 1 ); + QSpacerItem* spacer = new QSpacerItem( 20, 70, QSizePolicy::Minimum, QSizePolicy::Expanding ); + IncomingDialog_baseLayout->addItem( spacer, 4, 1 ); + languageChange(); + resize( QSize(525, 262).expandedTo(minimumSizeHint()) ); + + // signals and slots connections + connect( PushButton7, SIGNAL( clicked() ), this, SLOT( accept() ) ); + connect( PushButton4, SIGNAL( clicked() ), this, SLOT( retrieve() ) ); + connect( PushButton7_2, SIGNAL( clicked() ), this, SLOT( acceptAllMessages() ) ); + + // tab order + setTabOrder( PushButton7, PushButton4 ); + setTabOrder( PushButton4, PushButton7_2 ); + setTabOrder( PushButton7_2, mMessageListView ); + setTabOrder( mMessageListView, PushButton8 ); + setTabOrder( PushButton8, PushButton9 ); +} + +/* + * Destroys the object and frees any allocated resources + */ +IncomingDialog_base::~IncomingDialog_base() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void IncomingDialog_base::languageChange() +{ + setCaption( tr2i18n( "Scheduler - Incoming Messages" ) ); + PushButton4->setText( tr2i18n( "Retrieve &Messages" ) ); + PushButton7->setText( tr2i18n( "&Close" ) ); + mMessageListView->header()->setLabel( 0, tr2i18n( "Summary" ) ); + mMessageListView->header()->setLabel( 1, tr2i18n( "Start Date" ) ); + mMessageListView->header()->setLabel( 2, tr2i18n( "Start Time" ) ); + mMessageListView->header()->setLabel( 3, tr2i18n( "End Date" ) ); + mMessageListView->header()->setLabel( 4, tr2i18n( "End Time" ) ); + mMessageListView->header()->setLabel( 5, tr2i18n( "Organizer" ) ); + mMessageListView->header()->setLabel( 6, tr2i18n( "Method" ) ); + mMessageListView->header()->setLabel( 7, tr2i18n( "Status" ) ); + PushButton7_2->setText( tr2i18n( "Accept A&ll" ) ); + PushButton8->setText( tr2i18n( "&Accept" ) ); + PushButton9->setText( tr2i18n( "&Reject" ) ); +} + +void IncomingDialog_base::acceptAllMessages() +{ + qWarning( "IncomingDialog_base::acceptAllMessages(): Not implemented yet" ); +} + +void IncomingDialog_base::acceptMessage() +{ + qWarning( "IncomingDialog_base::acceptMessage(): Not implemented yet" ); +} + +void IncomingDialog_base::rejectMessage() +{ + qWarning( "IncomingDialog_base::rejectMessage(): Not implemented yet" ); +} + +void IncomingDialog_base::retrieve() +{ + qWarning( "IncomingDialog_base::retrieve(): Not implemented yet" ); +} + +#include "incomingdialog_base.moc" diff --git a/korganizer/incomingdialog_base.h b/korganizer/incomingdialog_base.h new file mode 100644 index 0000000..7732384 --- a/dev/null +++ b/korganizer/incomingdialog_base.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** Form interface generated from reading ui file '/build/kde/cvs/korge/kdepim/korganizer/incomingdialog_base.ui' +** +** Created: Sat Mar 29 22:24:26 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#ifndef INCOMINGDIALOG_BASE_H +#define INCOMINGDIALOG_BASE_H + +#include <qvariant.h> +#include <qdialog.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QListView; +class QListViewItem; +class QPushButton; + +class IncomingDialog_base : public QDialog +{ + Q_OBJECT + +public: + IncomingDialog_base( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~IncomingDialog_base(); + + QPushButton* PushButton4; + QPushButton* PushButton7; + QListView* mMessageListView; + QPushButton* PushButton7_2; + QPushButton* PushButton8; + QPushButton* PushButton9; + +protected: + QGridLayout* IncomingDialog_baseLayout; + +protected slots: + virtual void languageChange(); + + virtual void acceptAllMessages(); + virtual void acceptMessage(); + virtual void rejectMessage(); + virtual void retrieve(); + +}; + +#endif // INCOMINGDIALOG_BASE_H diff --git a/korganizer/incomingdialog_base.moc b/korganizer/incomingdialog_base.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/incomingdialog_base.moc diff --git a/korganizer/interfaces/korganizer/baseview.h b/korganizer/interfaces/korganizer/baseview.h new file mode 100644 index 0000000..09f8ba3 --- a/dev/null +++ b/korganizer/interfaces/korganizer/baseview.h @@ -0,0 +1,192 @@ +/* + This file is part of the KOrganizer interfaces. + Copyright (c) 1999 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KORG_BASEVIEW_H +#define KORG_BASEVIEW_H +// $Id$ +// KOBaseView is the abstract base class of all calendar views. + +#include <qwidget.h> +#include <qptrlist.h> +#include <qvaluelist.h> + +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> + +#include <libkcal/event.h> +#include <libkcal/calendar.h> + +using namespace KCal; + +class CalPrinter; + +namespace KOrg { + +class CalPrinterBase +{ + public: + enum PrintType { Day, Week, Month, Todolist }; +}; + + +/** + This class provides an interface for all views being displayed within the main + calendar view. It has functions to update the view, to specify date range and + other display parameter and to return selected objects. An important class, + which inherits KOBaseView is KOEventView, which provides the interface for all + views of event data like the agenda or the month view. + + @short Base class for calendar views + @author Preston Brown, Cornelius Schumacher + @see KOTodoView, KOEventView, KOListView, KOAgendaView, KOMonthView +*/ +class BaseView : public QWidget +{ + Q_OBJECT + public: + /** + Constructs a view. + + @param cal Pointer to the calendar object from which events + will be retrieved for display. + @param parent parent widget. + @param name name of this widget. + */ + BaseView(Calendar *cal, QWidget *parent = 0, const char *name = 0) : + QWidget(parent, name), mCalendar(cal) {} + + /** + Destructor. Views will do view-specific cleanups here. + */ + virtual ~BaseView() {} + + /** + Return calendar object of this view. + */ + Calendar *calendar() { return mCalendar; } + + /** + @return a list of selected events. Most views can probably only + select a single event at a time, but some may be able to select + more than one. + */ + virtual QPtrList<Incidence> selectedIncidences() = 0; + + /** + @return a list of the dates of selected events. Most views can probably only + select a single event at a time, but some may be able to select + more than one. + */ + virtual DateList selectedDates() = 0; + + /** + Generate a print preview of this event view. + + @param calPrinter Calendar printer object used for printing + @param fd from date + @param td to date + */ +/* + The date parameters should be determined by the view itself and not given as + parameters. At the moment I just move the code from the topwidget to the + individual views. +*/ + virtual void printPreview(CalPrinter *, + const QDate &, const QDate &) + { + KMessageBox::sorry(this, i18n("Unfortunately, we don't handle printing for\n" + "that view yet.\n")); + } + + /** + Print this view. + + @param calPrinter Calendar printer object used for printing + */ + virtual void print(CalPrinter *) + { + KMessageBox::sorry(this, i18n("Unfortunately, we don't handle printing for\n" + "that view yet.\n")); + } + + /** + Return number of currently shown dates. A return value of 0 means no idea. + */ + virtual int currentDateCount() = 0; + + /** Return if this view is a view for displaying events. */ + virtual bool isEventView() { return false; } + + public slots: + /** + Show incidences for the given date range. The date range actually shown may be + different from the requested range, depending on the particular requirements + of the view. + + @param start Start of date range. + @param end End of date range. + */ + virtual void showDates( const QDate &start, const QDate &end ) = 0; + + /** + Show given events. Depending on the actual view it might not be possible to + show all given events. + + @param eventList a list of events to show. + */ + virtual void showEvents(QPtrList<Event> eventList) = 0; + + /** + Updates the current display to reflect changes that may have happened + in the calendar since the last display refresh. + */ + virtual void updateView() = 0; + + /** + Write all unsaved data back to calendar store. + */ + virtual void flushView() {} + + /** + Updates the current display to reflect the changes to one particular event. + */ + virtual void changeEventDisplay(Event *, int) = 0; + + /** + Re-reads the KOrganizer configuration and picks up relevant + changes which are applicable to the view. + */ + virtual void updateConfig() {} + + /** + Clear selection. The incidenceSelected signal is not emitted. + */ + virtual void clearSelection() {} + + signals: + void incidenceSelected( Incidence * ); + + protected: + Calendar *mCalendar; +}; + +} +#endif diff --git a/korganizer/interfaces/korganizer/calendarviewbase.h b/korganizer/interfaces/korganizer/calendarviewbase.h new file mode 100644 index 0000000..3c715b1 --- a/dev/null +++ b/korganizer/interfaces/korganizer/calendarviewbase.h @@ -0,0 +1,65 @@ +/* + This file is part of the KOrganizer interfaces. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KORG_CALENDARVIEWBASE_H +#define KORG_CALENDARVIEWBASE_H +// $Id$ + +#include <qwidget.h> +#include <qlayout.h> + + +#include <libkcal/calendar.h> + +#include <korganizer/baseview.h> + +namespace KOrg { + +/** + @short interface for main calendar view widget + @author Cornelius Schumacher +*/ +class CalendarViewBase : public QWidget +{ + Q_OBJECT + public: + CalendarViewBase(QWidget *parent, const char *name) : + QWidget(parent,name) {new QVBoxLayout(this);} + virtual ~CalendarViewBase() {}; + + virtual KCal::Calendar *calendar() = 0; + + virtual QDate startDate() = 0; + virtual QDate endDate() = 0; + + virtual Incidence *currentSelection() = 0; + + virtual void addView(KOrg::BaseView *) = 0; + + /** changes the view to be the currently selected view */ + virtual void showView(KOrg::BaseView *) = 0; + + public slots: + virtual void updateView() = 0; + +}; + +} + +#endif diff --git a/korganizer/journalentry.cpp b/korganizer/journalentry.cpp new file mode 100644 index 0000000..d1d7946 --- a/dev/null +++ b/korganizer/journalentry.cpp @@ -0,0 +1,170 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +// +// Journal Entry + +#include <qlabel.h> +#include <qlayout.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <ktextedit.h> +#include "koprefs.h" + +#include <libkcal/journal.h> +#include <libkcal/calendarresources.h> +#include <libkcal/resourcecalendar.h> +#include <kresources/resourceselectdialog.h> + +#include "journalentry.h" +#include "journalentry.moc" +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#endif +JournalEntry::JournalEntry(Calendar *calendar,QWidget *parent) : + QFrame(parent) +{ + mCalendar = calendar; + mJournal = 0; + mDirty = false; + + mTitleLabel = new QLabel(i18n("Title"),this); + mTitleLabel->setMargin(2); + mTitleLabel->setAlignment(AlignCenter); + + mEditor = new KTextEdit(this); + connect(mEditor,SIGNAL(textChanged()),SLOT(setDirty())); +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( mEditor, QPEApplication::RightOnHold ); +#endif + mEditor->setWordWrap( KTextEdit::WidgetWidth ); + QBoxLayout *topLayout = new QVBoxLayout(this); + topLayout->addWidget(mTitleLabel); + topLayout->addWidget(mEditor); + mEditor->installEventFilter(this); +} + +JournalEntry::~JournalEntry() +{ +} + +void JournalEntry::setDate(const QDate &date) +{ + writeJournal(); + + mTitleLabel->setText(KGlobal::locale()->formatDate(date)); + + + mDate = date; +} + +void JournalEntry::setJournal(Journal *journal) +{ + writeJournal(); + + mJournal = journal; + + mEditor->setText(mJournal->description()); + + mDirty = false; +} + +Journal *JournalEntry::journal() const +{ + return mJournal; +} + +void JournalEntry::setDirty() +{ + mDirty = true; + +// kdDebug() << "JournalEntry::setDirty()" << endl; +} + +void JournalEntry::clear() +{ + mJournal = 0; + mEditor->setText(""); +} + +bool JournalEntry::eventFilter( QObject *o, QEvent *e ) +{ +// kdDebug() << "JournalEntry::event received " << e->type() << endl; + + if ( e->type() == QEvent::FocusOut ) { + writeJournal(); + } + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent * k = (QKeyEvent *) e; + if ( k->state() == Qt::ControlButton ) { + k->ignore(); + //return true; + } + } + + return QFrame::eventFilter( o, e ); // standard event processing +} + +void JournalEntry::writeJournal() +{ +// kdDebug() << "JournalEntry::writeJournal()" << endl; + if (!mDirty) return; + + if (mEditor->text().isEmpty()) { + if ( mJournal ) { + mDirty = false; + bool conf = KOPrefs::instance()->mConfirm; + KOPrefs::instance()->mConfirm = false; + emit deleteJournal(mJournal); + KOPrefs::instance()->mConfirm = conf; + mJournal = 0; + } + return; + } + +// kdDebug() << "JournalEntry::writeJournal()..." << endl; + + if (!mJournal) { + mJournal = new Journal; + mJournal->setDtStart(QDateTime(mDate,QTime(0,0,0))); + mCalendar->addJournal(mJournal); + } + + mJournal->setDescription(mEditor->text()); + + mDirty = false; +} + +void JournalEntry::flushEntry() +{ + if (!mDirty) return; + + writeJournal(); +} +void JournalEntry::keyPressEvent ( QKeyEvent * e ) +{ + e->ignore(); + +} diff --git a/korganizer/journalentry.h b/korganizer/journalentry.h new file mode 100644 index 0000000..1f784f4 --- a/dev/null +++ b/korganizer/journalentry.h @@ -0,0 +1,73 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef JOURNALENTRY_H +#define JOURNALENTRY_H +// +// Widget showing one Journal entry + +#include <qframe.h> + +#include <libkcal/calendar.h> + +class QLabel; +class KTextEdit; + +using namespace KCal; + +class JournalEntry : public QFrame { + Q_OBJECT + public: + JournalEntry(Calendar *,QWidget *parent); + virtual ~JournalEntry(); + + void setJournal(Journal *); + Journal *journal() const; + + void setDate(const QDate &); + + void clear(); + + void flushEntry(); + + protected slots: + void setDirty(); + signals: + void deleteJournal(Journal *); + + protected: + bool eventFilter( QObject *o, QEvent *e ); + + void writeJournal(); + + private: + Calendar *mCalendar; + Journal *mJournal; + QDate mDate; + void keyPressEvent ( QKeyEvent * ) ; + QLabel *mTitleLabel; + KTextEdit *mEditor; + + bool mDirty; +}; + +#endif diff --git a/korganizer/journalentry.moc b/korganizer/journalentry.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/journalentry.moc diff --git a/korganizer/kdatenavigator.cpp b/korganizer/kdatenavigator.cpp new file mode 100644 index 0000000..12e983b --- a/dev/null +++ b/korganizer/kdatenavigator.cpp @@ -0,0 +1,364 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001,2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qstring.h> +#include <qkeycode.h> +#include <qlayout.h> +#include <qtimer.h> +#include <qframe.h> +#include <qlabel.h> +#include <qapplication.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> + +#include "koglobals.h" +#include "koprefs.h" +#ifndef KORG_NOPLUGINS +#include "kocore.h" +#endif + +#include <kcalendarsystem.h> + +#include "navigatorbar.h" + +#include "kdatenavigator.h" + +KDateNavigator::KDateNavigator( QWidget *parent, Calendar *calendar, + bool show_week_nums, const char *name, + QDate startDate ) + : QFrame(parent, name), + updateTimer(0L) +{ + mCalendar = calendar; + + setFrameStyle(QFrame::NoFrame); + + QGridLayout *topLayout = new QGridLayout(this,8,8); + + if (! startDate.isValid()) { + kdDebug() << "KDateNavigator::KDateNavigator(): an invalid date was passed as a parameter!" << endl; + startDate = QDate::currentDate(); + } + + mSelectedDates.append(startDate); + m_MthYr = startDate; + m_bShowWeekNums = show_week_nums; + + setFont( KOPrefs::instance()->mDateNavigatorFont ); + mNavigatorBar = new NavigatorBar( startDate, this ); + topLayout->addMultiCellWidget( mNavigatorBar, 0, 0, 0, 7 ); + //mNavigatorBar->resize( 1,1); + connect( mNavigatorBar, SIGNAL( goPrevYear() ), SIGNAL( goPrevYear() ) ); + connect( mNavigatorBar, SIGNAL( goPrevMonth() ), SIGNAL( goPrevMonth() ) ); + connect( mNavigatorBar, SIGNAL( goNextMonth() ), SIGNAL( goNextMonth() ) ); + connect( mNavigatorBar, SIGNAL( goNextYear() ), SIGNAL( goNextYear() ) ); + connect( mNavigatorBar, SIGNAL( monthSelected( int ) ), SIGNAL( monthSelected( int ) ) ); + + // get the day of the week on the first day + QDate dayone(m_MthYr.year(), m_MthYr.month(), 1); + m_fstDayOfWk = dayone.dayOfWeek(); + + int i; + + // Set up the heading fields. + for( i = 0; i < 7; i++ ) { + headings[i] = new QLabel("",this); + //headings[i]->setFont(QFont("Arial", 10, QFont::Bold)); + headings[i]->setAlignment(AlignCenter); + + topLayout->addWidget(headings[i],1,i+1); + } + + // Create the weeknumber labels + for( i = 0; i < 6; i++ ) { + weeknos[i] = new QLabel(this); + weeknos[i]->setAlignment(AlignCenter); + //weeknos[i]->setFont(QFont("Arial", 10)); + if(!show_week_nums) { + weeknos[i]->hide(); + } + weeknos[i]->installEventFilter(this); + + topLayout->addWidget(weeknos[i],i+2,0); + } + + daymatrix = new KODayMatrix( this, mCalendar, dayone, + "KDateNavigator::DayMatrix"); + daymatrix->setFrameStyle(QFrame::Panel|QFrame::Sunken); + daymatrix->setLineWidth(1); + + connect( daymatrix, SIGNAL( selected( const KCal::DateList & ) ), + SIGNAL( datesSelected( const KCal::DateList & ) ) ); + + connect( daymatrix, SIGNAL( eventDropped( Event * ) ), + SIGNAL( eventDropped( Event * ) ) ); + + topLayout->addMultiCellWidget(daymatrix,2,7,1,7); + + // read settings from configuration file. + updateConfig(); + enableRollover(FollowMonth); + setFixedSize ( sizeHint() ); +} + +void KDateNavigator::enableRollover(RolloverType r) +{ + switch(r) + { + case None : + if (updateTimer) + { + updateTimer->stop(); + delete updateTimer; + updateTimer=0L; + } + break; + case FollowDay : + case FollowMonth : + if (!updateTimer) + { + updateTimer = new QTimer(this); + QObject::connect(updateTimer,SIGNAL(timeout()), + this,SLOT(possiblyPastMidnight())); + } + updateTimer->start(0,true); + lastDayChecked = QDate::currentDate(); + } + updateRollover=r; +} + + +KDateNavigator::~KDateNavigator() +{ +} + + +void KDateNavigator::passedMidnight() +{ + QDate today = QDate::currentDate(); + bool emitMonth = false; + + if (today.month() != lastDayChecked.month()) + { + if (updateRollover==FollowMonth && + daymatrix->isEndOfMonth()) { + goNextMonth(); + emitMonth=true; + } + } + daymatrix->recalculateToday(); + daymatrix->repaint(); + emit dayPassed(today); + if (emitMonth) { emit monthPassed(today); } +} + +/* slot */ void KDateNavigator::possiblyPastMidnight() +{ + if (lastDayChecked!=QDate::currentDate()) + { + passedMidnight(); + lastDayChecked=QDate::currentDate(); + } + // Set the timer to go off 1 second after midnight + // or after 8 minutes, whichever comes first. + if (updateTimer) + { + QTime now = QTime::currentTime(); + QTime midnight = QTime(23,59,59); + int msecsWait = QMIN(480000,now.msecsTo(midnight)+2000); + + // qDebug(QString("Waiting %1 msec from %2 to %3.").arg(msecsWait)) + // .arg(now.toString()).arg(midnight.toString())); + + updateTimer->stop(); + updateTimer->start(msecsWait,true); + } +} + +void KDateNavigator::updateDates() +{ + // Find the first day of the week of the current month. + //int d1 = KOGlobals::self()->calendarSystem()->day( m_MthYr ); + QDate dayone( m_MthYr.year(), m_MthYr.month(), m_MthYr.day() ); + int d2 = KOGlobals::self()->calendarSystem()->day( dayone ); + //int di = d1 - d2 + 1; + dayone = dayone.addDays( -d2 + 1 ); + + int m_fstDayOfWkCalsys = KOGlobals::self()->calendarSystem()->dayOfWeek( dayone ); + + // If month begins on Monday and Monday is first day of week, + // month should begin on second line. Sunday doesn't have this problem. + int nextLine = ( ( m_fstDayOfWkCalsys == 1) && + ( KGlobal::locale()->weekStartsMonday() == 1 ) ) ? 7 : 0; + + // update the matrix dates + int index = (KGlobal::locale()->weekStartsMonday() ? 1 : 0) - m_fstDayOfWkCalsys - nextLine; + + + daymatrix->updateView(dayone.addDays(index)); +//each updateDates is followed by an updateView -> repaint is issued there ! +// daymatrix->repaint(); +} + +void KDateNavigator::updateDayMatrix() +{ + daymatrix->updateView(); + daymatrix->repaint(); +} + + +void KDateNavigator::updateView() +{ + + setUpdatesEnabled( false ); + + int i; + +// kdDebug() << "updateView() -> daymatrix->updateView()" << endl; + daymatrix->updateView(); + + // set the week numbers. + for(i = 0; i < 6; i++) { + QString weeknum; + // remember, according to ISO 8601, the first week of the year is the + // first week that contains a thursday. Thus we must subtract off 4, + // not just 1. + + //ET int dayOfYear = buttons[(i + 1) * 7 - 4]->date().dayOfYear(); + int dayOfYear = KOGlobals::self()->calendarSystem()->dayOfYear((daymatrix->getDate((i+1)*7-4))); + + if (dayOfYear % 7 != 0) + weeknum.setNum(dayOfYear / 7 + 1); + else + weeknum.setNum(dayOfYear / 7); + weeknos[i]->setText(weeknum); + } + + setUpdatesEnabled( true ); +// kdDebug() << "updateView() -> repaint()" << endl; + repaint(); + daymatrix->repaint(); +} + +void KDateNavigator::updateConfig() +{ + int day; + for(int i=0; i<7; i++) { + // take the first letter of the day name to be the abbreviation + if (KGlobal::locale()->weekStartsMonday()) { + day = i+1; + } else { + if (i==0) day = 7; + else day = i; + } + QString dayName = KOGlobals::self()->calendarSystem()->weekDayName( day, + true ); + if ( KOPrefs::instance()->mCompactDialogs ) dayName = dayName.left( 1 ); + headings[i]->setText( dayName ); + } + updateDates(); + updateView(); +} + +void KDateNavigator::setShowWeekNums(bool enabled) +{ + m_bShowWeekNums = enabled; + for(int i=0; i<6; i++) { + if(enabled) + weeknos[i]->show(); + else + weeknos[i]->hide(); + } + resize(size()); +} + +void KDateNavigator::selectDates(const DateList& dateList) +{ + + if (dateList.count() > 0) { + mNavigatorBar->selectDates( dateList ); + mSelectedDates = dateList; + + // set our record of the month and year that this datetbl is + // displaying. + m_MthYr = mSelectedDates.first(); + + + // set our record of the first day of the week of the current + // month. This needs to be done before calling dayToIndex, since it + // relies on this information being up to date. + QDate dayone(m_MthYr.year(), m_MthYr.month(), 1); + m_fstDayOfWk = dayone.dayOfWeek(); + + updateDates(); + + daymatrix->setSelectedDaysFrom(*(dateList.begin()), *(--dateList.end())); + + updateView(); + } +} + +int KDateNavigator::dayNum(int row, int col) +{ + return 7 * (row - 1) + (col + 1) - m_fstDayOfWk; +} + +int KDateNavigator::dayToIndex(int dayNum) +{ + int row, col; + + row = (dayNum+m_fstDayOfWk-1-(KGlobal::locale()->weekStartsMonday() ? 1 : 0)) / 7; + if (KGlobal::locale()->weekStartsMonday() && (m_fstDayOfWk == 1)) + row++; + col = (dayNum+m_fstDayOfWk-1-(KGlobal::locale()->weekStartsMonday() ? 1 : 0)) % 7; + return row * 7 + col; +} + +void KDateNavigator::wheelEvent (QWheelEvent *e) +{ + if(e->delta()>0) emit goPrevious(); + else emit goNext(); + + e->accept(); +} + +bool KDateNavigator::eventFilter (QObject *o,QEvent *e) +{ + if (e->type() == QEvent::MouseButtonPress) { + int i; + for(i=0;i<6;++i) { + if (o == weeknos[i]) { + QDate weekstart = daymatrix->getDate(i*7); + emit weekClicked(weekstart); + break; + } + } + return true; + } else { + return false; + } +} + +#include "kdatenavigator.moc" diff --git a/korganizer/kdatenavigator.h b/korganizer/kdatenavigator.h new file mode 100644 index 0000000..3ae1648 --- a/dev/null +++ b/korganizer/kdatenavigator.h @@ -0,0 +1,148 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KDATENAVIGATOR_H +#define KDATENAVIGATOR_H + +#include <qframe.h> +#include <qdatetime.h> +#include <qlabel.h> + +#include <libkcal/calendar.h> + +#include "kodaymatrix.h" + +class QPushButton; +class QTimer; + +class KCalendarSystem; + +class NavigatorBar; + +class KDateNavigator: public QFrame +{ + Q_OBJECT + public: + KDateNavigator( QWidget *parent = 0, Calendar *calendar = 0, + bool show_week_numbers = false, const char *name = 0, + QDate date = QDate::currentDate() ); + ~KDateNavigator(); + + /** The DateNavigator automatically checks for + * the passage of midnight. If rollover type is + * set to None, no signals are emitted and no + * processing is done. With rollover set to + * FollowDay, the day highlighter changes at + * midnight and dayPassed() is emitted. + * With FollowMonth, it has the same effect + * as FollowDay but also adjusts the month that is + * visible and emits monthPassed() when the month changes. + */ + enum RolloverType { None, FollowDay, FollowMonth } ; + void enableRollover( RolloverType ); + + void setShowWeekNums( bool enabled ); + + public slots: + void selectDates( const KCal::DateList & ); + void updateView(); + void updateConfig(); + void updateDayMatrix(); + + signals: + void datesSelected( const KCal::DateList & ); + void eventDropped( Event * ); + void weekClicked( const QDate &); + + void goPrevious(); + void goNext(); + + void goNextMonth(); + void goPrevMonth(); + void goNextYear(); + void goPrevYear(); + void monthSelected( int ); + + // Signals emitted at midnight carrying the new date. + void dayPassed( QDate ); + void monthPassed( QDate ); + + protected slots: + + /** + * Called regularly to see if we need to update the view + * wrt. the today box and the month box. Only important + * if you leave KOrganizer idle for long periods of time. + * + * Until we have a reliable way of setting QTimers to go + * off at a particular wall-clock time, we need this, + * which calls passedMidnight() at the right moments. + */ + void possiblyPastMidnight(); + + /** handles updating the view when midnight has come by due to idle time. + * + */ + void passedMidnight(); + + protected: + void updateDates(); + + void wheelEvent (QWheelEvent *); + + bool eventFilter (QObject *,QEvent *); + + private: + NavigatorBar *mNavigatorBar; + + QFrame *headingSep; + QFrame *weeknumSep; + QLabel *headings[7]; + QLabel *weeknos[7]; + KODayMatrix *daymatrix; + + KCal::DateList mSelectedDates; + QDate m_MthYr; + int m_fstDayOfWk; + bool m_bShowWeekNums; + + int dayNum(int row, int col); + int dayToIndex(int dayNum); + + Calendar *mCalendar; + KCalendarSystem *mCalendarSystem; + + const QString *curHeaders; + + /** used to update the day view periodically, in particular every + * midnight to move the "today" rectangle. + */ + QTimer *updateTimer; + QDate lastDayChecked; + RolloverType updateRollover; + + // Disabling copy constructor and assignment operator + KDateNavigator(const KDateNavigator & ); + KDateNavigator &operator=(const KDateNavigator &); +}; + +#endif diff --git a/korganizer/kdatenavigator.moc b/korganizer/kdatenavigator.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kdatenavigator.moc diff --git a/korganizer/koagenda.cpp b/korganizer/koagenda.cpp new file mode 100644 index 0000000..607c250 --- a/dev/null +++ b/korganizer/koagenda.cpp @@ -0,0 +1,1932 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + Marcus Bains line. + Copyright (c) 2001 Ali Rahimi + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef _WIN32_ +#define protected public +#include <qwidget.h> +#undef protected +#endif +#include <qintdict.h> +#include <qdatetime.h> +#include <qapplication.h> +#include <qpopupmenu.h> +#include <qcursor.h> +#include <qpainter.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kglobal.h> + +#include "koagendaitem.h" +#include "koprefs.h" +#include "koglobals.h" + +#include "koagenda.h" +#include "koagenda.moc" + +#include <libkcal/event.h> +#include <libkcal/todo.h> + +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#endif + +//extern bool globalFlagBlockPainting; +extern int globalFlagBlockAgenda; +extern int globalFlagBlockAgendaItemPaint; +extern int globalFlagBlockAgendaItemUpdate; +extern int globalFlagBlockStartup; + +//////////////////////////////////////////////////////////////////////////// +MarcusBains::MarcusBains(KOAgenda *_agenda,const char *name) + : QFrame(_agenda->viewport(),name), agenda(_agenda) +{ + setLineWidth(0); + setMargin(0); + setBackgroundColor(Qt::red); + minutes = new QTimer(this); + connect(minutes, SIGNAL(timeout()), this, SLOT(updateLoc())); + minutes->start(0, true); + + mTimeBox = new QLabel(this); + mTimeBox->setAlignment(Qt::AlignRight | Qt::AlignBottom); + QPalette pal = mTimeBox->palette(); + pal.setColor(QColorGroup::Foreground, Qt::red); + mTimeBox->setPalette(pal); + //mTimeBox->setAutoMask(true); + + agenda->addChild(mTimeBox); + + oldToday = -1; +} + +MarcusBains::~MarcusBains() +{ + delete minutes; +} + +int MarcusBains::todayColumn() +{ + QDate currentDate = QDate::currentDate(); + + DateList dateList = agenda->dateList(); + DateList::ConstIterator it; + int col = 0; + for(it = dateList.begin(); it != dateList.end(); ++it) { + if((*it) == currentDate) + return KOGlobals::self()->reverseLayout() ? + agenda->columns() - 1 - col : col; + ++col; + } + + return -1; +} +void MarcusBains::updateLoc() +{ + updateLocation(); +} +void MarcusBains::updateLocation(bool recalculate) +{ + + QTime tim = QTime::currentTime(); + //qDebug(" MarcusBains::updateLocation %s ", tim.toString().latin1()); + if((tim.hour() == 0) && (oldTime.hour()==23)) + recalculate = true; + + int mins = tim.hour()*60 + tim.minute(); + int minutesPerCell = 24 * 60 / agenda->rows(); + int y = mins*agenda->gridSpacingY()/minutesPerCell; + int today = recalculate ? todayColumn() : oldToday; + int x = agenda->gridSpacingX()*today; + bool disabled = !(KOPrefs::instance()->mMarcusBainsEnabled); + + oldTime = tim; + oldToday = today; + + if(disabled || (today<0)) { + hide(); mTimeBox->hide(); + return; + } else { + show(); mTimeBox->show(); + } + + if(recalculate) + setFixedSize(agenda->gridSpacingX(),1); + agenda->moveChild(this, x, y); + raise(); + + if(recalculate) + //mTimeBox->setFont(QFont("helvetica",10)); + mTimeBox->setFont(KOPrefs::instance()->mMarcusBainsFont); + + mTimeBox->setText(KGlobal::locale()->formatTime(tim, KOPrefs::instance()->mMarcusBainsShowSeconds)); + mTimeBox->adjustSize(); + // the -2 below is there because there is a bug in this program + // somewhere, where the last column of this widget is a few pixels + // narrower than the other columns. + int offs = (today==agenda->columns()-1) ? -4 : 0; + agenda->moveChild(mTimeBox, + x+agenda->gridSpacingX()-mTimeBox->width()+offs-1, + y-mTimeBox->height()); + + mTimeBox->raise(); + //mTimeBox->setAutoMask(true); + minutes->start(5000,true); +} + + +//////////////////////////////////////////////////////////////////////////// + + +/* + Create an agenda widget with rows rows and columns columns. +*/ +KOAgenda::KOAgenda(int columns,int rows,int rowSize,QWidget *parent, + const char *name,WFlags f) : + QScrollView(parent,name,f) +{ + + mColumns = columns; + mRows = rows; + mGridSpacingY = rowSize; + mAllDayMode = false; +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold ); +#endif + mHolidayMask = 0; + init(); +} + +/* + Create an agenda widget with columns columns and one row. This is used for + all-day events. +*/ +KOAgenda::KOAgenda(int columns,QWidget *parent,const char *name,WFlags f) : + QScrollView(parent,name,f) +{ + + blockResize = false; + mColumns = columns; + mRows = 1; + //qDebug("aaaaaaaaaaaaaaaaaaldays %d ", KOPrefs::instance()->mAllDaySize); + mGridSpacingY = KOPrefs::instance()->mAllDaySize; + mAllDayMode = true; +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold ); +#endif + mHolidayMask = 0; + init(); +} + + +KOAgenda::~KOAgenda() +{ + if(mMarcusBains) delete mMarcusBains; + +} + +Incidence *KOAgenda::selectedIncidence() const +{ + return (mSelectedItem ? mSelectedItem->incidence() : 0); +} + + +QDate KOAgenda::selectedIncidenceDate() const +{ + return (mSelectedItem ? mSelectedItem->itemDate() : QDate()); +} + + +void KOAgenda::init() +{ +#ifndef _WIN32_ + int wflags = viewport()-> getWFlags() |WRepaintNoErase;//WResizeNoErase + viewport()->setWFlags ( wflags); +#endif + mGridSpacingX = 80; + mResizeBorderWidth = 8; + mScrollBorderWidth = 8; + mScrollDelay = 30; + mScrollOffset = 10; + mPaintPixmap.resize( 20,20); + //enableClipper(true); + + // Grab key strokes for keyboard navigation of agenda. Seems to have no + // effect. Has to be fixed. + setFocusPolicy(WheelFocus); + + connect(&mScrollUpTimer,SIGNAL(timeout()),SLOT(scrollUp())); + connect(&mScrollDownTimer,SIGNAL(timeout()),SLOT(scrollDown())); + connect(&mResizeTimer,SIGNAL(timeout()),SLOT(finishResize())); + + mStartCellX = 0; + mStartCellY = 0; + mCurrentCellX = 0; + mCurrentCellY = 0; + + mSelectionCellX = 0; + mSelectionYTop = 0; + mSelectionHeight = 0; + + mOldLowerScrollValue = -1; + mOldUpperScrollValue = -1; + + mClickedItem = 0; + + mActionItem = 0; + mActionType = NOP; + mItemMoved = false; + + mSelectedItem = 0; + + // mItems.setAutoDelete(true); + + resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 ); + + viewport()->update(); + + setMinimumSize(30, 1); +// setMaximumHeight(mGridSpacingY * mRows + 5); + + // Disable horizontal scrollbar. This is a hack. The geometry should be + // controlled in a way that the contents horizontally always fits. Then it is + // not necessary to turn off the scrollbar. + setHScrollBarMode(AlwaysOff); + if ( ! mAllDayMode ) + setVScrollBarMode(AlwaysOn); + else + setVScrollBarMode(AlwaysOff); + + setStartHour(KOPrefs::instance()->mDayBegins); + + calculateWorkingHours(); + + connect(verticalScrollBar(),SIGNAL(valueChanged(int)), + SLOT(checkScrollBoundaries(int))); + + // Create the Marcus Bains line. + if(mAllDayMode) + mMarcusBains = 0; + else { + mMarcusBains = new MarcusBains(this); + addChild(mMarcusBains); + } +} + +void KOAgenda::clear() +{ + KOAgendaItem *item; + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + mUnusedItems.append( item ); + //item->hide(); + } + mItems.clear(); + mSelectedItem = 0; + clearSelection(); +} + +void KOAgenda::clearSelection() +{ + mSelectionCellX = 0; + mSelectionYTop = 0; + mSelectionHeight = 0; +} + +void KOAgenda::marcus_bains() +{ + if(mMarcusBains) mMarcusBains->updateLocation(true); +} + + +void KOAgenda::changeColumns(int columns) +{ + if (columns == 0) { + kdDebug() << "KOAgenda::changeColumns() called with argument 0" << endl; + return; + } + + clear(); + + mColumns = columns; +// setMinimumSize(mColumns * 10, mGridSpacingY + 1); +// init(); +// update(); + //qDebug("KOAgenda::changeColumns "); + computeSizes(); + // QResizeEvent event( size(), size() ); + + //QApplication::sendEvent( this, &event ); +} + +/* + This is the eventFilter function, which gets all events from the KOAgendaItems + contained in the agenda. It has to handle moving and resizing for all items. +*/ +bool KOAgenda::eventFilter ( QObject *object, QEvent *event ) +{ +// kdDebug() << "KOAgenda::eventFilter" << endl; + switch(event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + return eventFilter_mouse(object, static_cast<QMouseEvent *>(event)); + + case (QEvent::Leave): + if (!mActionItem) + setCursor(arrowCursor); + return true; + + default: + return QScrollView::eventFilter(object,event); + } +} + + +bool KOAgenda::eventFilter_mouse(QObject *object, QMouseEvent *me) +{ + //qDebug("KOAgenda::eventFilter_mous "); + QPoint viewportPos; + if (object != viewport()) { + viewportPos = ((QWidget *)object)->mapToParent(me->pos()); + } else { + viewportPos = me->pos(); + } + static int startX = 0; + static int startY = 0; + static bool block = true; + switch (me->type()) { + case QEvent::MouseButtonPress: + //qDebug("QEvent::MouseButtonPress: "); + // kdDebug() << "koagenda: filtered button press" << endl; + if (object != viewport()) { + if (me->button() == RightButton) { + + mClickedItem = (KOAgendaItem *)object; + if (mClickedItem) { + selectItem(mClickedItem); + // emit showIncidencePopupSignal(mClickedItem->incidence()); + } + //mItemPopup->popup(QCursor::pos()); + } else { + mActionItem = (KOAgendaItem *)object; + if (mActionItem) { + if ( mSelectionHeight > 0 ) { + int selectionCellX = mSelectionCellX * mGridSpacingX; + int selectionYTop = mSelectionYTop; + int gridSpacingX = mGridSpacingX; + int selectionHeight = mSelectionHeight; + clearSelection(); + repaintContents( selectionCellX, selectionYTop, + gridSpacingX, selectionHeight,false ); + } + selectItem(mActionItem); + Incidence *incidence = mActionItem->incidence(); + if ( incidence->isReadOnly() /*|| incidence->recurrence()->doesRecur() */) { + mActionItem = 0; + } else { + startItemAction(viewportPos); + startX = viewportPos.x(); + startY = viewportPos.y(); + block = true; + } + } + } + } else { + selectItem(0); + mActionItem = 0; + setCursor(arrowCursor); + startSelectAction(viewportPos); + } + break; + + case QEvent::MouseButtonRelease: + //qDebug("QEvent::MouseButtonRelease: "); + if (me->button() == RightButton && block ) { + if (object != viewport()) { + mClickedItem = (KOAgendaItem *)object; + if (mActionItem ) { + endItemAction(); + } + if (mClickedItem) { + selectItem(mClickedItem); + emit showIncidencePopupSignal(mClickedItem->incidence()); + } + } + break; + } + block = true; + if (mActionItem) { + QPoint clipperPos = clipper()->mapFromGlobal(viewport()->mapToGlobal(viewportPos)); + //qDebug(" %d %d %d ",clipperPos.y(),visibleHeight() , 9 ); + if ( mActionType == MOVE && (clipperPos.y() > visibleHeight()-2 ||clipperPos.y() < 0 ) ) { + mScrollUpTimer.stop(); + mScrollDownTimer.stop(); + mActionItem->resetMove(); + placeSubCells( mActionItem ); + // emit startDragSignal( mActionItem->incidence() ); + setCursor( arrowCursor ); + mActionItem = 0; + mActionType = NOP; + mItemMoved = 0; + return true; + } + endItemAction(); + } else if ( mActionType == SELECT ) { + endSelectAction(); + } + break; + + case QEvent::MouseMove: + if (object != viewport()) { + KOAgendaItem *moveItem = (KOAgendaItem *)object; + //qDebug("moveItem %d ",moveItem ); + if (!moveItem->incidence()->isReadOnly() /*&& + !moveItem->incidence()->recurrence()->doesRecur()*/ ) + if (!mActionItem) + setNoActionCursor(moveItem,viewportPos); + else { + if ( block ) { + int dX, dY; + dX = startX - viewportPos.x(); + if ( dX < 0 ) + dX = -dX; + dY = viewportPos.y() - startY; + if ( dY < 0 ) + dY = -dY; + int diff = 30; + if ( QApplication::desktop()->width() < 480 ) + diff = 15; + // qDebug(" %d %d ",dX, dY ); + if ( dX > diff || dY > diff ) { + block = false; + } + } + if ( !block ) + performItemAction(viewportPos); + } + } else { + if ( mActionType == SELECT ) { + performSelectAction( viewportPos ); + } + } + break; + + case QEvent::MouseButtonDblClick: + if (object == viewport()) { + selectItem(0); + int x,y; + viewportToContents(viewportPos.x(),viewportPos.y(),x,y); + int gx,gy; + contentsToGrid(x,y,gx,gy); + emit newEventSignal(gx,gy); + } else { + KOAgendaItem *doubleClickedItem = (KOAgendaItem *)object; + selectItem(doubleClickedItem); + if ( KOPrefs::instance()->mEditOnDoubleClick ) + emit editIncidenceSignal(doubleClickedItem->incidence()); + else + emit showIncidenceSignal(doubleClickedItem->incidence()); + } + break; + + default: + break; + } + + return true; +} + +void KOAgenda::startSelectAction(QPoint viewportPos) +{ + //emit newStartSelectSignal(); + + mActionType = SELECT; + + int x,y; + viewportToContents(viewportPos.x(),viewportPos.y(),x,y); + int gx,gy; + contentsToGrid(x,y,gx,gy); + + mStartCellX = gx; + mStartCellY = gy; + mCurrentCellX = gx; + mCurrentCellY = gy; + + // Store coordinates of old selection + int selectionX = mSelectionCellX * mGridSpacingX; + int selectionYTop = mSelectionYTop; + int selectionHeight = mSelectionHeight; + + // Store new selection + mSelectionCellX = gx; + mSelectionYTop = gy * mGridSpacingY; + mSelectionHeight = mGridSpacingY; + + // Clear old selection + repaintContents( selectionX, selectionYTop, + mGridSpacingX, selectionHeight,false ); + + // Paint new selection + // repaintContents( mSelectionCellX * mGridSpacingX, mSelectionYTop, + // mGridSpacingX, mSelectionHeight ); +} + +void KOAgenda::performSelectAction(QPoint viewportPos) +{ + int x,y; + viewportToContents(viewportPos.x(),viewportPos.y(),x,y); + int gx,gy; + contentsToGrid(x,y,gx,gy); + + QPoint clipperPos = clipper()-> + mapFromGlobal(viewport()->mapToGlobal(viewportPos)); + + // Scroll if cursor was moved to upper or lower end of agenda. + if (clipperPos.y() < mScrollBorderWidth) { + mScrollUpTimer.start(mScrollDelay); + } else if (visibleHeight() - clipperPos.y() < + mScrollBorderWidth) { + mScrollDownTimer.start(mScrollDelay); + } else { + mScrollUpTimer.stop(); + mScrollDownTimer.stop(); + } + + if ( gy > mCurrentCellY ) { + mSelectionHeight = ( gy + 1 ) * mGridSpacingY - mSelectionYTop; + +#if 0 + // FIXME: Repaint only the newly selected region + repaintContents( mSelectionCellX * mGridSpacingX, + mCurrentCellY + mGridSpacingY, + mGridSpacingX, + mSelectionHeight - ( gy - mCurrentCellY - 1 ) * mGridSpacingY ); +#else + repaintContents( (KOGlobals::self()->reverseLayout() ? + mColumns - 1 - mSelectionCellX : mSelectionCellX) * + mGridSpacingX, mSelectionYTop, + mGridSpacingX, mSelectionHeight , false); +#endif + + mCurrentCellY = gy; + } else if ( gy < mCurrentCellY ) { + if ( gy >= mStartCellY ) { + int selectionHeight = mSelectionHeight; + mSelectionHeight = ( gy + 1 ) * mGridSpacingY - mSelectionYTop; + + repaintContents( (KOGlobals::self()->reverseLayout() ? + mColumns - 1 - mSelectionCellX : mSelectionCellX) * + mGridSpacingX, mSelectionYTop, + mGridSpacingX, selectionHeight,false ); + + mCurrentCellY = gy; + } else { + } + } +} + +void KOAgenda::endSelectAction() +{ + mActionType = NOP; + mScrollUpTimer.stop(); + mScrollDownTimer.stop(); + + emit newTimeSpanSignal(mStartCellX,mStartCellY,mCurrentCellX,mCurrentCellY); +} + +void KOAgenda::startItemAction(QPoint viewportPos) +{ + int x,y; + viewportToContents(viewportPos.x(),viewportPos.y(),x,y); + int gx,gy; + contentsToGrid(x,y,gx,gy); + + mStartCellX = gx; + mStartCellY = gy; + mCurrentCellX = gx; + mCurrentCellY = gy; + + if (mAllDayMode) { + int gridDistanceX = (x - gx * mGridSpacingX); + if (gridDistanceX < mResizeBorderWidth && + mActionItem->cellX() == mCurrentCellX) { + mActionType = RESIZELEFT; + setCursor(sizeHorCursor); + } else if ((mGridSpacingX - gridDistanceX) < mResizeBorderWidth && + mActionItem->cellXWidth() == mCurrentCellX) { + mActionType = RESIZERIGHT; + setCursor(sizeHorCursor); + } else { + mActionType = MOVE; + mActionItem->startMove(); + setCursor(sizeAllCursor); + } + } else { + int gridDistanceY = (y - gy * mGridSpacingY); + bool allowResize = ( mActionItem->incidence()->type() != "Todo" ); + if (allowResize && gridDistanceY < mResizeBorderWidth && + mActionItem->cellYTop() == mCurrentCellY && + !mActionItem->firstMultiItem()) { + mActionType = RESIZETOP; + setCursor(sizeVerCursor); + } else if (allowResize &&(mGridSpacingY - gridDistanceY) < mResizeBorderWidth && + mActionItem->cellYBottom() == mCurrentCellY && + !mActionItem->lastMultiItem()) { + mActionType = RESIZEBOTTOM; + setCursor(sizeVerCursor); + } else { + mActionType = MOVE; + mActionItem->startMove(); + setCursor(sizeAllCursor); + } + } +} + +void KOAgenda::performItemAction(QPoint viewportPos) +{ +// kdDebug() << "viewportPos: " << viewportPos.x() << "," << viewportPos.y() << endl; +// QPoint point = viewport()->mapToGlobal(viewportPos); +// kdDebug() << "Global: " << point.x() << "," << point.y() << endl; +// point = clipper()->mapFromGlobal(point); +// kdDebug() << "clipper: " << point.x() << "," << point.y() << endl; +// kdDebug() << "visible height: " << visibleHeight() << endl; + int x,y; + viewportToContents(viewportPos.x(),viewportPos.y(),x,y); +// kdDebug() << "contents: " << x << "," << y << "\n" << endl; + int gx,gy; + contentsToGrid(x,y,gx,gy); + QPoint clipperPos = clipper()-> + mapFromGlobal(viewport()->mapToGlobal(viewportPos)); + + // Cursor left active agenda area. + // This starts a drag. + if ( /*clipperPos.y() < 0 || clipperPos.y() > visibleHeight() ||*/ + clipperPos.x() < 0 || clipperPos.x() > visibleWidth() ) { + if ( mActionType == MOVE ) { + mScrollUpTimer.stop(); + mScrollDownTimer.stop(); + mActionItem->resetMove(); + placeSubCells( mActionItem ); + // emit startDragSignal( mActionItem->incidence() ); + setCursor( arrowCursor ); + mActionItem = 0; + mActionType = NOP; + mItemMoved = 0; + return; + } + } else { + switch ( mActionType ) { + case MOVE: + setCursor( sizeAllCursor ); + break; + case RESIZETOP: + case RESIZEBOTTOM: + setCursor( sizeVerCursor ); + break; + case RESIZELEFT: + case RESIZERIGHT: + setCursor( sizeHorCursor ); + break; + default: + setCursor( arrowCursor ); + } + } + + // Scroll if item was moved to upper or lower end of agenda. + if (clipperPos.y() < mScrollBorderWidth) { + mScrollUpTimer.start(mScrollDelay); + } else if (visibleHeight() - clipperPos.y() < + mScrollBorderWidth) { + mScrollDownTimer.start(mScrollDelay); + } else { + mScrollUpTimer.stop(); + mScrollDownTimer.stop(); + } + + // Move or resize item if necessary + if (mCurrentCellX != gx || mCurrentCellY != gy) { + mItemMoved = true; + mActionItem->raise(); + if (mActionType == MOVE) { + // Move all items belonging to a multi item + KOAgendaItem *moveItem = mActionItem->firstMultiItem(); + bool isMultiItem = (moveItem || mActionItem->lastMultiItem()); + if (!moveItem) moveItem = mActionItem; + while (moveItem) { + int dy; + if (isMultiItem) dy = 0; + else dy = gy - mCurrentCellY; + moveItem->moveRelative(gx - mCurrentCellX,dy); + int x,y; + gridToContents(moveItem->cellX(),moveItem->cellYTop(),x,y); + moveItem->resize(mGridSpacingX * moveItem->cellWidth(), + mGridSpacingY * moveItem->cellHeight()); + moveChild(moveItem,x,y); + moveItem = moveItem->nextMultiItem(); + } + } else if (mActionType == RESIZETOP) { + if (mCurrentCellY <= mActionItem->cellYBottom()) { + mActionItem->expandTop(gy - mCurrentCellY); + mActionItem->resize(mActionItem->width(), + mGridSpacingY * mActionItem->cellHeight()); + int x,y; + gridToContents(mCurrentCellX,mActionItem->cellYTop(),x,y); + //moveChild(mActionItem,childX(mActionItem),y); + QScrollView::moveChild( mActionItem,childX(mActionItem),y ); + } + } else if (mActionType == RESIZEBOTTOM) { + if (mCurrentCellY >= mActionItem->cellYTop()) { + mActionItem->expandBottom(gy - mCurrentCellY); + mActionItem->resize(mActionItem->width(), + mGridSpacingY * mActionItem->cellHeight()); + } + } else if (mActionType == RESIZELEFT) { + if (mCurrentCellX <= mActionItem->cellXWidth()) { + mActionItem->expandLeft(gx - mCurrentCellX); + mActionItem->resize(mGridSpacingX * mActionItem->cellWidth(), + mActionItem->height()); + int x,y; + gridToContents(mActionItem->cellX(),mActionItem->cellYTop(),x,y); + moveChild(mActionItem,x,childY(mActionItem)); + } + } else if (mActionType == RESIZERIGHT) { + if (mCurrentCellX >= mActionItem->cellX()) { + mActionItem->expandRight(gx - mCurrentCellX); + mActionItem->resize(mGridSpacingX * mActionItem->cellWidth(), + mActionItem->height()); + } + } + mCurrentCellX = gx; + mCurrentCellY = gy; + } +} + +void KOAgenda::endItemAction() +{ + + if ( mItemMoved ) { + KOAgendaItem *placeItem = mActionItem->firstMultiItem(); + if ( !placeItem ) { + placeItem = mActionItem; + } + if ( placeItem->incidence()->recurrence()->doesRecur() ) { + Incidence* oldInc = placeItem->incidence(); + placeItem->recreateIncidence(); + emit addToCalSignal(placeItem->incidence(), oldInc ); + } + int type = mActionType; + if ( mAllDayMode ) + type = -1; + KOAgendaItem *modifiedItem = placeItem; + //emit itemModified( placeItem, mActionType /*KOGlobals::EVENTEDITED */); + QPtrList<KOAgendaItem> oldconflictItems ;//= placeItem->conflictItems(); + KOAgendaItem *item; + + if ( placeItem->incidence()->type() == "Todo" ) { + mSelectedItem = 0; + //qDebug("todo %d %d %d ", mCurrentCellX, modifiedItem->cellX() ,modifiedItem->cellXWidth()); + modifiedItem->mLastMoveXPos = mCurrentCellX; + emit itemModified( modifiedItem, mActionType ); + } + else { +#if 0 + for ( item=oldconflictItems.first(); item != 0; + item=oldconflictItems.next() ) { + placeSubCells(item); + } + while ( placeItem ) { + //qDebug("placeItem %s ", placeItem->incidence()->summary().latin1()); + placeSubCells( placeItem ); + placeItem = placeItem->nextMultiItem(); + } +#endif + + globalFlagBlockAgendaItemPaint = 1; + for ( item=oldconflictItems.first(); item != 0; + item=oldconflictItems.next() ) { + placeSubCells(item); + } + while ( placeItem ) { + //qDebug("placeItem %s ", placeItem->incidence()->summary().latin1()); + oldconflictItems = placeItem->conflictItems(); + for ( item=oldconflictItems.first(); item != 0; + item=oldconflictItems.next() ) { + placeSubCells(item); + } + placeSubCells( placeItem ); + placeItem = placeItem->nextMultiItem(); + } + globalFlagBlockAgendaItemPaint = 0; + for ( item=oldconflictItems.first(); item != 0; + item=oldconflictItems.next() ) { + globalFlagBlockAgendaItemUpdate = 0; + item->repaintMe(); + globalFlagBlockAgendaItemUpdate = 1; + item->repaint( false ); + } + placeItem = modifiedItem; + + while ( placeItem ) { + //qDebug("placeItem %s ", placeItem->incidence()->summary().latin1()); + globalFlagBlockAgendaItemUpdate = 0; + placeItem->repaintMe(); + globalFlagBlockAgendaItemUpdate = 1; + placeItem->repaint(false); + placeItem = placeItem->nextMultiItem(); + } + emit itemModified( modifiedItem, mActionType ); + + + placeItem = modifiedItem; + while ( placeItem ) { + oldconflictItems = placeItem->conflictItems(); + for ( item=oldconflictItems.first(); item != 0; + item=oldconflictItems.next() ) { + placeSubCells(item); + } + placeSubCells( placeItem ); + placeItem = placeItem->nextMultiItem(); + + } + placeItem = modifiedItem; + while ( placeItem ) { + oldconflictItems = placeItem->conflictItems(); + for ( item=oldconflictItems.first(); item != 0; + item=oldconflictItems.next() ) { + globalFlagBlockAgendaItemUpdate = 0; + item->repaintMe(); + globalFlagBlockAgendaItemUpdate = 1; + item->repaint(false); + } + placeItem = placeItem->nextMultiItem(); + } + /* + + oldconflictItems = modifiedItem->conflictItems(); + for ( item=oldconflictItems.first(); item != 0; + item=oldconflictItems.next() ) { + globalFlagBlockAgendaItemUpdate = 0; + item->paintMe(false); + globalFlagBlockAgendaItemUpdate = 1; + item->repaint(false); + } + */ + + + } + + } + + mScrollUpTimer.stop(); + mScrollDownTimer.stop(); + setCursor( arrowCursor ); + mActionItem = 0; + mActionType = NOP; + mItemMoved = 0; + +} + +void KOAgenda::setNoActionCursor(KOAgendaItem *moveItem,QPoint viewportPos) +{ +// kdDebug() << "viewportPos: " << viewportPos.x() << "," << viewportPos.y() << endl; +// QPoint point = viewport()->mapToGlobal(viewportPos); +// kdDebug() << "Global: " << point.x() << "," << point.y() << endl; +// point = clipper()->mapFromGlobal(point); +// kdDebug() << "clipper: " << point.x() << "," << point.y() << endl; + + int x,y; + viewportToContents(viewportPos.x(),viewportPos.y(),x,y); +// kdDebug() << "contents: " << x << "," << y << "\n" << endl; + int gx,gy; + contentsToGrid(x,y,gx,gy); + + // Change cursor to resize cursor if appropriate + if (mAllDayMode) { + int gridDistanceX = (x - gx * mGridSpacingX); + if (gridDistanceX < mResizeBorderWidth && + moveItem->cellX() == gx) { + setCursor(sizeHorCursor); + } else if ((mGridSpacingX - gridDistanceX) < mResizeBorderWidth && + moveItem->cellXWidth() == gx) { + setCursor(sizeHorCursor); + } else { + setCursor(arrowCursor); + } + } else { + int gridDistanceY = (y - gy * mGridSpacingY); + if (gridDistanceY < mResizeBorderWidth && + moveItem->cellYTop() == gy && + !moveItem->firstMultiItem()) { + setCursor(sizeVerCursor); + } else if ((mGridSpacingY - gridDistanceY) < mResizeBorderWidth && + moveItem->cellYBottom() == gy && + !moveItem->lastMultiItem()) { + setCursor(sizeVerCursor); + } else { + setCursor(arrowCursor); + } + } +} + + +/* + Place item in cell and take care that multiple items using the same cell do + not overlap. This method is not yet optimal. It doesn´t use the maximum space + it can get in all cases. + At the moment the method has a bug: When an item is placed only the sub cell + widths of the items are changed, which are within the Y region the item to + place spans. When the sub cell width change of one of this items affects a + cell, where other items are, which do not overlap in Y with the item to place, + the display gets corrupted, although the corruption looks quite nice. +*/ +void KOAgenda::placeSubCells(KOAgendaItem *placeItem) +{ + + QPtrList<KOAgendaItem> conflictItems; + int maxSubCells = 0; + QIntDict<KOAgendaItem> subCellDict(5); + + KOAgendaItem *item; + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + if (item != placeItem) { + if (placeItem->cellX() <= item->cellXWidth() && + placeItem->cellXWidth() >= item->cellX()) { + if ((placeItem->cellYTop() <= item->cellYBottom()) && + (placeItem->cellYBottom() >= item->cellYTop())) { + conflictItems.append(item); + if (item->subCells() > maxSubCells) + maxSubCells = item->subCells(); + subCellDict.insert(item->subCell(),item); + } + } + } + } + + if (conflictItems.count() > 0) { + // Look for unused sub cell and insert item + int i; + for(i=0;i<maxSubCells;++i) { + if (!subCellDict.find(i)) { + placeItem->setSubCell(i); + break; + } + } + if (i == maxSubCells) { + placeItem->setSubCell(maxSubCells); + maxSubCells++; // add new item to number of sub cells + } + + // Prepare for sub cell geometry adjustment + int newSubCellWidth; + if (mAllDayMode) newSubCellWidth = mGridSpacingY / maxSubCells; + else newSubCellWidth = mGridSpacingX / maxSubCells; + conflictItems.append(placeItem); + + + // Adjust sub cell geometry of all items + for ( item=conflictItems.first(); item != 0; + item=conflictItems.next() ) { + item->setSubCells(maxSubCells); + if (mAllDayMode) { + item->resize(item->cellWidth() * mGridSpacingX, newSubCellWidth); + } else { + item->resize(newSubCellWidth, item->cellHeight() * mGridSpacingY); + } + int x,y; + gridToContents(item->cellX(),item->cellYTop(),x,y); + if (mAllDayMode) { + y += item->subCell() * newSubCellWidth; + } else { + x += item->subCell() * newSubCellWidth; + } + moveChild(item,x,y); + // qDebug("moveChild %s %d %d ", item->incidence()->summary().latin1() ,x,y); + //item->updateItem(); + } + + } else { + placeItem->setSubCell(0); + placeItem->setSubCells(1); + if (mAllDayMode) placeItem->resize(placeItem->width(),mGridSpacingY); + else placeItem->resize(mGridSpacingX,placeItem->height()); + int x,y; + gridToContents(placeItem->cellX(),placeItem->cellYTop(),x,y); + moveChild(placeItem,x,y); + } + placeItem->setConflictItems(conflictItems); + // for ( item=conflictItems.first(); item != 0; +// item=conflictItems.next() ) { +// //item->updateItem(); +// //qDebug("xxx item->updateItem() %s %d %d", item->incidence()->summary().latin1(),item->x(), item->y() ); +// } +// placeItem->updateItem(); +} + +void KOAgenda::drawContents(QPainter* p, int cx, int cy, int cw, int ch) +{ + if ( globalFlagBlockAgenda ) + return; + //qDebug("KOAgenda::drawContents "); + if ( mCurPixWid != contentsWidth() || mCurPixHei != contentsHeight() ) + ;//drawContentsToPainter(); + + QPaintDevice* pd = p->device(); + p->end(); + int vx, vy; + int selectionX = KOGlobals::self()->reverseLayout() ? + (mColumns - 1 - mSelectionCellX) * mGridSpacingX : + mSelectionCellX * mGridSpacingX; + contentsToViewport ( cx, cy, vx,vy); + // qDebug(" %d %d %d %d ", cx, cy, cw,ch) ; + if ( !(selectionX == cx && cy == mSelectionYTop && cw ==mGridSpacingX && ch == mSelectionHeight ) ) + bitBlt ( pd, vx, vy, &mPaintPixmap, cx, cy, cw, ch ,CopyROP); + + if ( mSelectionHeight > 0 ) { + //qDebug("---- %d %d %d %d ", selectionX, mSelectionYTop, mGridSpacingX, mSelectionHeight ); + if ( ( cx + cw ) >= selectionX && cx <= ( selectionX + mGridSpacingX ) && + ( cy + ch ) >= mSelectionYTop && cy <= ( mSelectionYTop + mSelectionHeight ) ) { + contentsToViewport ( selectionX, mSelectionYTop, vx,vy); + bitBlt ( pd, vx+1, vy, &mHighlightPixmap, 0, mSelectionYTop, mGridSpacingX-1, mSelectionHeight ,CopyROP); + } + } + //qDebug("btbl "); + p->begin( pd ); + //qDebug("end "); +} + +void KOAgenda::finishUpdate() +{ + + KOAgendaItem *item; + globalFlagBlockAgendaItemPaint = 1; + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + if ( !item->isVisible() ) + item->show(); + + } + globalFlagBlockAgendaItemUpdate = 0; + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + item->repaintMe( ); + } + globalFlagBlockAgendaItemUpdate = 1; + qApp->processEvents(); + globalFlagBlockAgendaItemPaint = 0; + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + item->repaint( false ); + } + +} + +/* + Draw grid in the background of the agenda. +*/ +void KOAgenda::drawContentsToPainter( QPainter* paint, bool backgroundOnly )// int cx, int cy, int cw, int ch) +{ + + + if ( ! mGridSpacingX || ! mGridSpacingY ||! mHolidayMask ) + return; + if ( globalFlagBlockAgenda > 1 && globalFlagBlockAgenda < 4 ) + return; + int cx = 0, cy = 0, cw = contentsWidth(), ch = contentsHeight(); + if ( ch < 1 ) + ch = 1; + if ( mPaintPixmap.width() < contentsWidth()+42 || mPaintPixmap.height() < ch ) { + mPaintPixmap.resize( contentsWidth()+42, ch ); + } + mCurPixWid = contentsWidth(); + mCurPixHei = ch; + if ( mHighlightPixmap.width() < mGridSpacingX-1 || mHighlightPixmap.height() < ch ) { + mHighlightPixmap.resize( mGridSpacingX-1, ch ); + mHighlightPixmap.fill ( KOPrefs::instance()->mHighlightColor ); + } + mPixPainter.begin( &mPaintPixmap) ; + //qDebug("wid %d hei %d ",mPaintPixmap.width(),mPaintPixmap.height() ); + QPainter * p ; + if (paint == 0) { + mPaintPixmap.fill(KOPrefs::instance()->mAgendaBgColor); + p = &mPixPainter; + } + else + p = paint ; + // qDebug("++++++KOAgenda::drawContentsTo Painter %d %d %d %d ", cx, cy, cw, ch); + + //--cx;++cw; + int lGridSpacingY = mGridSpacingY*2; + int selDay; + if ( !backgroundOnly ) + for ( selDay = 0; selDay < mSelectedDates.count(); ++selDay) + { + if ( mSelectedDates[selDay] == QDateTime::currentDateTime ().date() && KOPrefs::instance()->mHighlightCurrentDay) { + int x1 = cx; + int y1 = 0; + if (y1 < cy) y1 = cy; + int x2 = cx+cw-1; + int y2 = contentsHeight(); + if (y2 > cy+ch-1) y2=cy+ch-1; + if (x2 >= x1 && y2 >= y1) { + int gxStart = selDay; + int gxEnd = gxStart ; + int xStart = KOGlobals::self()->reverseLayout() ? + (mColumns - 1 - gxStart)*mGridSpacingX : + gxStart*mGridSpacingX; + if (xStart < x1) xStart = x1; + int xEnd = KOGlobals::self()->reverseLayout() ? + (mColumns - gxStart)*mGridSpacingX-1 : + (gxStart+1)*mGridSpacingX-1; + if (xEnd > x2) xEnd = x2; + if ( KOPrefs::instance()->mUseHighlightLightColor ) + p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1, + KOPrefs::instance()->mAgendaBgColor.light()); + else + p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1, + KOPrefs::instance()->mAgendaBgColor.dark()); + + } + } + } + // Highlight working hours + + if ( !backgroundOnly ) + if (mWorkingHoursEnable) { + int x1 = cx; + int y1 = mWorkingHoursYTop; + if (y1 < cy) y1 = cy; + int x2 = cx+cw-1; + // int x2 = mGridSpacingX * 5 - 1; + // if (x2 > cx+cw-1) x2 = cx + cw - 1; + int y2 = mWorkingHoursYBottom; + if (y2 > cy+ch-1) y2=cy+ch-1; + + if (x2 >= x1 && y2 >= y1) { + // qDebug("x1 %d mGridSpacingX %d ", x1, mGridSpacingX ); + int gxStart = x1/mGridSpacingX; + int gxEnd = x2/mGridSpacingX; + while(gxStart <= gxEnd) { + if (gxStart < int(mHolidayMask->count()) && + !mHolidayMask->at(gxStart)) { + int xStart = KOGlobals::self()->reverseLayout() ? + (mColumns - 1 - gxStart)*mGridSpacingX : + gxStart*mGridSpacingX; + if (xStart < x1) xStart = x1; + int xEnd = KOGlobals::self()->reverseLayout() ? + (mColumns - gxStart)*mGridSpacingX-1 : + (gxStart+1)*mGridSpacingX-1; + if (xEnd > x2) xEnd = x2; + if ( mSelectedDates[gxStart] == QDateTime::currentDateTime ().date()&& KOPrefs::instance()->mHighlightCurrentDay ) { + if ( KOPrefs::instance()->mUseHighlightLightColor ) + p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1, + KOPrefs::instance()->mWorkingHoursColor.light()); + else + p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1, + KOPrefs::instance()->mWorkingHoursColor.dark()); + } else { + p->fillRect(xStart,y1,xEnd-xStart+1,y2-y1+1, + KOPrefs::instance()->mWorkingHoursColor); + } + } + ++gxStart; + } + } + } + /* + int selectionX = KOGlobals::self()->reverseLayout() ? + (mColumns - 1 - mSelectionCellX) * mGridSpacingX : + mSelectionCellX * mGridSpacingX; + + // Draw selection + if ( ( cx + cw ) >= selectionX && cx <= ( selectionX + mGridSpacingX ) && + ( cy + ch ) >= mSelectionYTop && cy <= ( mSelectionYTop + mSelectionHeight ) ) { + // TODO: paint only part within cx,cy,cw,ch + p->fillRect( selectionX, mSelectionYTop, mGridSpacingX, + mSelectionHeight, KOPrefs::instance()->mHighlightColor ); + } + */ + // Draw vertical lines of grid + + int x = ((int)(cx/mGridSpacingX))*mGridSpacingX; + if ( mGridSpacingX > 0 ) { + while (x < cx + cw) { + p->drawLine(x,cy,x,cy+ch); + x+=mGridSpacingX; + } + } + // Draw horizontal lines of grid + int y = ((int)(cy/lGridSpacingY))*lGridSpacingY; + if ( lGridSpacingY > 0 ) { + while (y < cy + ch) { + p->drawLine(cx,y,cx+cw,y); + y+=lGridSpacingY; + } + } + mPixPainter.end() ; +} + +/* + Convert srcollview contents coordinates to agenda grid coordinates. +*/ +void KOAgenda::contentsToGrid (int x, int y, int& gx, int& gy) +{ + gx = KOGlobals::self()->reverseLayout() ? mColumns - 1 - x/mGridSpacingX : + x/mGridSpacingX; + gy = y/mGridSpacingY; +} + +/* + Convert agenda grid coordinates to scrollview contents coordinates. +*/ +void KOAgenda::gridToContents (int gx, int gy, int& x, int& y) +{ + x = KOGlobals::self()->reverseLayout() ? (mColumns - 1 - gx)*mGridSpacingX: + gx*mGridSpacingX; + y = gy*mGridSpacingY; +} + + +/* + Return Y coordinate corresponding to time. Coordinates are rounded to fit into + the grid. +*/ +int KOAgenda::timeToY(const QTime &time) +{ + int minutesPerCell = 24 * 60 / mRows; + int timeMinutes = time.hour() * 60 + time.minute(); + int Y = (timeMinutes + (minutesPerCell / 2)) / minutesPerCell; + return Y; +} + + +/* + Return time corresponding to cell y coordinate. Coordinates are rounded to + fit into the grid. +*/ +QTime KOAgenda::gyToTime(int gy) +{ + + int secondsPerCell = 24 * 60 * 60/ mRows; + + int timeSeconds = secondsPerCell * gy; + + QTime time( 0, 0, 0 ); + if ( timeSeconds < 24 * 60 * 60 ) { + time = time.addSecs(timeSeconds); + } else { + time.setHMS( 23, 59, 59 ); + } + + return time; +} + +void KOAgenda::setStartHour(int startHour) +{ + int startCell = startHour * mRows / 24; + setContentsPos(0,startCell * gridSpacingY()); +} +void KOAgenda::hideUnused() +{ + // experimental only + // return; + KOAgendaItem *item; + for ( item=mUnusedItems.first(); item != 0; item=mUnusedItems.next() ) { + item->hide(); + } +} + + +KOAgendaItem *KOAgenda::getNewItem(Incidence * event,QDate qd, QWidget* view) +{ + + KOAgendaItem *fi; + for ( fi=mUnusedItems.first(); fi != 0; fi=mUnusedItems.next() ) { + if ( fi->incidence() == event ) { + mUnusedItems.remove(); + fi->init( event, qd ); + return fi; + } + } + fi=mUnusedItems.first(); + if ( fi ) { + mUnusedItems.remove(); + fi->init( event, qd ); + return fi; + } + // qDebug("new KOAgendaItem "); + + KOAgendaItem* agendaItem = new KOAgendaItem( event, qd, view, mAllDayMode ); + agendaItem->installEventFilter(this); + addChild(agendaItem,0,0); + return agendaItem; +} +KOAgendaItem * KOAgenda::getItemForTodo ( Todo * todo ) +{ + KOAgendaItem *item; + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + if ( item->incidence() == todo ) { + mItems.remove(); + return item; + } + } + return 0; +} + + +void KOAgenda::updateTodo( Todo * todo, int days, bool remove) +{ + + KOAgendaItem *item; + item = getItemForTodo ( todo ); + //qDebug("KOAgenda::updateTodo %d %d %d %d", this, todo, days, remove); + if ( item ) { + blockSignals( true ); + //qDebug("item found "); + item->hide(); + item->setCellX(-2, -1 ); + item->select(false); + mUnusedItems.append( item ); + mItems.remove( item ); + QPtrList<KOAgendaItem> oldconflictItems = item->conflictItems(); + KOAgendaItem *itemit; + //globalFlagBlockAgendaItemPaint = 1; + for ( itemit=oldconflictItems.first(); itemit != 0; + itemit=oldconflictItems.next() ) { + if ( itemit != item ) + placeSubCells(itemit); + } + qApp->processEvents(); + //globalFlagBlockAgendaItemPaint = 0; + for ( itemit=oldconflictItems.first(); itemit != 0; + itemit=oldconflictItems.next() ) { + globalFlagBlockAgendaItemUpdate = 0; + if ( itemit != item ) + itemit->repaintMe(); + globalFlagBlockAgendaItemUpdate = 1; + itemit->repaint(); + } + blockSignals( false ); + } + if ( remove ) { + //qDebug("remove****************************************** "); + return; + } + //qDebug("updateTodo+++++++++++++++++++++++++++++++++++++ "); + bool overdue = (!todo->isCompleted()) && (todo->dtDue() < QDate::currentDate())&& ( KOPrefs::instance()->mShowTodoInAgenda ); + QDate currentDate; + if ( overdue ) { + currentDate = QDate::currentDate(); + days += todo->dtDue().date().daysTo( currentDate ); + } + else + currentDate = todo->dtDue().date(); + + if ( todo->doesFloat() || overdue ) { + if ( ! mAllDayMode ) return; + // aldayagenda + globalFlagBlockAgendaItemPaint = 1; + item = insertAllDayItem(todo, currentDate,days, days); + item->show(); + + } + else { + if ( mAllDayMode ) return; + // mAgenda + globalFlagBlockAgendaItemPaint = 1; + int endY = timeToY(todo->dtDue().time()) - 1; + int hi = 12/KOPrefs::instance()->mHourSize; + int startY = endY - 1-hi; + item = insertItem(todo,currentDate,days,startY,endY); + item->show(); + } + qApp->processEvents(); + globalFlagBlockAgendaItemPaint = 0; + QPtrList<KOAgendaItem> oldconflictItems = item->conflictItems(); + KOAgendaItem *itemit; + for ( itemit=oldconflictItems.first(); itemit != 0; + itemit=oldconflictItems.next() ) { + globalFlagBlockAgendaItemUpdate = 0; + itemit->repaintMe(); + globalFlagBlockAgendaItemUpdate = 1; + itemit->repaint(); + } + globalFlagBlockAgendaItemUpdate = 0; + item->repaintMe(); + globalFlagBlockAgendaItemUpdate = 1; + item->repaint(); +} +/* + Insert KOAgendaItem into agenda. +*/ +KOAgendaItem *KOAgenda::insertItem (Incidence *event,QDate qd,int X,int YTop,int YBottom) +{ + //kdDebug() << "KOAgenda::insertItem:" << event->summary() << "-" << qd.toString() << " ;top, bottom:" << YTop << "," << YBottom << endl; + + if (mAllDayMode) { + kdDebug() << "KOAgenda: calling insertItem in all-day mode is illegal." << endl; + return 0; + } + + KOAgendaItem *agendaItem = getNewItem(event,qd,viewport()); + //agendaItem->setFrameStyle(WinPanel|Raised); + + int YSize = YBottom - YTop + 1; + if (YSize < 0) { + kdDebug() << "KOAgenda::insertItem(): Text: " << agendaItem->text() << " YSize<0" << endl; + YSize = 1; + } + int iheight = mGridSpacingY * YSize; + + agendaItem->resize(mGridSpacingX,iheight ); + agendaItem->setCellXY(X,YTop,YBottom); + agendaItem->setCellXWidth(X); + + //addChild(agendaItem,X*mGridSpacingX,YTop*mGridSpacingY); + mItems.append(agendaItem); + + placeSubCells(agendaItem); + + //agendaItem->show(); + + marcus_bains(); + + return agendaItem; +} + + +/* + Insert all-day KOAgendaItem into agenda. +*/ +KOAgendaItem *KOAgenda::insertAllDayItem (Incidence *event,QDate qd,int XBegin,int XEnd) +{ + if (!mAllDayMode) { + return 0; + } + + KOAgendaItem *agendaItem = getNewItem(event,qd,viewport()); + + agendaItem->setCellXY(XBegin,0,0); + agendaItem->setCellXWidth(XEnd); + agendaItem->resize(mGridSpacingX * agendaItem->cellWidth(),mGridSpacingY); + + //addChild(agendaItem,XBegin*mGridSpacingX,0); + mItems.append(agendaItem); + + placeSubCells(agendaItem); + + //agendaItem->show(); + + return agendaItem; +} + + +void KOAgenda::insertMultiItem (Event *event,QDate qd,int XBegin,int XEnd, + int YTop,int YBottom) +{ + if (mAllDayMode) { + ; + return; + } + + int cellX,cellYTop,cellYBottom; + QString newtext; + int width = XEnd - XBegin + 1; + int count = 0; + KOAgendaItem *current = 0; + QPtrList<KOAgendaItem> multiItems; + for (cellX = XBegin;cellX <= XEnd;++cellX) { + if (cellX == XBegin) cellYTop = YTop; + else cellYTop = 0; + if (cellX == XEnd) cellYBottom = YBottom; + else cellYBottom = rows() - 1; + newtext = QString("(%1/%2): ").arg(++count).arg(width); + newtext.append(event->summary()); + current = insertItem(event,qd,cellX,cellYTop,cellYBottom); + current->setText(newtext); + multiItems.append(current); + } + + KOAgendaItem *next = 0; + KOAgendaItem *last = multiItems.last(); + KOAgendaItem *first = multiItems.first(); + KOAgendaItem *setFirst,*setLast; + current = first; + while (current) { + next = multiItems.next(); + if (current == first) setFirst = 0; + else setFirst = first; + if (current == last) setLast = 0; + else setLast = last; + + current->setMultiItem(setFirst,next,setLast); + current = next; + } + + marcus_bains(); +} + + +//QSizePolicy KOAgenda::sizePolicy() const +//{ + // Thought this would make the all-day event agenda minimum size and the + // normal agenda take the remaining space. But it doesn´t work. The QSplitter + // don´t seem to think that an Expanding widget needs more space than a + // Preferred one. + // But it doesn´t hurt, so it stays. +// if (mAllDayMode) { +// return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); +// } else { +// return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); +// } +//} +void KOAgenda::finishResize ( ) +{ + //qDebug("finishResize+++++++++++++++++++++++++++++++ ( ) "); + if ( globalFlagBlockAgenda == 0 ) { + finishUpdate(); + //qDebug("finishUpdate() called "); + } +} +/* + Overridden from QScrollView to provide proper resizing of KOAgendaItems. +*/ +void KOAgenda::resizeEvent ( QResizeEvent *ev ) +{ + + mResizeTimer.start( 150 , true ); + computeSizes(); + return; + +} +void KOAgenda::computeSizes() +{ + if ( globalFlagBlockStartup ) + return; + + if (mAllDayMode) { + mGridSpacingX = (width()-3) / mColumns; + mGridSpacingY = height() - 2 * frameWidth() - 1; + resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY + 1); +// mGridSpacingY = height(); +// resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 ); + + KOAgendaItem *item; + int subCellWidth; + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + subCellWidth = mGridSpacingY / item->subCells(); + item->resize(mGridSpacingX * item->cellWidth(),subCellWidth); + moveChild(item,KOGlobals::self()->reverseLayout() ? + (mColumns - 1 - item->cellX()) * mGridSpacingX : + item->cellX() * mGridSpacingX, + item->subCell() * subCellWidth); + } + KOPrefs::instance()->mAllDaySize = mGridSpacingY; + } else { + mGridSpacingX = (width() - verticalScrollBar()->width()-3)/mColumns; + if (height() > mGridSpacingY * mRows + 1 ) { + KOPrefs::instance()->mHourSize = ((height())/mRows)+1; + mGridSpacingY = KOPrefs::instance()->mHourSize ; + resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 ); + emit resizedSignal(); + } else + resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY * mRows + 1 ); + KOAgendaItem *item; + int subCellWidth; + + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + subCellWidth = mGridSpacingX / item->subCells(); + item->resize(subCellWidth,item->height()); + moveChild(item,(KOGlobals::self()->reverseLayout() ? + (mColumns - 1 - item->cellX()) * mGridSpacingX : + item->cellX() * mGridSpacingX) + + item->subCell() * subCellWidth,childY(item)); + } + } + int cw = contentsWidth(); + int ch = contentsHeight(); + if ( mAllDayMode ) { + QPixmap* paintPixAll = KOAgendaItem::paintPixAllday(); + if ( paintPixAll->width() < cw || paintPixAll->height() < ch ) + paintPixAll->resize( cw, ch ); + } else { + QPixmap* paintPix = KOAgendaItem::paintPix(); + if ( paintPix->width() < cw || paintPix->height() < ch ) + KOAgendaItem::resizePixmap( cw , ch ); + } + + checkScrollBoundaries(); + marcus_bains(); + drawContentsToPainter(); + viewport()->repaint(false); +} + +void KOAgenda::scrollUp() +{ + scrollBy(0,-mScrollOffset); +} + + +void KOAgenda::scrollDown() +{ + scrollBy(0,mScrollOffset); +} + +void KOAgenda::popupAlarm() +{ + if (!mClickedItem) { + kdDebug() << "KOAgenda::popupAlarm() called without having a clicked item" << endl; + return; + } +// TODO: deal correctly with multiple alarms + Alarm* alarm; + QPtrList<Alarm> list(mClickedItem->incidence()->alarms()); + for(alarm=list.first();alarm;alarm=list.next()) { + alarm->toggleAlarm(); + } + emit itemModified( mClickedItem , KOGlobals::EVENTEDITED ); + mClickedItem->paintMe( true ); + mClickedItem->repaint( false ); +} + +/* + Calculates the minimum width +*/ +int KOAgenda::minimumWidth() const +{ + // TODO:: develop a way to dynamically determine the minimum width + int min = 100; + + return min; +} + +void KOAgenda::updateConfig() +{ + if ( viewport()->backgroundColor() != KOPrefs::instance()->mAgendaBgColor) + viewport()->setBackgroundColor(KOPrefs::instance()->mAgendaBgColor); + if ( mAllDayMode ) { + mGridSpacingY = height() - 1 ;// KOPrefs::instance()->mAllDaySize; + //mGridSpacingY = KOPrefs::instance()->mAllDaySize; + resizeContents( mGridSpacingX * mColumns + 1 , mGridSpacingY+1 ); + // setMaximumHeight( mGridSpacingY+1 ); + viewport()->repaint( false ); + //setFixedHeight( mGridSpacingY+1 ); + //qDebug("KOPrefs:aaaaa:instance()->mAllDaySize %d ", KOPrefs::instance()->mAllDaySize); + } + else { + mGridSpacingY = KOPrefs::instance()->mHourSize; + calculateWorkingHours(); + marcus_bains(); + } +} + +void KOAgenda::checkScrollBoundaries() +{ + // Invalidate old values to force update + mOldLowerScrollValue = -1; + mOldUpperScrollValue = -1; + + checkScrollBoundaries(verticalScrollBar()->value()); +} + +void KOAgenda::checkScrollBoundaries(int v) +{ + if ( mGridSpacingY == 0 ) + return; + int yMin = v/mGridSpacingY; + int yMax = (v+visibleHeight())/mGridSpacingY; + +// kdDebug() << "--- yMin: " << yMin << " yMax: " << yMax << endl; + + if (yMin != mOldLowerScrollValue) { + mOldLowerScrollValue = yMin; + emit lowerYChanged(yMin); + } + if (yMax != mOldUpperScrollValue) { + mOldUpperScrollValue = yMax; + emit upperYChanged(yMax); + } +} + +void KOAgenda::deselectItem() +{ + if (mSelectedItem.isNull()) return; + mSelectedItem->select(false); + mSelectedItem = 0; +} + +void KOAgenda::selectItem(KOAgendaItem *item) +{ + if ((KOAgendaItem *)mSelectedItem == item) return; + deselectItem(); + if (item == 0) { + emit incidenceSelected( 0 ); + return; + } + mSelectedItem = item; + mSelectedItem->select(); + emit incidenceSelected( mSelectedItem->incidence() ); +} + +// This function seems never be called. +void KOAgenda::keyPressEvent( QKeyEvent *kev ) +{ + switch(kev->key()) { + case Key_PageDown: + verticalScrollBar()->addPage(); + break; + case Key_PageUp: + verticalScrollBar()->subtractPage(); + break; + case Key_Down: + verticalScrollBar()->addLine(); + break; + case Key_Up: + verticalScrollBar()->subtractLine(); + break; + default: + ; + } +} + +void KOAgenda::calculateWorkingHours() +{ +// mWorkingHoursEnable = KOPrefs::instance()->mEnableWorkingHours; + mWorkingHoursEnable = !mAllDayMode; + + mWorkingHoursYTop = mGridSpacingY * + KOPrefs::instance()->mWorkingHoursStart * 4; + mWorkingHoursYBottom = mGridSpacingY * + KOPrefs::instance()->mWorkingHoursEnd * 4 - 1; +} + + +DateList KOAgenda::dateList() const +{ + return mSelectedDates; +} + +void KOAgenda::setDateList(const DateList &selectedDates) +{ + mSelectedDates = selectedDates; + marcus_bains(); +} + +void KOAgenda::setHolidayMask(QMemArray<bool> *mask) +{ + mHolidayMask = mask; + +/* + kdDebug() << "HolidayMask: "; + for(uint i=0;i<mask->count();++i) { + kdDebug() << (mask->at(i) ? "*" : "o"); + } + kdDebug() << endl; +*/ +} + +void KOAgenda::contentsMousePressEvent ( QMouseEvent *event ) +{ + + QScrollView::contentsMousePressEvent(event); +} + +void KOAgenda::storePosition() +{ + //mContentPosition + int max = mGridSpacingY*4*24; + if ( contentsY() < 5 && max > viewport()->height()*3/2 ) + mContentPosition = 0; + else if ( contentsY() + viewport()->height() > max - 5 && max > viewport()->height()*3/2) + mContentPosition = -1.0; + else + mContentPosition = ((float) max)/ ((float)(contentsY()+ ( viewport()->height()/2))); + //qDebug("mContentPosition %f %d %d %d",mContentPosition , max, contentsY() ,viewport()->height()); + +} +void KOAgenda::restorePosition() +{ + int posY; + int max = mGridSpacingY*4*24; + if ( mContentPosition < 0 ) + posY = max-viewport()->height(); + else + if ( mContentPosition == 0 ) + posY = 0; + else + posY = (max/mContentPosition)-(viewport()->height()/2); + setContentsPos (0, posY ); + //qDebug("posY %d hei %d", posY, max); + +} +void KOAgenda::moveChild( QWidget *w, int x , int y ) +{ + ++x; + QScrollView::moveChild( w, x , y ); +} +#include <qmessagebox.h> +#ifdef DESKTOP_VERSION +#include <qprinter.h> +#include <qpainter.h> +#include <qpaintdevicemetrics.h> + +#endif +void KOAgenda::printSelection() +{ +#ifdef DESKTOP_VERSION + if ( mStartCellY == mCurrentCellY ) { + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + i18n("Nothing selected!\n\nThis prints the full width of the Agenda view as you see it!\n\nTo determine the vertical range of the printing, please select\na vertical range (with the left mouse button down) in one column. "), + i18n("OK"), 0, 0, + 0, 1 ); + return; + } + + float dx, dy; + int x,y,w,h; + x= 0; + w= contentsWidth()+2; + // h= contentsHeight(); + y = mGridSpacingY*mStartCellY; + h = mGridSpacingY*(mCurrentCellY+1)-y+2; + + //return; + QPrinter* printer = new QPrinter(); + if ( !printer->setup()) { + delete printer; + return; + } + QPainter p( printer ); + QPaintDeviceMetrics m = QPaintDeviceMetrics ( printer ); + QString date = i18n("Date range: ")+KGlobal::locale()->formatDate( mSelectedDates.first() )+" - "+KGlobal::locale()->formatDate( mSelectedDates.last() ); + date += " --- printing time: " + KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(), true ); + int hei = p.boundingRect(0,0, 5, 5, Qt::AlignLeft, date ).height(); + // p.drawText( 0, 0, date ); + int offset = m.width()/8; + // compute the scale + dx = ((float) m.width()-offset) / (float)w; + dy = (float)(m.height() - ( 2 * hei )-offset ) / (float)h; + float scale; + // scale to fit the width or height of the paper + if ( dx < dy ) + scale = dx; + else + scale = dy; + // set the scale + p.drawText( offset* scale, offset* scale*3/4, date ); + + int selDay; + float widOffset = ((float) m.width()-offset) / ((float)(mSelectedDates.count())); + float startX = 1; + for ( selDay = 0; selDay < mSelectedDates.count(); ++selDay) + { + QString text = KGlobal::locale()->formatDate( mSelectedDates[selDay],true ); + p.setClipRect(offset* scale+startX , 0, widOffset-4, offset* scale+(2*hei* scale) ); + p.drawText( offset* scale+startX, (offset+hei)* scale, text ); + startX += widOffset; + + } + p.translate( offset* scale,offset* scale+ (-y * scale)+(2*hei* scale)); + p.scale( scale, scale ); + p.setClipRect( offset* scale, offset* scale+(2*hei* scale), w*scale, h*scale ); + // now printing with y offset: 2 hei + // p.translate( 0, -y*scale); + + drawContentsToPainter(&p, true ); + globalFlagBlockAgendaItemUpdate = false; + KOAgendaItem *item; + for ( item=mItems.first(); item != 0; item=mItems.next() ) { + item->select(false); + item->paintMe( false, &p ); + } + globalFlagBlockAgendaItemUpdate = true; + p.end(); + delete printer; +#else + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + i18n("Not supported \non PDA!\n"), + i18n("OK"), 0, 0, + 0, 1 ); +#endif +} diff --git a/korganizer/koagenda.h b/korganizer/koagenda.h new file mode 100644 index 0000000..111242f --- a/dev/null +++ b/korganizer/koagenda.h @@ -0,0 +1,286 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KOAGENDA_H +#define KOAGENDA_H + +#include <qscrollview.h> +#include <qtimer.h> +#include <qmemarray.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qguardedptr.h> + +#include "koagendaitem.h" + +class QPopupMenu; +class QTime; +class KConfig; +class QFrame; +class KOAgenda; +class KCal::Event; +class KCal::Todo; + +using namespace KCal; + +class MarcusBains : public QFrame { + Q_OBJECT + public: + MarcusBains(KOAgenda *agenda=0,const char *name=0); + virtual ~MarcusBains(); + + public slots: + void updateLocation(bool recalculate=false); + void updateLoc(); + + private: + int todayColumn(); + QTimer *minutes; + QLabel *mTimeBox; + KOAgenda *agenda; + QTime oldTime; + int oldToday; +}; + + +class KOAgenda : public QScrollView +{ + Q_OBJECT + public: + enum MouseActionType { NOP, MOVE, SELECT, + RESIZETOP, RESIZEBOTTOM, RESIZELEFT, RESIZERIGHT }; + + KOAgenda ( int columns, int rows, int columnSize, QWidget * parent=0, + const char * name=0, WFlags f=0 ); + KOAgenda ( int columns, QWidget * parent=0, + const char * name=0, WFlags f=0 ); + virtual ~KOAgenda(); + + Incidence *selectedIncidence() const; + QDate selectedIncidenceDate() const; + + virtual bool eventFilter ( QObject *, QEvent * ); + + void contentsToGrid (int x, int y, int& gx, int& gy); + void gridToContents (int gx, int gy, int& x, int& y); + + int timeToY (const QTime &time); + QTime gyToTime (int y); + + void setStartHour(int startHour); + + KOAgendaItem *insertItem (Incidence *event,QDate qd,int X,int YTop,int YBottom); + KOAgendaItem *insertAllDayItem (Incidence *event,QDate qd,int XBegin,int XEnd); + void insertMultiItem (Event *event,QDate qd,int XBegin,int XEnd, + int YTop,int YBottom); + + void changeColumns(int columns); + + int columns() { return mColumns; } + int rows() { return mRows; } + + int gridSpacingX() const { return mGridSpacingX; } + int gridSpacingY() const { return mGridSpacingY; } + +// virtual QSizePolicy sizePolicy() const; + + void clear(); + + void clearSelection(); + void hideUnused(); + + /** Calculates the minimum width */ + virtual int minimumWidth() const; + /** Update configuration from preference settings */ + void updateConfig(); + + void checkScrollBoundaries(); + + void setHolidayMask(QMemArray<bool> *); + void setDateList(const DateList &selectedDates); + DateList dateList() const; + void drawContentsToPainter( QPainter* paint = 0, bool backgroundOnly = false); + void finishUpdate(); + void printSelection(); + void storePosition(); + void restorePosition(); + + + public slots: + void moveChild( QWidget *, int, int ); + void scrollUp(); + void scrollDown(); + void updateTodo( Todo * t, int , bool ); + void popupAlarm(); + + void checkScrollBoundaries(int); + + /** Deselect selected items. This function does not emit any signals. */ + void deselectItem(); + /** Select item. If the argument is 0, the currently selected item gets + deselected. This function emits the itemSelected(bool) signal to inform + about selection/deseelction of events. */ + void selectItem(KOAgendaItem *); + void finishResize(); + + signals: + void newEventSignal(); + void newEventSignal(int gx,int gy); + void newEventSignal(int gxStart, int gyStart, int gxEnd, int gyEnd); + void newTimeSpanSignal(int gxStart, int gyStart, int gxEnd, int gyEnd); + void newStartSelectSignal(); + void showIncidenceSignal(Incidence *); + void editIncidenceSignal(Incidence *); + void deleteIncidenceSignal(Incidence *); + void showIncidencePopupSignal(Incidence *); + + void itemModified(KOAgendaItem *item, int ); + void incidenceSelected(Incidence *); + + void lowerYChanged(int); + void upperYChanged(int); + + void startDragSignal(Incidence *); + void addToCalSignal(Incidence *, Incidence *); + void resizedSignal(); + + protected: + QPainter mPixPainter; + QPixmap mPaintPixmap; + QPixmap mHighlightPixmap; + void drawContents(QPainter *p,int cx, int cy, int cw, int ch); + virtual void resizeEvent ( QResizeEvent * ); + + /** Handles mouse events. Called from eventFilter */ + virtual bool eventFilter_mouse ( QObject *, QMouseEvent * ); + + /** Start selecting time span. */ + void startSelectAction(QPoint viewportPos); + + /** Select time span. */ + void performSelectAction(QPoint viewportPos); + + /** Emd selecting time span. */ + void endSelectAction(); + + /** Start moving/resizing agenda item */ + void startItemAction(QPoint viewportPos); + + /** Move/resize agenda item */ + void performItemAction(QPoint viewportPos); + + /** End moving/resizing agenda item */ + void endItemAction(); + + /** Set cursor, when no item action is in progress */ + void setNoActionCursor(KOAgendaItem *moveItem,QPoint viewportPos); + + /** Place agenda item in agenda and adjust other cells if necessary */ + void placeSubCells(KOAgendaItem *placeItem); + + /** Process the keyevent, including the ignored keyevents of eventwidgets. + * Implements pgup/pgdn and cursor key navigation in the view. + */ + void keyPressEvent( QKeyEvent * ); + + void calculateWorkingHours(); + + virtual void contentsMousePressEvent ( QMouseEvent * ); + + private: + void init(); + void marcus_bains(); + bool mAllDayMode; + bool blockResize; + QTimer mResizeTimer; + double mContentPosition; + + // Width and height of agenda cells + int mGridSpacingX; + int mGridSpacingY; + + // size of border, where mouse action will resize the KOAgendaItem + int mResizeBorderWidth; + + // size of border, where mouse mve will cause a scroll of the agenda + int mScrollBorderWidth; + int mScrollDelay; + int mScrollOffset; + + QTimer mScrollUpTimer; + QTimer mScrollDownTimer; + + // Number of Columns/Rows of agenda grid + int mColumns; + int mRows; + + // Cells to store Move and Resize coordiantes + int mStartCellX; + int mStartCellY; + int mCurrentCellX; + int mCurrentCellY; + + // Working Hour coordiantes + bool mWorkingHoursEnable; + int mWorkingHoursYTop; + int mWorkingHoursYBottom; + + // Selection + int mSelectionCellX; + int mSelectionYTop; + int mSelectionHeight; + + // List of dates to be displayed + DateList mSelectedDates; + + // The KOAgendaItem, which has been right-clicked last + KOAgendaItem *mClickedItem; + + // The KOAgendaItem, which is being moved/resized + QGuardedPtr<KOAgendaItem> mActionItem; + + // Currently selected item + QGuardedPtr<KOAgendaItem> mSelectedItem; + + // The Marcus Bains Line widget. + MarcusBains *mMarcusBains; + void computeSizes(); + + MouseActionType mActionType; + + bool mItemMoved; + + // List of all Items contained in agenda + QPtrList<KOAgendaItem> mItems; + QPtrList<KOAgendaItem> mUnusedItems; + KOAgendaItem* getNewItem(Incidence * event,QDate qd, QWidget* viewport); + QPopupMenu *mItemPopup; // Right mouse button popup menu for KOAgendaItems + + int mOldLowerScrollValue; + int mOldUpperScrollValue; + KOAgendaItem * getItemForTodo ( Todo * todo ); + QMemArray<bool> *mHolidayMask; + int mCurPixWid; + int mCurPixHei; +}; + +#endif // KOAGENDA_H diff --git a/korganizer/koagenda.moc b/korganizer/koagenda.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koagenda.moc diff --git a/korganizer/koagendaitem.cpp b/korganizer/koagendaitem.cpp new file mode 100644 index 0000000..02fd33b --- a/dev/null +++ b/korganizer/koagendaitem.cpp @@ -0,0 +1,720 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <qlabel.h> +#include <qlayout.h> +#include <qhbox.h> +#include <qvbox.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <qdragobject.h> +#include <qdrawutil.h> +#include <qpainter.h> + +#include <kiconloader.h> +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#define AGENDA_ICON_SIZE 5 +#else +#define AGENDA_ICON_SIZE 7 +#endif +#include <libkcal/icaldrag.h> +#include <libkcal/vcaldrag.h> +#include <libkdepim/kincidenceformatter.h> +extern int globalFlagBlockAgenda; +extern int globalFlagBlockAgendaItemPaint; +extern int globalFlagBlockAgendaItemUpdate; + +#include "koprefs.h" + +#include "koagendaitem.h" +#include "koagendaitem.moc" + + +//-------------------------------------------------------------------------- + +QToolTipGroup *KOAgendaItem::mToolTipGroup = 0; + +//-------------------------------------------------------------------------- + +KOAgendaItem::KOAgendaItem(Incidence *incidence, QDate qd, QWidget *parent,bool allday, + const char *name,WFlags) : + QWidget(parent, name), mIncidence(incidence), mDate(qd) +{ +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( this, QPEApplication::RightOnHold ); +#endif + int wflags = getWFlags() |WRepaintNoErase;// WResizeNoErase + setWFlags ( wflags); + mAllDay = allday; + init ( incidence, qd ); + setMouseTracking(true); + //setAcceptDrops(true); + xPaintCoord = -1; + yPaintCoord = -1; +} + +void KOAgendaItem::init ( Incidence *incidence, QDate qd ) +{ + mIncidence = incidence; + mDate = qd; + mFirstMultiItem = 0; + mNextMultiItem = 0; + mLastMultiItem = 0; + computeText(); + + if ( (incidence->type() == "Todo") && + ( !((static_cast<Todo*>(incidence))->isCompleted()) && + ((static_cast<Todo*>(incidence))->dtDue().date() <= QDate::currentDate()) ) ) { + if ( (static_cast<Todo*>(incidence))->dtDue() < QDateTime::currentDateTime().date()) + mBackgroundColor = KOPrefs::instance()->mTodoOverdueColor ; + else + mBackgroundColor = KOPrefs::instance()->mTodoDueTodayColor; + } + else { + QStringList categories = mIncidence->categories(); + QString cat = categories.first(); + if (cat.isEmpty()) { + mBackgroundColor =KOPrefs::instance()->mEventColor; + } else { + mBackgroundColor = *KOPrefs::instance()->categoryColor(cat); + } + } + mColorGroup = QColorGroup( mBackgroundColor.light(), + mBackgroundColor.dark(),mBackgroundColor.light(), + mBackgroundColor.dark(),mBackgroundColor, black, mBackgroundColor) ; + setBackgroundColor( mBackgroundColor ); + + setCellXY(0,0,1); + setCellXWidth(0); + setSubCell(0); + setSubCells(1); + setMultiItem(0,0,0); + startMove(); + mSelected = true; + select(false); + QString tipText = mIncidence->summary(); + // QToolTip::add(this,tipText); + QWhatsThis::add(this,KIncidenceFormatter::instance()->getFormattedText( mIncidence )); + if ( !mIncidence->doesFloat() ) + if ( mIncidence->type() == "Event" ) { + if ( (static_cast<Event*>(mIncidence))->isMultiDay() ) { + tipText += "\n"+i18n("From: ")+mIncidence->dtStartStr(); + tipText += "\n"+i18n("To: ")+(static_cast<Event*>(mIncidence))->dtEndStr(); + } + else { + tipText += "\n"+i18n("Time: ")+mIncidence->dtStartTimeStr(); + tipText += " - "+(static_cast<Event*>(mIncidence))->dtEndTimeStr(); + } + } + else if ( mIncidence->type() == "Todo" ) { + tipText += "\n"+i18n("Due: ")+ (static_cast<Todo*>(mIncidence))->dtDueTimeStr(); + } + + if (!mIncidence->location().isEmpty()) { + tipText += "\n"+i18n("Location: ")+mIncidence->location(); + } + QToolTip::add(this,tipText,toolTipGroup(),""); + QFontMetrics fontinf(KOPrefs::instance()->mAgendaViewFont); + mFontPixelSize = fontinf.height();; + hide(); + xPaintCoord = -1; + yPaintCoord = -1; +} + + +KOAgendaItem::~KOAgendaItem() +{ + // qDebug("deleteKOAgendaItem::~KOAgendaItem( "); + +} + +void KOAgendaItem::recreateIncidence() +{ + Incidence* newInc = mIncidence->clone(); + newInc->recreate(); + if ( mIncidence->doesRecur() ) { + mIncidence->addExDate( mDate ); + newInc->recurrence()->unsetRecurs(); + int len = mIncidence->dtStart().secsTo( ((Event*)mIncidence)->dtEnd()); + QTime tim = mIncidence->dtStart().time(); + newInc->setDtStart( QDateTime(mDate, tim) ); + ((Event*)newInc)->setDtEnd( newInc->dtStart().addSecs( len ) ); + } + mIncidence = newInc; +} +bool KOAgendaItem::updateIcons(QPainter * p, bool horLayout) +{ + int size = AGENDA_ICON_SIZE; + + int yOff = 0; + int xOff = 0; + int x = pos().x() +3; + int y; + if ( mAllDay ) + y = pos().y()+3; + else + y = mCellYTop * ( height() / cellHeight() ) +3; + if (mIncidence->cancelled()) { + int xpos = xOff*( 1 +AGENDA_ICON_SIZE )+x; + int ypos = yOff*( 1 +AGENDA_ICON_SIZE)+y; + p->drawLine( xpos, ypos, xpos+AGENDA_ICON_SIZE-1, ypos+AGENDA_ICON_SIZE-1 ); + p->drawLine( xpos, ypos+AGENDA_ICON_SIZE-1, xpos+AGENDA_ICON_SIZE-1, ypos ); + if ( horLayout ) + ++xOff; + else + ++yOff; + } + if (mIncidence->isAlarmEnabled()) { + p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, red ); + if ( horLayout ) + ++xOff; + else + ++yOff; + } + if (mIncidence->recurrence()->doesRecur()) { + p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, blue ); + if ( horLayout ) + ++xOff; + else + ++yOff; + } + if (mIncidence->description().length() > 0) { + p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, darkGreen ); + if ( horLayout ) + ++xOff; + else + ++yOff; + } + if (mIncidence->isReadOnly()) { + p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, white ); + if ( horLayout ) + ++xOff; + else + ++yOff; + } + + if (mIncidence->attendeeCount()>0) { + + if (mIncidence->organizer() == KOPrefs::instance()->email()) { + p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, black ); + if ( horLayout ) + ++xOff; + else + ++yOff; + } else { + Attendee *me = mIncidence->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email()); + if (me!=0) { + + + } else { + p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, yellow ); + if ( horLayout ) + ++xOff; + else + ++yOff; + + } + p->fillRect ( xOff*( 1 +AGENDA_ICON_SIZE )+x, yOff*( 1 +AGENDA_ICON_SIZE)+y, AGENDA_ICON_SIZE, AGENDA_ICON_SIZE, darkYellow ); + if ( horLayout ) + ++xOff; + else + ++yOff; + + } + + } + return ( yOff || xOff ); +} + + +void KOAgendaItem::select(bool selected) +{ + //qDebug("select %d %d",firstMultiItem(), nextMultiItem() ); + if (mSelected == selected) return; + mSelected = selected; + if ( ! isVisible() ) + return; + if ( firstMultiItem() ) + firstMultiItem()->select( selected ); + if ( !firstMultiItem() && nextMultiItem() ) { + KOAgendaItem * placeItem = nextMultiItem(); + while ( placeItem ) { + placeItem->select( selected ); + placeItem = placeItem->nextMultiItem(); + } + } + globalFlagBlockAgendaItemUpdate = 0; + paintMe( selected ); + globalFlagBlockAgendaItemUpdate = 1; + repaint( false ); +} + + +/* + The eventFilter has to filter the mouse events of the agenda item childs. The + events are fed into the event handling method of KOAgendaItem. This allows the + KOAgenda to handle the KOAgendaItems by using an eventFilter. +*/ +bool KOAgendaItem::eventFilter ( QObject *object, QEvent *e ) +{ + if (e->type() == QEvent::MouseButtonPress || + e->type() == QEvent::MouseButtonDblClick || + e->type() == QEvent::MouseButtonRelease || + e->type() == QEvent::MouseMove) { + QMouseEvent *me = (QMouseEvent *)e; + QPoint itemPos = this->mapFromGlobal(((QWidget *)object)-> + mapToGlobal(me->pos())); + QMouseEvent returnEvent (e->type(),itemPos,me->button(),me->state()); + return event(&returnEvent); + } else { + return false; + } +} +void KOAgendaItem::repaintMe( ) +{ + paintMe ( mSelected ); +} +void KOAgendaItem::paintMe( bool selected, QPainter* paint ) +{ + if ( globalFlagBlockAgendaItemUpdate && ! selected) + return; + QPainter pa; + + if ( mSelected ) { + pa.begin( paintPixSel() ); + } else { + if ( mAllDay ) + pa.begin( paintPixAllday() ); + else + pa.begin( paintPix() ); + } + int x, yy, w, h; + float nfh; + x = pos().x(); w = width(); h = height (); + if ( mAllDay ) + yy = y(); + else + yy = mCellYTop * ( height() / cellHeight() ); + xPaintCoord= x; + yPaintCoord = yy; + wPaintCoord = width(); + hPaintCoord = height(); + //qDebug("paintMe %s %d %d %d %d",incidence()->summary().latin1(), x, yy, width(), height()); + if ( paint == 0 ) + paint = &pa; + bool horLayout = ( w < h ); + int maxhei = mFontPixelSize+4; + if ( horLayout ) + maxhei += AGENDA_ICON_SIZE -4; + bool small = ( h < maxhei ); + if ( ! small ) + paint->setFont(KOPrefs::instance()->mAgendaViewFont); + else { + QFont f = KOPrefs::instance()->mAgendaViewFont; + f.setBold( false ); + int fh = f.pointSize(); + nfh = (((float)height())/(float)(mFontPixelSize+4))*fh; + if ( nfh < 6 ) + nfh = 6; + f.setPointSize( nfh ); + paint->setFont(f); + } + paint->fillRect ( x, yy, w, h, mBackgroundColor ); + static const QPixmap completedPxmp = SmallIcon("greenhook16"); + static const QPixmap overduePxmp = SmallIcon("redcross16"); + if ( mIncidence->type() == "Todo" ) { + Todo* tempTodo = static_cast<Todo*>(mIncidence); + int xx = pos().x()+(width()-completedPxmp.width()-3 ); + int yyy = yy+3; + if ( tempTodo->isCompleted() ) + paint->drawPixmap ( xx, yyy, completedPxmp ); + else { + paint->drawPixmap ( xx, yyy, overduePxmp ); + + } + } + bool addIcon = false; + if ( ! small || w > 3 * h || h > 3* w ) + addIcon = updateIcons( paint, horLayout ); + + qDrawShadePanel (paint, x, yy, w, h, mColorGroup, selected , 2, 0); + //qDebug("draw rect %d %d %d %d ",x, yy, w, h ); + if ( ! small ) { + x += 3; yy += 3;w -= 6; h-= 5; + } else { + x += 2; yy += 1;w -= 4; h-= 4; + if ( nfh < 6.01 ) { + yy -= 2; + h += 4; + } + else + if ( nfh < h -2 ) + ++yy; + } + int align; +#ifndef DESKTOP_VERSION + align = ( AlignLeft|WordBreak|AlignTop); +#else + align = ( AlignLeft|BreakAnywhere|WordBreak|AlignTop); +#endif + if ( addIcon ) { + if ( ! horLayout ) { + x += AGENDA_ICON_SIZE+3; + w -= (AGENDA_ICON_SIZE+3); + } + else { + yy+= AGENDA_ICON_SIZE+2; + h -=(AGENDA_ICON_SIZE+3); + } + } + int colsum = mBackgroundColor.red() + mBackgroundColor.green() + mBackgroundColor.blue(); + if ( colsum < 250 ) + paint->setPen ( white); + if ( x < 0 ) { + w = w+x-3; + x = 3; + if ( w > parentWidget()->width() ){ + w = parentWidget()->width() - 6; +#ifndef DESKTOP_VERSION + align = ( AlignCenter|WordBreak); +#else + align = ( AlignCenter|BreakAnywhere|WordBreak); +#endif + + } + } + QRect dr; + paint->drawText ( x, yy, w, h, align, mDisplayedText, -1, &dr ); + if ( mIncidence->cancelled() ){ + if ( ! small ) { + QFontMetrics fm ( paint->font() ); + paint->drawLine(dr.left(), yy+fm.height()/2, dr.right()-2, yy+fm.height()/2); + } + + } + pa.end(); + +} +void KOAgendaItem::resizePixmap( int w , int h ) +{ + paintPix()->resize( w, h ); + paintPixSel()->resize( w, h ); + +} +QPixmap * KOAgendaItem::paintPix() +{ + static QPixmap* mPaintPix = 0; + if ( ! mPaintPix ) + mPaintPix = new QPixmap(); + return mPaintPix ; +} +QPixmap * KOAgendaItem::paintPixAllday() +{ + static QPixmap* mPaintPixA = 0; + if ( ! mPaintPixA ) + mPaintPixA = new QPixmap(); + return mPaintPixA ; +} +QPixmap * KOAgendaItem::paintPixSel() +{ + static QPixmap* mPaintPixSel = 0; + if ( ! mPaintPixSel ) + mPaintPixSel = new QPixmap(); + return mPaintPixSel ; +} +void KOAgendaItem::paintEvent ( QPaintEvent *e ) +{ + + if ( globalFlagBlockAgendaItemPaint ) + return; + if ( globalFlagBlockAgenda > 0 && globalFlagBlockAgenda < 5 ) + return; + int yy; + if ( mAllDay ) + yy = y(); + else + yy = mCellYTop * ( height() / cellHeight() ); + int xx = x(); + if ( xPaintCoord != xx || yPaintCoord != yy || + wPaintCoord != width() || hPaintCoord != height()) { + xPaintCoord= xx; + yPaintCoord = yy; + wPaintCoord = width(); + hPaintCoord = height(); + globalFlagBlockAgendaItemUpdate = 0; + paintMe( mSelected ); + //qDebug("calling paintMe "); + globalFlagBlockAgendaItemUpdate = 1; + } + int rx, ry, rw, rh; + rx = e->rect().x(); + ry = e->rect().y(); + rw = e->rect().width(); + rh = e->rect().height(); + //qDebug(" paintevent %s %d %d %d %d", mIncidence->summary().latin1(), x(), yy, width(), height()); + + QPixmap* paintFrom ; + if ( mSelected ) { + paintFrom = paintPixSel(); + } else { + if ( mAllDay ) + paintFrom = paintPixAllday(); + else + paintFrom = paintPix(); + } + bitBlt (this, rx, ry, paintFrom, x()+rx ,yPaintCoord+ry, rw, rh ,CopyROP); +} +void KOAgendaItem::computeText() +{ + mDisplayedText = mIncidence->summary(); + if ( (mIncidence->type() == "Todo") ) { + if ( static_cast<Todo*>(mIncidence)->dtDue().date() < QDate::currentDate() ) + mDisplayedText += i18n(" (") +KGlobal::locale()->formatDate((static_cast<Todo*>(mIncidence))->dtDue().date(), true)+")"; + else if ( !(mIncidence->doesFloat())) + mDisplayedText += i18n(" (") +KGlobal::locale()->formatTime((static_cast<Todo*>(mIncidence))->dtDue().time())+")"; + + + + } else { + if ( !(mIncidence->doesFloat())) + mDisplayedText += ": " +KGlobal::locale()->formatTime((static_cast<Event*>(mIncidence))->dtStart().time()) + "-" + KGlobal::locale()->formatTime((static_cast<Event*>(mIncidence))->dtEnd().time()) ; + + if ( mAllDay ) { + if ( mIncidence->dtStart().date().addDays(3) < mIncidence->dtEnd().date() ) { + mDisplayedText += ": " +KGlobal::locale()->formatDate((static_cast<Event*>(mIncidence))->dtStart().date(), true) + " - " + KGlobal::locale()->formatDate((static_cast<Event*>(mIncidence))->dtEnd().date(), true) ; + } + } + + } + + if ( !mIncidence->location().isEmpty() ) { + if ( mAllDay ) + mDisplayedText += " ("; + else + mDisplayedText += "\n("; + mDisplayedText += mIncidence->location() +")"; + } +} +void KOAgendaItem::updateItem() +{ + computeText(); + + //qDebug("KOAgendaItem:: updateItem() %s %d %d ",incidence()->summary().latin1(), x(), y()); + paintMe( mSelected ); + repaint( false); +} + +void KOAgendaItem::resizeEvent ( QResizeEvent *ev ) +{ + //qDebug("KOAgendaItem::resizeEvent %s ", mIncidence->summary().latin1()); + paintMe( mSelected ); + repaint( false ); +} + +/* + Return height of item in units of agenda cells +*/ +int KOAgendaItem::cellHeight() +{ + int ret = mCellYBottom - mCellYTop + 1; + if ( ret <= 0 ) { + ret = 1; + mCellYBottom = 0; + mCellYTop = 0; + } + return ret; +} + +/* + Return height of item in units of agenda cells +*/ +int KOAgendaItem::cellWidth() +{ + return mCellXWidth - mCellX + 1; +} + +void KOAgendaItem::setItemDate(QDate qd) +{ + mDate = qd; +} + +void KOAgendaItem::setCellXY(int X, int YTop, int YBottom) +{ + mCellX = X; + mCellYTop = YTop; + mCellYBottom = YBottom; +} + +void KOAgendaItem::setCellXWidth(int xwidth) +{ + mCellXWidth = xwidth; +} + +void KOAgendaItem::setCellX(int XLeft, int XRight) +{ + mCellX = XLeft; + mCellXWidth = XRight; +} + +void KOAgendaItem::setCellY(int YTop, int YBottom) +{ + mCellYTop = YTop; + mCellYBottom = YBottom; +} + +void KOAgendaItem::setSubCell(int subCell) +{ + mSubCell = subCell; +} + +void KOAgendaItem::setSubCells(int subCells) +{ + mSubCells = subCells; +} + +void KOAgendaItem::setMultiItem(KOAgendaItem *first,KOAgendaItem *next, + KOAgendaItem *last) +{ + mFirstMultiItem = first; + mNextMultiItem = next; + mLastMultiItem = last; +} + +void KOAgendaItem::startMove() +{ + mStartCellX = mCellX; + mStartCellXWidth = mCellXWidth; + mStartCellYTop = mCellYTop; + mStartCellYBottom = mCellYBottom; +} + +void KOAgendaItem::resetMove() +{ + mCellX = mStartCellX; + mCellXWidth = mStartCellXWidth; + mCellYTop = mStartCellYTop; + mCellYBottom = mStartCellYBottom; +} + +void KOAgendaItem::moveRelative(int dx, int dy) +{ + int newX = cellX() + dx; + int newXWidth = cellXWidth() + dx; + int newYTop = cellYTop() + dy; + int newYBottom = cellYBottom() + dy; + setCellXY(newX,newYTop,newYBottom); + setCellXWidth(newXWidth); +} + +void KOAgendaItem::expandTop(int dy) +{ + int newYTop = cellYTop() + dy; + int newYBottom = cellYBottom(); + if (newYTop > newYBottom) newYTop = newYBottom; + setCellY(newYTop, newYBottom); +} + +void KOAgendaItem::expandBottom(int dy) +{ + int newYTop = cellYTop(); + int newYBottom = cellYBottom() + dy; + if (newYBottom < newYTop) newYBottom = newYTop; + setCellY(newYTop, newYBottom); +} + +void KOAgendaItem::expandLeft(int dx) +{ + int newX = cellX() + dx; + int newXWidth = cellXWidth(); + if (newX > newXWidth) newX = newXWidth; + setCellX(newX,newXWidth); +} + +void KOAgendaItem::expandRight(int dx) +{ + int newX = cellX(); + int newXWidth = cellXWidth() + dx; + if (newXWidth < newX) newXWidth = newX; + setCellX(newX,newXWidth); +} + +QToolTipGroup *KOAgendaItem::toolTipGroup() +{ + if (!mToolTipGroup) mToolTipGroup = new QToolTipGroup(0); + return mToolTipGroup; +} + +void KOAgendaItem::dragEnterEvent( QDragEnterEvent *e ) +{ +#ifndef KORG_NODND + if ( ICalDrag::canDecode( e ) || VCalDrag::canDecode( e ) || + !QTextDrag::canDecode( e ) ) { + e->ignore(); + return; + } + e->accept(); +#endif +} + +void KOAgendaItem::dropEvent( QDropEvent *e ) +{ +#ifndef KORG_NODND + QString text; + if(QTextDrag::decode(e,text)) + { + kdDebug() << "Dropped : " << text << endl; + QStringList emails = QStringList::split(",",text); + for(QStringList::ConstIterator it = emails.begin();it!=emails.end();++it) { + kdDebug() << " Email: " << (*it) << endl; + int pos = (*it).find("<"); + QString name = (*it).left(pos); + QString email = (*it).mid(pos); + if (!email.isEmpty()) { + mIncidence->addAttendee(new Attendee(name,email)); + } + } + } +#endif +} + + +QPtrList<KOAgendaItem> KOAgendaItem::conflictItems() +{ + return mConflictItems; +} + +void KOAgendaItem::setConflictItems(QPtrList<KOAgendaItem> ci) +{ + mConflictItems = ci; + KOAgendaItem *item; + for ( item=mConflictItems.first(); item != 0; + item=mConflictItems.next() ) { + item->addConflictItem(this); + } +} + +void KOAgendaItem::addConflictItem(KOAgendaItem *ci) +{ + if (mConflictItems.find(ci)<0) + mConflictItems.append(ci); +} diff --git a/korganizer/koagendaitem.h b/korganizer/koagendaitem.h new file mode 100644 index 0000000..7321af2 --- a/dev/null +++ b/korganizer/koagendaitem.h @@ -0,0 +1,160 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef KOAGENDAITEM_H +#define KOAGENDAITEM_H + +#include <qframe.h> +#include <qlabel.h> +#include <qpixmap.h> +#include <qdatetime.h> +#include <qpalette.h> + +#include <libkcal/incidence.h> + +class QToolTipGroup; +class QDragEnterEvent; +class QDropEvent; + +using namespace KCal; + +/* + The KOAgendaItem has to make sure that it receives all mouse events, which are + to be used for dragging and resizing. That means it has to be installed as + eventfiler for its children, if it has children, and it has to pass mouse + events from the cildren to itself. See eventFilter(). +*/ +class KOAgendaItem : public QWidget +{ + Q_OBJECT + public: + KOAgendaItem(Incidence *incidence, QDate qd, QWidget *parent, bool allday, const char *name=0, + WFlags f=0 ); + ~KOAgendaItem(); + void init ( Incidence *incidence, QDate qd ); + int cellX() { return mCellX; } + int cellXWidth() { return mCellXWidth; } + int cellYTop() { return mCellYTop; } + int cellYBottom() { return mCellYBottom; } + int cellHeight(); + int cellWidth(); + int subCell() { return mSubCell; } + int subCells() { return mSubCells; } + + void setCellXY(int X, int YTop, int YBottom); + void setCellY(int YTop, int YBottom); + void setCellX(int XLeft, int XRight); + void setCellXWidth(int xwidth); + void setSubCell(int subCell); + void setSubCells(int subCells); + + /** Start movement */ + void startMove(); + /** Reset to original values */ + void resetMove(); + + void moveRelative(int dx,int dy); + void expandTop(int dy); + void expandBottom(int dy); + void expandLeft(int dx); + void expandRight(int dx); + int mLastMoveXPos; + + void setMultiItem(KOAgendaItem *first,KOAgendaItem *next, + KOAgendaItem *last); + KOAgendaItem *firstMultiItem() { return mFirstMultiItem; } + KOAgendaItem *nextMultiItem() { return mNextMultiItem; } + KOAgendaItem *lastMultiItem() { return mLastMultiItem; } + + Incidence *incidence() const { return mIncidence; } + QDate itemDate() { return mDate; } + + /** Update the date of this item's occurence (not in the event) */ + void setItemDate(QDate qd); + + void setText ( const QString & text ) { mDisplayedText = text; } + QString text () { return mDisplayedText; } + + virtual bool eventFilter ( QObject *, QEvent * ); + + static QToolTipGroup *toolTipGroup(); + + QPtrList<KOAgendaItem> conflictItems(); + void setConflictItems(QPtrList<KOAgendaItem>); + void addConflictItem(KOAgendaItem *ci); + void paintMe( bool, QPainter* painter = 0 ); + void repaintMe(); + static void resizePixmap( int, int ); + static QPixmap * paintPix(); + static QPixmap * paintPixSel(); + static QPixmap * paintPixAllday(); + void updateItem(); + void computeText(); + void recreateIncidence(); + public slots: + bool updateIcons( QPainter *, bool ); + void select(bool=true); + + protected: + void dragEnterEvent(QDragEnterEvent *e); + void dropEvent(QDropEvent *e); + void paintEvent ( QPaintEvent * ); + void resizeEvent ( QResizeEvent *ev ); + + private: + bool mAllDay; + int mCellX; + int mCellXWidth; + int mCellYTop,mCellYBottom; + int mSubCell; // subcell number of this item + int mSubCells; // Total number of subcells in cell of this item + int xPaintCoord; + int yPaintCoord; + int wPaintCoord; + int hPaintCoord; + // Variables to remember start position + int mStartCellX; + int mStartCellXWidth; + int mStartCellYTop,mStartCellYBottom; + int mLastMovePos; + + // Multi item pointers + KOAgendaItem *mFirstMultiItem; + KOAgendaItem *mNextMultiItem; + KOAgendaItem *mLastMultiItem; + + int mFontPixelSize; + Incidence *mIncidence; // corresponding event or todo + QDate mDate; //date this events occurs (for recurrence) + //void showIcon( QLabel*, int ); + //QLabel *mTodoIconLabel; + //QLabel *mItemLabel; + //QWidget *mIconBox; + //QLabel *mIconAlarm,*mIconRecur,*mIconReadonly; + //QLabel *mIconReply,*mIconGroup,*mIconOrganizer; + //QLabel *mIconMoreInfo; + static QToolTipGroup *mToolTipGroup; + + QColor mBackgroundColor; + QColorGroup mColorGroup; + QString mDisplayedText; + bool mSelected; + QPtrList<KOAgendaItem> mConflictItems; +}; + +#endif // KOAGENDAITEM_H diff --git a/korganizer/koagendaitem.moc b/korganizer/koagendaitem.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koagendaitem.moc diff --git a/korganizer/koagendaview.cpp b/korganizer/koagendaview.cpp new file mode 100644 index 0000000..9e057e4 --- a/dev/null +++ b/korganizer/koagendaview.cpp @@ -0,0 +1,1436 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qhbox.h> +#include <qvbox.h> +#include <qlabel.h> +#include <qframe.h> +#include <qlayout.h> +#ifndef KORG_NOSPLITTER +#include <qsplitter.h> +#endif +#include <qfont.h> +#include <qfontmetrics.h> +#include <qpopupmenu.h> +#include <qtooltip.h> +#include <qpainter.h> +#include <qpushbutton.h> +#include <qapplication.h> + +#include <kapplication.h> +#include <KDGanttMinimizeSplitter.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kconfig.h> +#include <kglobal.h> +#include "calendarview.h" +#include "koviewmanager.h" + +#include <libkcal/calendar.h> +#include <libkcal/icaldrag.h> +#include <libkcal/dndfactory.h> + +#include <kcalendarsystem.h> + +#include "koglobals.h" +#ifndef KORG_NOPLUGINS +#include "kocore.h" +#endif +#include "koprefs.h" +#include "koagenda.h" +#include "koagendaitem.h" +#ifndef KORG_NOPRINTER +#include "calprinter.h" +#endif + +#include "koagendaview.h" +#include "koagendaview.moc" + +//extern bool globalFlagBlockPainting; +extern int globalFlagBlockAgenda; +extern int globalFlagBlockStartup; +extern int globalFlagBlockAgendaItemPaint; +extern int globalFlagBlockAgendaItemUpdate; +extern int globalFlagBlockLabel; +using namespace KOrg; + +TimeLabels::TimeLabels(int rows,QWidget *parent,const char *name,WFlags f) : + QScrollView(parent,name,f) +{ + mRows = rows; + + setMinimumHeight( 20 ); + mCellHeight = KOPrefs::instance()->mHourSize*4; + + enableClipper(true); + + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); + + resizeContents(50,mRows * mCellHeight); + + viewport()->setBackgroundMode( PaletteBackground ); +} + +void TimeLabels::setCellHeight(int height) +{ + mCellHeight = height; +} + +/* + Optimization so that only the "dirty" portion of the scroll view + is redrawn. Unfortunately, this is not called by default paintEvent() method. +*/ +void TimeLabels::drawContents(QPainter *p,int cx, int cy, int cw, int ch) +{ + + // if ( globalFlagBlockAgenda ) + // return; + // bug: the parameters cx, cy, cw, ch are the areas that need to be + // redrawn, not the area of the widget. unfortunately, this + // code assumes the latter... + + // now, for a workaround... + // these two assignments fix the weird redraw bug + cx = contentsX() + 2; + cw = contentsWidth() - 2; + // end of workaround + + int cell = ((int)(cy/mCellHeight)); + int y = cell * mCellHeight; + QFontMetrics fm = fontMetrics(); + QString hour; + QString suffix; + QString fullTime; + int tW = fm.width("24:00i"); + + while (y < cy + ch) { + p->drawLine(cx,y,cx+tW,y); + hour.setNum(cell); + suffix = "am"; + + // handle 24h and am/pm time formats + if (KGlobal::locale()->use12Clock()) { + if (cell > 11) suffix = "pm"; + if (cell == 0) hour.setNum(12); + if (cell > 12) hour.setNum(cell - 12); + } else { + suffix = ":00"; + } + + // create string in format of "XX:XX" or "XXpm/am" + fullTime = hour + suffix; + + // center and draw the time label + int timeWidth = fm.width(fullTime+"i"); + int offset = this->width() - timeWidth; + int borderWidth = 5; + int timeHeight = fm.height(); + timeHeight = timeHeight + 2 - ( timeHeight / 4 ); + p->drawText(cx -borderWidth + offset, y+ timeHeight, fullTime); + + // increment indices + y += mCellHeight; + cell++; + } +} + +/** + Calculates the minimum width. +*/ +int TimeLabels::minimumWidth() const +{ + QFontMetrics fm = fontMetrics(); + + //TODO: calculate this value + int borderWidth = 4; + + // the maximum width possible + int width = fm.width("88:88x") + borderWidth; + + return width; +} + +/** updates widget's internal state */ +void TimeLabels::updateConfig() +{ + // set the font + // config->setGroup("Fonts"); + // QFont font = config->readFontEntry("TimeBar Font"); + setFont(KOPrefs::instance()->mTimeBarFont); + + // update geometry restrictions based on new settings + setFixedWidth(minimumWidth()); + + // update HourSize + mCellHeight = KOPrefs::instance()->mHourSize*4; + resizeContents(50,mRows * mCellHeight); +} + +/** update time label positions */ +void TimeLabels::positionChanged() +{ + int adjustment = mAgenda->contentsY(); + setContentsPos(0, adjustment); +} + +/** */ +void TimeLabels::setAgenda(KOAgenda* agenda) +{ + mAgenda = agenda; +} + + +/** This is called in response to repaint() */ +void TimeLabels::paintEvent(QPaintEvent*) +{ + + // kdDebug() << "paintevent..." << endl; + // this is another hack! + // QPainter painter(this); + //QString c + repaintContents(contentsX(), contentsY(), visibleWidth(), visibleHeight()); +} + +//////////////////////////////////////////////////////////////////////////// + +EventIndicator::EventIndicator(Location loc,QWidget *parent,const char *name) + : QFrame(parent,name) +{ + mColumns = 1; + mTopBox = 0; + mLocation = loc; + mTopLayout = 0; + mPaintWidget = 0; + mXOffset = 0; + if (mLocation == Top) mPixmap = SmallIcon("1uparrow"); + else mPixmap = SmallIcon("1downarrow"); + mEnabled.resize(mColumns); + if (mLocation == Top) + setMaximumHeight(0); + else + setMinimumHeight(mPixmap.height()); +} + +EventIndicator::~EventIndicator() +{ +} + +void EventIndicator::drawContents(QPainter *p) +{ + + // kdDebug() << "======== top: " << contentsRect().top() << " bottom " << // contentsRect().bottom() << " left " << contentsRect().left() << " right " << contentsRect().right() << endl; + KDGanttSplitterHandle* han = 0; + if ( mPaintWidget ) + han = mPaintWidget->firstHandle(); + if ( ! han ) { + int i; + for(i=0;i<mColumns;++i) { + if (mEnabled[i]) { + int cellWidth = contentsRect().right()/mColumns; + int xOffset = KOGlobals::self()->reverseLayout() ? + (mColumns - 1 - i)*cellWidth + cellWidth/2 -mPixmap.width()/2 : + i*cellWidth + cellWidth/2 -mPixmap.width()/2; + p->drawPixmap(QPoint(xOffset,0),mPixmap); + } + } + } else { + han->repaint(); + //mPaintWidget->setBackgroundColor( red ); + + QPainter pa( han ); + int i; + bool setColor = false; + for(i=0;i<mColumns;++i) { + if (mEnabled[i]) { + setColor = true; + + int cellWidth = contentsRect().right()/mColumns; + int xOffset = KOGlobals::self()->reverseLayout() ? + (mColumns - 1 - i)*cellWidth + cellWidth/2 -mPixmap.width()/2 : + i*cellWidth + cellWidth/2 -mPixmap.width()/2; + pa.drawPixmap(QPoint(mXOffset + xOffset,0),mPixmap); + //qDebug("222draw pix %d ",xOffset ); + + } + + } + pa.end(); + + } +} + +void EventIndicator::setXOffset( int x ) +{ + mXOffset = x; +} +void EventIndicator::setPaintWidget( KDGanttMinimizeSplitter * w ) +{ + mPaintWidget = w; +} +void EventIndicator::changeColumns(int columns) +{ + mColumns = columns; + mEnabled.resize(mColumns); + + update(); +} + +void EventIndicator::enableColumn(int column, bool enable) +{ + mEnabled[column] = enable; +} + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +KOAgendaView::KOAgendaView(Calendar *cal,QWidget *parent,const char *name) : + KOEventView (cal,parent,name) +{ + mBlockUpdating = true; + mStartHour = 8; + mSelectedDates.append(QDate::currentDate()); + + mLayoutDayLabels = 0; + mDayLabelsFrame = 0; + mDayLabels = 0; + bool isRTL = KOGlobals::self()->reverseLayout(); + + if ( KOPrefs::instance()->mVerticalScreen ) { + mExpandedPixmap = SmallIcon( "1downarrow" ); + mNotExpandedPixmap = SmallIcon( "1uparrow" ); + } else { + mExpandedPixmap = SmallIcon( isRTL ? "1leftarrow" : "1rightarrow" ); + mNotExpandedPixmap = SmallIcon( isRTL ? "1rightarrow" : "1leftarrow" ); + } + + QBoxLayout *topLayout = new QVBoxLayout(this); + + // Create day name labels for agenda columns + mDayLabelsFrame = new QHBox(this); + topLayout->addWidget(mDayLabelsFrame); + mDayLabels = new QFrame (mDayLabelsFrame); + mLayoutDayLabels = new QHBoxLayout(mDayLabels); + // Create agenda splitter +#ifndef KORG_NOSPLITTER + mSplitterAgenda = new QSplitter(Vertical,this); + topLayout->addWidget(mSplitterAgenda); + mSplitterAgenda->setOpaqueResize(); + + mAllDayFrame = new QHBox(mSplitterAgenda); + + QWidget *agendaFrame = new QWidget(mSplitterAgenda); +#else +#if 0 + QWidget *mainBox = new QWidget( this ); + topLayout->addWidget( mainBox ); + QBoxLayout *mainLayout = new QVBoxLayout(mainBox); + mAllDayFrame = new QHBox(mainBox); + mainLayout->addWidget(mAllDayFrame); + mainLayout->setStretchFactor( mAllDayFrame, 0 ); + mAllDayFrame->setFocusPolicy(NoFocus); + QWidget *agendaFrame = new QWidget(mainBox); + mainLayout->addWidget(agendaFrame); + mainLayout->setStretchFactor( agendaFrame, 10 ); + + agendaFrame->setFocusPolicy(NoFocus); +#endif + mSplitterAgenda = new KDGanttMinimizeSplitter( Qt::Vertical, this); + mSplitterAgenda->setMinimizeDirection ( KDGanttMinimizeSplitter::Up ); + topLayout->addWidget( mSplitterAgenda ); + mAllDayFrame = new QHBox(mSplitterAgenda); + mAllDayFrame->setFocusPolicy(NoFocus); + QWidget *agendaFrame = new QWidget(mSplitterAgenda); + agendaFrame->setFocusPolicy(NoFocus); + +#endif + + // Create all-day agenda widget + mDummyAllDayLeft = new QVBox( mAllDayFrame ); + + mExpandButton = new QPushButton(mDummyAllDayLeft); + mExpandButton->setPixmap( mNotExpandedPixmap ); + mExpandButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, + QSizePolicy::Fixed ) ); + connect( mExpandButton, SIGNAL( clicked() ), SIGNAL( toggleExpand() ) ); + mExpandButton->setFocusPolicy(NoFocus); + mAllDayAgenda = new KOAgenda(1,mAllDayFrame); + mAllDayAgenda->setFocusPolicy(NoFocus); + QWidget *dummyAllDayRight = new QWidget(mAllDayFrame); + + // Create event context menu for all day agenda + mAllDayAgendaPopup = eventPopup(); + connect(mAllDayAgenda,SIGNAL(showIncidencePopupSignal(Incidence *)), + mAllDayAgendaPopup,SLOT(showIncidencePopup(Incidence *))); + + // Create agenda frame + QGridLayout *agendaLayout = new QGridLayout(agendaFrame,3,3); + // QHBox *agendaFrame = new QHBox(splitterAgenda); + + // create event indicator bars + mEventIndicatorTop = new EventIndicator(EventIndicator::Top,agendaFrame); + agendaLayout->addWidget(mEventIndicatorTop,0,1); + mEventIndicatorTop->setPaintWidget( mSplitterAgenda ); + mEventIndicatorBottom = new EventIndicator(EventIndicator::Bottom, + agendaFrame); + agendaLayout->addWidget(mEventIndicatorBottom,2,1); + QWidget *dummyAgendaRight = new QWidget(agendaFrame); + agendaLayout->addWidget(dummyAgendaRight,0,2); + + // Create time labels + mTimeLabels = new TimeLabels(24,agendaFrame); + agendaLayout->addWidget(mTimeLabels,1,0); + + // Create agenda + mAgenda = new KOAgenda(1,96,KOPrefs::instance()->mHourSize,agendaFrame); + agendaLayout->addMultiCellWidget(mAgenda,1,1,1,2); + agendaLayout->setColStretch(1,1); + mAgenda->setFocusPolicy(NoFocus); + // Create event context menu for agenda + mAgendaPopup = eventPopup(); + + mAgendaPopup->addAdditionalItem(QIconSet(SmallIcon("bell")), + i18n("Toggle Alarm"),mAgenda, + SLOT(popupAlarm()),true); + + + connect(mAgenda,SIGNAL(showIncidencePopupSignal(Incidence *)), + mAgendaPopup,SLOT(showIncidencePopup(Incidence *))); + + // make connections between dependent widgets + mTimeLabels->setAgenda(mAgenda); + + // Update widgets to reflect user preferences + // updateConfig(); + + // createDayLabels(); + + // these blank widgets make the All Day Event box line up with the agenda + dummyAllDayRight->setFixedWidth(mAgenda->verticalScrollBar()->width()); + dummyAgendaRight->setFixedWidth(mAgenda->verticalScrollBar()->width()); + mDummyAllDayLeft->setFixedWidth(mTimeLabels->width()); + + // Scrolling + connect(mAgenda->verticalScrollBar(),SIGNAL(valueChanged(int)), + mTimeLabels, SLOT(positionChanged())); + connect(mTimeLabels->verticalScrollBar(),SIGNAL(valueChanged(int)), + SLOT(setContentsPos(int))); + + // Create/Show/Edit/Delete Event + connect(mAgenda,SIGNAL(newEventSignal(int,int)), + SLOT(newEvent(int,int))); + connect(mAgenda,SIGNAL(newEventSignal(int,int,int,int)), + SLOT(newEvent(int,int,int,int))); + connect(mAllDayAgenda,SIGNAL(newEventSignal(int,int)), + SLOT(newEventAllDay(int,int))); + connect(mAllDayAgenda,SIGNAL(newEventSignal(int,int,int,int)), + SLOT(newEventAllDay(int,int))); + connect(mAgenda,SIGNAL(newTimeSpanSignal(int,int,int,int)), + SLOT(newTimeSpanSelected(int,int,int,int))); + connect(mAllDayAgenda,SIGNAL(newTimeSpanSignal(int,int,int,int)), + SLOT(newTimeSpanSelectedAllDay(int,int,int,int))); + connect(mAgenda,SIGNAL(newStartSelectSignal()),SLOT(updateView())); + connect(mAllDayAgenda,SIGNAL(newStartSelectSignal()),SLOT(updateView())); + + connect(mAgenda,SIGNAL(editIncidenceSignal(Incidence *)), + SIGNAL(editIncidenceSignal(Incidence *))); + connect(mAllDayAgenda,SIGNAL(editIncidenceSignal(Incidence *)), + SIGNAL(editIncidenceSignal(Incidence *))); + connect(mAgenda,SIGNAL(showIncidenceSignal(Incidence *)), + SIGNAL(showIncidenceSignal(Incidence *))); + connect(mAllDayAgenda,SIGNAL(showIncidenceSignal(Incidence *)), + SIGNAL(showIncidenceSignal(Incidence *))); + connect(mAgenda,SIGNAL(deleteIncidenceSignal(Incidence *)), + SIGNAL(deleteIncidenceSignal(Incidence *))); + connect(mAllDayAgenda,SIGNAL(deleteIncidenceSignal(Incidence *)), + SIGNAL(deleteIncidenceSignal(Incidence *))); + + connect(mAgenda,SIGNAL(itemModified(KOAgendaItem *, int )), + SLOT(updateEventDates(KOAgendaItem *, int ))); + connect(mAllDayAgenda,SIGNAL(itemModified(KOAgendaItem *, int )), + SLOT(updateEventDates(KOAgendaItem *, int))); + + // event indicator update + connect(mAgenda,SIGNAL(lowerYChanged(int)), + SLOT(updateEventIndicatorTop(int))); + connect(mAgenda,SIGNAL(upperYChanged(int)), + SLOT(updateEventIndicatorBottom(int))); + // drag signals + /* + connect(mAgenda,SIGNAL(startDragSignal(Event *)), + SLOT(startDrag(Event *))); + connect(mAllDayAgenda,SIGNAL(startDragSignal(Event *)), + SLOT(startDrag(Event *))); + */ + // synchronize selections + connect( mAgenda, SIGNAL( incidenceSelected( Incidence * ) ), + mAllDayAgenda, SLOT( deselectItem() ) ); + connect( mAllDayAgenda, SIGNAL( incidenceSelected( Incidence * ) ), + mAgenda, SLOT( deselectItem() ) ); + connect( mAgenda, SIGNAL( incidenceSelected( Incidence * ) ), + SIGNAL( incidenceSelected( Incidence * ) ) ); + connect( mAllDayAgenda, SIGNAL( incidenceSelected( Incidence * ) ), + SIGNAL( incidenceSelected( Incidence * ) ) ); + connect( mAgenda, SIGNAL( resizedSignal() ), + SLOT( updateConfig( ) ) ); + connect( mAgenda, SIGNAL( addToCalSignal(Incidence *, Incidence *) ), + SLOT( addToCalSlot(Incidence *, Incidence * ) ) ); + connect( mAllDayAgenda, SIGNAL( addToCalSignal(Incidence * ,Incidence *) ), + SLOT( addToCalSlot(Incidence * , Incidence *) ) ); + // connect( mAgenda, SIGNAL( cloneIncidenceSignal(Incidence *) ), SIGNAL( cloneIncidenceSignal(Incidence *) ) ); + //connect( mAllDayAgenda, SIGNAL( cloneIncidenceSignal(Incidence *) ), SIGNAL( cloneIncidenceSignal(Incidence *) ) ); + + +} + +void KOAgendaView::toggleAllDay() +{ + if ( mSplitterAgenda->firstHandle() ) + mSplitterAgenda->firstHandle()->toggle(); +} +void KOAgendaView::addToCalSlot(Incidence * inc, Incidence * incOld ) +{ + calendar()->addIncidence( inc ); + + if ( incOld ) { + if ( incOld->type() == "Todo" ) + emit todoMoved((Todo*)incOld, KOGlobals::EVENTEDITED ); + else + emit incidenceChanged(incOld, KOGlobals::EVENTEDITED); + } + +} + +KOAgendaView::~KOAgendaView() +{ + delete mAgendaPopup; + delete mAllDayAgendaPopup; + delete KOAgendaItem::paintPix(); + delete KOAgendaItem::paintPixSel(); +} +void KOAgendaView::resizeEvent( QResizeEvent* e ) +{ + //qDebug("KOAgendaView::resizeEvent( QResizeEvent* e ) %d ", e->size().width()); + bool uc = false; + int ow = e->oldSize().width(); + int oh = e->oldSize().height(); + int w = e->size().width(); + int h = e->size().height(); + if ( (ow > oh && w< h ) || (ow < oh && w > h ) ) { + if ( ! mBlockUpdating && !globalFlagBlockStartup && !globalFlagBlockAgenda ) + uc = true; + //qDebug("view changed %d %d %d %d ", ow, oh , w , h); + } + mUpcomingWidth = e->size().width() ; + if ( mBlockUpdating || uc ) { + mBlockUpdating = false; + //mAgenda->setMinimumSize(800 , 600 ); + //qDebug("mAgenda->resize+++++++++++++++ "); + updateConfig(); + //qDebug("KOAgendaView::Updating now possible "); + } else + createDayLabels(); + //qDebug("resizeEvent end "); + +} +void KOAgendaView::createDayLabels() +{ + + if ( mBlockUpdating || globalFlagBlockLabel == 1) { + // qDebug(" KOAgendaView::createDayLabels() blocked "); + return; + + } + int newHight; + + // ### Before deleting and recreating we could check if mSelectedDates changed... + // It would remove some flickering and gain speed (since this is called by + // each updateView() call) + + int maxWid = mUpcomingWidth - mTimeLabels->width()- mAgenda->verticalScrollBar()->width() - 2; + mDayLabelsFrame->setMaximumWidth( mUpcomingWidth ); + if ( maxWid < 0 ) + maxWid = 20; + + QFont dlf = KOPrefs::instance()->mTimeLabelsFont; + QFontMetrics fm ( dlf ); + int selCount = mSelectedDates.count(); + QString dayTest = "Mon 20"; + int wid = fm.width( dayTest ); + maxWid -= ( selCount * 3 ); + if ( maxWid < 0 ) + maxWid = 20; + int needWid = wid * selCount; + //qDebug("++++++++Needed : %d MaxWidth: %d", needWid, maxWid ); + //if ( needWid > maxWid ) + // qDebug("DAYLABELS TOOOOOOO BIG "); + while ( needWid > maxWid ) { + dayTest = dayTest.left( dayTest.length() - 1 ); + wid = fm.width( dayTest ); + needWid = wid * selCount; + } + int maxLen = dayTest.length(); + int fontPoint = dlf.pointSize(); + if ( maxLen < 2 ) { + int fontPoint = dlf.pointSize(); + while ( fontPoint > 4 ) { + --fontPoint; + dlf.setPointSize( fontPoint ); + QFontMetrics f( dlf ); + wid = f.width( "20" ); + needWid = wid * selCount; + if ( needWid < maxWid ) + break; + } + maxLen = 2; + } + //qDebug("Max len %d ", dayTest.length() ); + + QFontMetrics tempF( dlf ); + newHight = tempF.height(); + mDayLabels->setFont( dlf ); + // mLayoutDayLabels = new QHBoxLayout(mDayLabels);; + // mLayoutDayLabels->addSpacing(mTimeLabels->width()); + //mLayoutDayLabels->addSpacing( 2 ); + // QFont lFont = dlf; + bool appendLabels = false; + QLabel *dayLabel; + dayLabel = mDayLabelsList.first(); + if ( !dayLabel ) { + appendLabels = true; + dayLabel = new QLabel(mDayLabels); + mDayLabelsList.append( dayLabel ); + mLayoutDayLabels->addWidget(dayLabel); + } + dayLabel->setFixedWidth( mTimeLabels->width()+2 ); + dayLabel->setFont( dlf ); + dayLabel->setAlignment(QLabel::AlignHCenter); + dayLabel->setText( KOGlobals::self()->calendarSystem()->monthName( mSelectedDates.first(), true ) ); + dayLabel->show(); + DateList::ConstIterator dit; + for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) { + QDate date = *dit; + // QBoxLayout *dayLayout = new QVBoxLayout(mLayoutDayLabels); + if ( ! appendLabels ) { + dayLabel = mDayLabelsList.next(); + if ( !dayLabel ) + appendLabels = true; + } + if ( appendLabels ) { + dayLabel = new QLabel(mDayLabels); + mDayLabelsList.append( dayLabel ); + mLayoutDayLabels->addWidget(dayLabel); + } + dayLabel->setMinimumWidth( 1 ); + dayLabel->setMaximumWidth( 2048 ); + dayLabel->setFont( dlf ); + dayLabel->show(); + QString str; + int dW = KOGlobals::self()->calendarSystem()->dayOfWeek(date); + QString dayName = KOGlobals::self()->calendarSystem()->weekDayName( dW, true ); + switch ( maxLen ) { + case 2: + str = QString::number( date.day() ); + break; + + case 3: + str = dayName.left( 1 ) +QString::number( date.day()); + + break; + case 4: + str = dayName.left( 1 ) + " " +QString::number( date.day()); + + break; + case 5: + str = dayName.left( 2 ) + " " +QString::number( date.day()); + + break; + case 6: + str = dayName.left( 3 ) + " " +QString::number( date.day()); + break; + + default: + break; + } + + dayLabel->setText(str); + dayLabel->setAlignment(QLabel::AlignHCenter); + if (date == QDate::currentDate()) { + QFont bFont = dlf; + bFont.setBold( true ); + dayLabel->setFont(bFont); + } + //dayLayout->addWidget(dayLabel); + +#ifndef KORG_NOPLUGINS + CalendarDecoration::List cds = KOCore::self()->calendarDecorations(); + CalendarDecoration *it; + for(it = cds.first(); it; it = cds.next()) { + QString text = it->shortText( date ); + if ( !text.isEmpty() ) { + QLabel *label = new QLabel(text,mDayLabels); + label->setAlignment(AlignCenter); + dayLayout->addWidget(label); + } + } + + for(it = cds.first(); it; it = cds.next()) { + QWidget *wid = it->smallWidget(mDayLabels,date); + if ( wid ) { + // wid->setHeight(20); + dayLayout->addWidget(wid); + } + } +#endif + } + if ( ! appendLabels ) { + dayLabel = mDayLabelsList.next(); + if ( !dayLabel ) + appendLabels = true; + } + if ( appendLabels ) { + dayLabel = new QLabel(mDayLabels); + mDayLabelsList.append( dayLabel ); + mLayoutDayLabels->addWidget(dayLabel); + } + //dayLabel->hide();//test only + + int offset = (mAgenda->width() - mAgenda->verticalScrollBar()->width()-3 ) % mSelectedDates.count() ; + if ( offset < 0 ) offset = 0; + //qDebug("mLayoutDayLabels->addSpacing %d ", mAgenda->verticalScrollBar()->width()+offset+2 ); + dayLabel->setText("");//QString::number ( mSelectedDates.first().month() ) ); + dayLabel->show(); + dayLabel->setFixedWidth( mAgenda->verticalScrollBar()->width()+ offset ); + //qDebug("setToFixed %d ", mAgenda->verticalScrollBar()->width()+ offset+2); + //mLayoutDayLabels->addSpacing(mAgenda->verticalScrollBar()->width()+ offset+2); + if ( !appendLabels ) { + dayLabel = mDayLabelsList.next(); + while ( dayLabel ) { + //qDebug("!dayLabel %d",dayLabel ); + dayLabel->hide(); + dayLabel = mDayLabelsList.next(); + } + } + //mDayLabelsFrame->show(); + //mDayLabels->show(); + //qDebug("heigt %d %d %d ",mDayLabelsFrame->height(), mDayLabelsFrame->sizeHint().height(), newHight); + //mDayLabelsFrame->resize( mAgenda->visibleWidth(), newHight ); + mDayLabelsFrame->setFixedHeight( newHight ); +} + +int KOAgendaView::maxDatesHint() +{ + // Not sure about the max number of events, so return 0 for now. + return 0; +} + +int KOAgendaView::currentDateCount() +{ + return mSelectedDates.count(); +} + +QPtrList<Incidence> KOAgendaView::selectedIncidences() +{ + QPtrList<Incidence> selected; + Incidence *incidence; + + incidence = mAgenda->selectedIncidence(); + if (incidence) selected.append(incidence); + + incidence = mAllDayAgenda->selectedIncidence(); + if (incidence) selected.append(incidence); + + return selected; +} + +DateList KOAgendaView::selectedDates() +{ + DateList selected; + QDate qd; + + qd = mAgenda->selectedIncidenceDate(); + if (qd.isValid()) selected.append(qd); + + qd = mAllDayAgenda->selectedIncidenceDate(); + if (qd.isValid()) selected.append(qd); + + return selected; +} + + +void KOAgendaView::updateView() +{ + if ( mBlockUpdating ) + return; + // kdDebug() << "KOAgendaView::updateView()" << endl; + fillAgenda(); + +} + + +/* + Update configuration settings for the agenda view. This method is not + complete. +*/ +void KOAgendaView::updateConfig() +{ + if ( mBlockUpdating ) + return; + // kdDebug() << "KOAgendaView::updateConfig()" << endl; + + // update config for children + mTimeLabels->updateConfig(); + mAgenda->storePosition(); + mAgenda->updateConfig(); + mAllDayAgenda->updateConfig(); + // widget synchronization + //TODO: find a better way, maybe signal/slot + mTimeLabels->positionChanged(); + + // for some reason, this needs to be called explicitly + mTimeLabels->repaint(); + + mDummyAllDayLeft->setFixedWidth(mTimeLabels->width()); + + // ToolTips displaying summary of events + KOAgendaItem::toolTipGroup()->setEnabled(KOPrefs::instance() + ->mEnableToolTips); + + //setHolidayMasks(); + + //createDayLabels(); called by via updateView(); + mEventIndicatorTop->setXOffset(mTimeLabels->width() + mAgenda->frameWidth()); + updateView(); + mAgenda->restorePosition(); +} + + +void KOAgendaView::updateEventDates(KOAgendaItem *item, int type) +{ + // kdDebug() << "KOAgendaView::updateEventDates(): " << item->text() << endl; + //qDebug("KOAgendaView::updateEventDates "); + QDateTime startDt,endDt; + QDate startDate; + int lenInSecs; + // if ( type == KOAgenda::RESIZETOP ) + // qDebug("RESIZETOP "); + // if ( type == KOAgenda::RESIZEBOTTOM ) + // qDebug("RESIZEBOTTOM "); + // if ( type == KOAgenda::MOVE ) + // qDebug("MOVE "); + if ( item->incidence()->type() == "Event" ) { + startDt =item->incidence()->dtStart(); + endDt = item->incidence()->dtEnd(); + lenInSecs = startDt.secsTo( endDt ); + } + + // emit incidenceItemChanged( item->incidence(), KOGlobals::EVENTEDITED ); + + if ( item->incidence()->type()=="Todo" && item->mLastMoveXPos > 0 ) { + startDate = mSelectedDates[item->mLastMoveXPos]; + } else { + if (item->cellX() < 0) { + startDate = (mSelectedDates.first()).addDays(item->cellX()); + } else { + startDate = mSelectedDates[item->cellX()]; + } + } + startDt.setDate(startDate); + + if (item->incidence()->doesFloat()) { + endDt.setDate(startDate.addDays(item->cellWidth() - 1)); + } else { + if ( type == KOAgenda::RESIZETOP || type == KOAgenda::MOVE ) + startDt.setTime(mAgenda->gyToTime(item->cellYTop())); + if ( item->incidence()->type() == "Event" ) { + if ( type == KOAgenda::MOVE ) { + endDt = startDt.addSecs(lenInSecs); + + } else if ( type == KOAgenda::RESIZEBOTTOM ) { + if (item->lastMultiItem()) { + endDt.setTime(mAgenda->gyToTime(item->lastMultiItem()->cellYBottom()+1)); + endDt.setDate(startDate. + addDays(item->lastMultiItem()->cellX() - item->cellX())); + } else { + endDt.setTime(mAgenda->gyToTime(item->cellYBottom()+1)); + endDt.setDate(startDate); + } + } + } else { + // todo + if (item->lastMultiItem()) { + endDt.setTime(mAgenda->gyToTime(item->lastMultiItem()->cellYBottom()+1)); + endDt.setDate(startDate. + addDays(item->lastMultiItem()->cellX() - item->cellX())); + } else { + //qDebug("tem->cellYBottom() %d",item->cellYBottom() ); + if ( item->cellYBottom() > 0 ) + endDt.setTime(mAgenda->gyToTime(item->cellYBottom()+1)); + else + endDt.setTime((static_cast<Todo*>(item->incidence()))->dtDue().time()); + endDt.setDate(startDate); + } + } + } + + + if ( item->incidence()->type() == "Event" ) { + item->incidence()->setDtStart(startDt); + (static_cast<Event*>(item->incidence()))->setDtEnd(endDt); + } else if ( item->incidence()->type() == "Todo" ) { + (static_cast<Todo*>(item->incidence()))->setDtDue(endDt); + } + //qDebug("KOAgendaView::updateEventDates stsart %s end %s ", startDt.toString().latin1(), endDt.toString().latin1() ); + item->incidence()->setRevision(item->incidence()->revision()+1); + item->setItemDate(startDt.date()); + //item->updateItem(); + if ( item->incidence()->type() == "Todo" ) { + emit todoMoved((Todo*)item->incidence(), KOGlobals::EVENTEDITED ); + + } + else + emit incidenceChanged(item->incidence(), KOGlobals::EVENTEDITED); + item->updateItem(); +} + +void KOAgendaView::showDates( const QDate &start, const QDate &end ) +{ + // kdDebug() << "KOAgendaView::selectDates" << endl; + + mSelectedDates.clear(); + // qDebug("KOAgendaView::showDates "); + QDate d = start; + while (d <= end) { + mSelectedDates.append(d); + d = d.addDays( 1 ); + } + + // and update the view + fillAgenda(); +} + + +void KOAgendaView::showEvents(QPtrList<Event>) +{ + kdDebug() << "KOAgendaView::showEvents() is not yet implemented" << endl; +} + +void KOAgendaView::changeEventDisplay(Event *, int) +{ + // qDebug("KOAgendaView::changeEventDisplay "); + // kdDebug() << "KOAgendaView::changeEventDisplay" << endl; + // this should be re-written to be MUCH smarter. Right now we + // are just playing dumb. + fillAgenda(); +} + +void KOAgendaView::fillAgenda(const QDate &) +{ + // qDebug("KOAgendaView::fillAgenda "); + fillAgenda(); +} + +void KOAgendaView::fillAgenda() +{ + if ( globalFlagBlockStartup ) + return; + if ( globalFlagBlockAgenda == 1 ) + return; + //if ( globalFlagBlockAgenda == 2 ) + //globalFlagBlockAgenda = 0; + // globalFlagBlockPainting = false; + if ( globalFlagBlockAgenda == 0 ) + globalFlagBlockAgenda = 1; + // clearView(); + //qDebug("fillAgenda()++++ "); + globalFlagBlockAgendaItemPaint = 1; + mAllDayAgenda->changeColumns(mSelectedDates.count()); + mAgenda->changeColumns(mSelectedDates.count()); + qApp->processEvents(); + mEventIndicatorTop->changeColumns(mSelectedDates.count()); + mEventIndicatorBottom->changeColumns(mSelectedDates.count()); + setHolidayMasks(); + + //mAgenda->hideUnused(); + //mAllDayAgenda->hideUnused(); + + // mAgenda->blockNextRepaint( false ); + // mAgenda->viewport()->repaint(); + // mAgenda->blockNextRepaint( true ); + mMinY.resize(mSelectedDates.count()); + mMaxY.resize(mSelectedDates.count()); + + QPtrList<Event> dayEvents; + + // ToDo items shall be displayed for the day they are due, but only showed today if they are already overdue. + // Therefore, get all of them. + QPtrList<Todo> todos = calendar()->todos(); + + mAgenda->setDateList(mSelectedDates); + + QDate today = QDate::currentDate(); + + DateList::ConstIterator dit; + int curCol = 0; + for( dit = mSelectedDates.begin(); dit != mSelectedDates.end(); ++dit ) { + QDate currentDate = *dit; + // kdDebug() << "KOAgendaView::fillAgenda(): " << currentDate.toString() + // << endl; + + dayEvents = calendar()->events(currentDate,true); + + // Default values, which can never be reached + mMinY[curCol] = mAgenda->timeToY(QTime(23,59)) + 1; + mMaxY[curCol] = mAgenda->timeToY(QTime(0,0)) - 1; + + unsigned int numEvent; + for(numEvent=0;numEvent<dayEvents.count();++numEvent) { + Event *event = dayEvents.at(numEvent); + if ( !KOPrefs::instance()->mShowSyncEvents && event->uid().left(21) == QString("last-syncEvent-device") ) + continue; + // kdDebug() << " Event: " << event->summary() << endl; + + int beginX = currentDate.daysTo(event->dtStart().date()) + curCol; + int endX = currentDate.daysTo(event->dtEnd().date()) + curCol; + + // kdDebug() << " beginX: " << beginX << " endX: " << endX << endl; + + if (event->doesFloat()) { + if (event->recurrence()->doesRecur()) { + mAllDayAgenda->insertAllDayItem(event,currentDate,curCol,curCol); + } else { + if (beginX <= 0 && curCol == 0) { + mAllDayAgenda->insertAllDayItem(event,currentDate,beginX,endX); + } else if (beginX == curCol) { + mAllDayAgenda->insertAllDayItem(event,currentDate,beginX,endX); + } + } + } else if (event->isMultiDay()) { + if ( event->doesRecur () ) { + QDate dateit = currentDate; + int count = 0; + int max = event->dtStart().daysTo( event->dtEnd() ) +2; + while (! event->recursOn( dateit ) && count <= max ) { + ++count; + dateit = dateit.addDays( -1 ); + } + bool ok; + QDateTime nextOcstart = event->getNextOccurence( QDateTime(dateit) ,&ok ); + if ( ok ) + { + int secs = event->dtStart().secsTo( event->dtEnd() ); + QDateTime nextOcend =nextOcstart.addSecs( secs ); ; + beginX = currentDate.daysTo(nextOcstart.date()) + curCol; + endX = currentDate.daysTo(nextOcend.date()) + curCol; + + } + } + int startY = mAgenda->timeToY(event->dtStart().time()); + int endY = mAgenda->timeToY(event->dtEnd().time()) - 1; + //qDebug("insert %d %d %d %d %d ",beginX,endX,startY,endY , curCol ); + if ((beginX <= 0 && curCol == 0) || beginX == curCol) { + //qDebug("insert!!! "); + mAgenda->insertMultiItem(event,currentDate,beginX,endX,startY,endY); + } + if (beginX == curCol) { + mMaxY[curCol] = mAgenda->timeToY(QTime(23,59)); + if (startY < mMinY[curCol]) mMinY[curCol] = startY; + } else if (endX == curCol) { + mMinY[curCol] = mAgenda->timeToY(QTime(0,0)); + if (endY > mMaxY[curCol]) mMaxY[curCol] = endY; + } else { + mMinY[curCol] = mAgenda->timeToY(QTime(0,0)); + mMaxY[curCol] = mAgenda->timeToY(QTime(23,59)); + } + } else { + int startY = mAgenda->timeToY(event->dtStart().time()); + int endY = mAgenda->timeToY(event->dtEnd().time()) - 1; + if (endY < startY) endY = startY; + mAgenda->insertItem(event,currentDate,curCol,startY,endY); + if (startY < mMinY[curCol]) mMinY[curCol] = startY; + if (endY > mMaxY[curCol]) mMaxY[curCol] = endY; + } + } + // ---------- [display Todos -------------- + unsigned int numTodo; + for (numTodo = 0; numTodo < todos.count(); ++numTodo) { + Todo *todo = todos.at(numTodo); + + if ( ! todo->hasDueDate() ) continue; // todo shall not be displayed if it has no date + + // ToDo items shall be displayed for the day they are due, but only showed today if they are already overdue. + // Already completed items can be displayed on their original due date + //if not KOPrefs::instance()->mShowTodoInAgenda, show overdue in agenda + bool overdue = (!todo->isCompleted()) && (todo->dtDue() < today) && KOPrefs::instance()->mShowTodoInAgenda; + + if ( ((todo->dtDue().date() == currentDate) && !overdue) || + ((currentDate == today) && overdue) ) { + if ( todo->doesFloat() || overdue ) { // Todo has no due-time set or is already overdue + if ( KOPrefs::instance()->mShowTodoInAgenda ) + mAllDayAgenda->insertAllDayItem(todo, currentDate, curCol, curCol); + } + else { + + int endY = mAgenda->timeToY(todo->dtDue().time()) - 1; + int hi = (18/KOPrefs::instance()->mHourSize); + //qDebug("hei %d ",KOPrefs::instance()->mHourSize); + int startY = endY -hi; + + mAgenda->insertItem(todo,currentDate,curCol,startY,endY); + + if (startY < mMinY[curCol]) mMinY[curCol] = startY; + if (endY > mMaxY[curCol]) mMaxY[curCol] = endY; + } + } + } + // ---------- display Todos] -------------- + + ++curCol; + } + mAgenda->hideUnused(); + mAllDayAgenda->hideUnused(); + mAgenda->checkScrollBoundaries(); + + deleteSelectedDateTime(); + + createDayLabels(); + emit incidenceSelected( 0 ); + + if ( globalFlagBlockAgenda == 2 ) { + if ( KOPrefs::instance()->mSetTimeToDayStartAt ) + setStartHour( KOPrefs::instance()->mDayBegins ); + else if ( KOPrefs::instance()->mCenterOnCurrentTime ) + setStartHour( QTime::currentTime ().hour() ); + // qApp->processEvents(); + } + qApp->processEvents(); + //qDebug("qApp->processEvents(); END "); + globalFlagBlockAgenda = 0; + + // mAgenda->hideUnused(); + //mAllDayAgenda->hideUnused(); + mAllDayAgenda->drawContentsToPainter(); + mAgenda->drawContentsToPainter(); + repaintAgenda(); + // mAgenda->finishUpdate(); + //mAllDayAgenda->finishUpdate(); + + // repaintAgenda(); + //qApp->processEvents(); + // globalFlagBlockAgenda = 0; +} +void KOAgendaView::repaintAgenda() +{ + // mAllDayAgenda->drawContentsToPainter(); +// mAllDayAgenda->viewport()->repaint( false ); +// mAgenda->drawContentsToPainter(); +// mAgenda->viewport()->repaint( false ); +// qApp->processEvents(); + + //qDebug("KOAgendaView::repaintAgenda() "); + //qApp->processEvents(); + mAgenda->viewport()->repaint( false ); + mAllDayAgenda->viewport()->repaint( false ); + mAgenda->finishUpdate(); + mAllDayAgenda->finishUpdate(); +} + + +void KOAgendaView::clearView() +{ + // kdDebug() << "ClearView" << endl; + mAllDayAgenda->clear(); + mAgenda->clear(); +} + +void KOAgendaView::printPreview(CalPrinter *calPrinter, const QDate &fd, + const QDate &td) +{ +#ifndef KORG_NOPRINTER + if (fd == td) + calPrinter->preview(CalPrinter::Day, fd, td); + else + calPrinter->preview(CalPrinter::Week, fd, td); +#endif +} + +// void KOAgendaView::updateMovedTodo() +// { +// // updateConfig(); +// // emit updateTodoViews(); +// } + +void KOAgendaView::newEvent(int gx, int gy) +{ + if (!mSelectedDates.count()) return; + + QDate day = mSelectedDates[gx]; + + QTime time = mAgenda->gyToTime(gy); + QDateTime dt(day,time); + // if ( dt < QDateTime::currentDateTime () ) + // dt = QDateTime::currentDateTime ().addSecs( 3600 ); + emit newEventSignal(dt); +} + +void KOAgendaView::newEvent(int gxStart, int gyStart, int gxEnd, int gyEnd) +{ + if (!mSelectedDates.count()) return; + + QDate dayStart = mSelectedDates[gxStart]; + QDate dayEnd = mSelectedDates[gxEnd]; + + QTime timeStart = mAgenda->gyToTime(gyStart); + QTime timeEnd = mAgenda->gyToTime( gyEnd + 1 ); + + QDateTime dtStart(dayStart,timeStart); + QDateTime dtEnd(dayEnd,timeEnd); + + emit newEventSignal(dtStart,dtEnd); +} + +void KOAgendaView::newEventAllDay(int gx, int ) +{ + if (!mSelectedDates.count()) return; + + QDate day = mSelectedDates[gx]; + + emit newEventSignal(day); +} + +void KOAgendaView::updateEventIndicatorTop(int newY) +{ + uint i; + for(i=0;i<mMinY.size();++i) { + if (newY >= mMinY.at(i)) mEventIndicatorTop->enableColumn(i,true); + else mEventIndicatorTop->enableColumn(i,false); + } + + mEventIndicatorTop->update(); +} + +void KOAgendaView::updateEventIndicatorBottom(int newY) +{ + uint i; + for(i=0;i<mMaxY.size();++i) { + if (newY <= mMaxY.at(i)) mEventIndicatorBottom->enableColumn(i,true); + else mEventIndicatorBottom->enableColumn(i,false); + } + + mEventIndicatorBottom->update(); +} + +void KOAgendaView::startDrag(Event *event) +{ +#ifndef KORG_NODND + DndFactory factory( calendar() ); + ICalDrag *vd = factory.createDrag(event,this); + if (vd->drag()) { + kdDebug() << "KOAgendaView::startDrag(): Delete drag source" << endl; + } +#endif +} + +void KOAgendaView::readSettings() +{ + readSettings(KOGlobals::config()); +} + +void KOAgendaView::readSettings(KConfig *config) +{ + // kdDebug() << "KOAgendaView::readSettings()" << endl; + + config->setGroup("Views"); + + //#ifndef KORG_NOSPLITTER + QValueList<int> sizes = config->readIntListEntry("Separator AgendaView"); + if (sizes.count() == 2) { + if ( sizes[0] < 20 ) { + sizes[1] = sizes[1] +20 - sizes[0]; + sizes[0] = 20; + } + mSplitterAgenda->setSizes(sizes); + // qDebug("read %d %d ",sizes[0],sizes[1] ); + } + //#endif + + // updateConfig(); +} + +void KOAgendaView::writeSettings(KConfig *config) +{ + // kdDebug() << "KOAgendaView::writeSettings()" << endl; + + config->setGroup("Views"); + + //#ifndef KORG_NOSPLITTER + QValueList<int> list = mSplitterAgenda->sizes(); + config->writeEntry("Separator AgendaView",list); + //qDebug("write %d %d ", list[0],list[1] ); + //#endif +} + +void KOAgendaView::setHolidayMasks() +{ + mHolidayMask.resize(mSelectedDates.count()); + + uint i; + for(i=0;i<mSelectedDates.count();++i) { + QDate date = mSelectedDates[i]; + bool showSaturday = KOPrefs::instance()->mExcludeSaturdays && (date.dayOfWeek() == 6); + bool showSunday = KOPrefs::instance()->mExcludeHolidays && (date.dayOfWeek() == 7); +#ifndef KORG_NOPLUGINS + bool showHoliday = KOPrefs::instance()->mExcludeHolidays && + !KOCore::self()->holiday(date).isEmpty(); + bool showDay = showSaturday || showSunday || showHoliday; +#else + bool showDay = showSaturday || showSunday; +#endif + if (showDay) { + mHolidayMask.at(i) = true; + } else { + mHolidayMask.at(i) = false; + } + } + + mAgenda->setHolidayMask(&mHolidayMask); + mAllDayAgenda->setHolidayMask(&mHolidayMask); +} + +void KOAgendaView::setContentsPos(int y) +{ + mAgenda->setContentsPos(0,y); +} + +void KOAgendaView::setExpandedButton( bool expanded ) +{ + if ( expanded ) { + mExpandButton->setPixmap( mExpandedPixmap ); + } else { + mExpandButton->setPixmap( mNotExpandedPixmap ); + } +} + +void KOAgendaView::clearSelection() +{ + mAgenda->deselectItem(); + mAllDayAgenda->deselectItem(); +} + +void KOAgendaView::newTimeSpanSelectedAllDay(int gxStart, int gyStart, + int gxEnd, int gyEnd) +{ + mTimeSpanInAllDay = true; + newTimeSpanSelected(gxStart,gyStart,gxEnd,gyEnd); +} + + + + +void KOAgendaView::newTimeSpanSelected(int gxStart, int gyStart, + int gxEnd, int gyEnd) +{ + if (!mSelectedDates.count()) return; + + QDate dayStart = mSelectedDates[gxStart]; + QDate dayEnd = mSelectedDates[gxEnd]; + + QTime timeStart = mAgenda->gyToTime(gyStart); + QTime timeEnd = mAgenda->gyToTime( gyEnd + 1 ); + + QDateTime dtStart(dayStart,timeStart); + QDateTime dtEnd(dayEnd,timeEnd); + + mTimeSpanBegin = dtStart; + mTimeSpanEnd = dtEnd; + +} + +void KOAgendaView::deleteSelectedDateTime() +{ + mTimeSpanBegin.setDate(QDate()); + mTimeSpanEnd.setDate(QDate()); + mTimeSpanInAllDay = false; +} + +void KOAgendaView::keyPressEvent ( QKeyEvent * e ) +{ + e->ignore(); +} + +void KOAgendaView::scrollOneHourUp() +{ + + mAgenda->scrollBy ( 0, -mAgenda->contentsHeight () / 24 ); +} +void KOAgendaView::scrollOneHourDown() +{ + mAgenda->scrollBy ( 0, mAgenda->contentsHeight () / 24 ); +} + +void KOAgendaView::setStartHour( int h ) +{ + mAgenda->setStartHour( h ); + +} + +void KOAgendaView::updateTodo( Todo * t, int ) +{ + + bool remove = false; + bool removeAD = false; + if ( ! t->hasDueDate() ) { + remove = true; + removeAD = true; + } + else { + bool overdue = (!t->isCompleted()) && (t->dtDue() < QDate::currentDate()) && KOPrefs::instance()->mShowTodoInAgenda ; + if ( overdue && + QDate::currentDate() >= mSelectedDates.first() && + QDate::currentDate() <= mSelectedDates.last()) { + removeAD = false; + remove = true; + } + else { + if ( t->dtDue().date() < mSelectedDates.first() || + t->dtDue().date() > mSelectedDates.last() ) { + remove = true; + removeAD = true; + } else { + remove = t->doesFloat(); + removeAD = !remove; + } + } + } + int days = mSelectedDates.first().daysTo( t->dtDue().date() ); + // qDebug("daysto %d ", days ); + mAgenda->updateTodo( t , days, remove); + if ( KOPrefs::instance()->mShowTodoInAgenda ) + mAllDayAgenda->updateTodo( t , days, removeAD); + //qDebug("KOAgendaView::updateTodo( Todo *, int ) "); + +} diff --git a/korganizer/koagendaview.h b/korganizer/koagendaview.h new file mode 100644 index 0000000..0079253 --- a/dev/null +++ b/korganizer/koagendaview.h @@ -0,0 +1,252 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KOAGENDAVIEW_H +#define KOAGENDAVIEW_H + +#include <qscrollview.h> +#include <qdatetime.h> +#include <qlayout.h> +#ifndef DESKTOP_VERSION +#include <qksplitter.h> +#else +#include <qsplitter.h> +#endif +#include <qmemarray.h> + +#include "koeventview.h" + + +class QHBox; +class QFrame; +class QLabel; +class QPushButton; +class CalendarView; +class KOAgenda; +class KOAgendaItem; +class KConfig; +class KDGanttMinimizeSplitter; +class TimeLabels : public QScrollView { + Q_OBJECT + public: + TimeLabels(int rows,QWidget *parent=0,const char *name=0,WFlags f=0); + + void setCellHeight(int height); + + /** Calculates the minimum width */ + virtual int minimumWidth() const; + + /** updates widget's internal state */ + void updateConfig(); + + /** */ + void setAgenda(KOAgenda* agenda); + + /** */ + virtual void paintEvent(QPaintEvent* e); + + public slots: + /** update time label positions */ + void positionChanged(); + + protected: + void drawContents(QPainter *p,int cx, int cy, int cw, int ch); + + private: + int mRows; + int mCellHeight; + + /** */ + KOAgenda* mAgenda; +}; + +class EventIndicator : public QFrame { + Q_OBJECT + public: + enum Location { Top, Bottom }; + EventIndicator(Location loc=Top,QWidget *parent=0,const char *name=0); + virtual ~EventIndicator(); + + void changeColumns(int columns); + void setPaintWidget( KDGanttMinimizeSplitter* ); + void setXOffset( int ); + void enableColumn(int column, bool enable); + + protected: + void drawContents(QPainter *); + + private: + int mXOffset; + KDGanttMinimizeSplitter* mPaintWidget; + int mColumns; + QHBox *mTopBox; + QBoxLayout *mTopLayout; + Location mLocation; + QPixmap mPixmap; + QMemArray<bool> mEnabled; +}; + +/** + KOAgendaView is the agenda-like view used to display events in an one or + multi-day view. +*/ +class KOAgendaView : public KOEventView { + Q_OBJECT + public: + KOAgendaView(Calendar *cal,QWidget *parent = 0,const char *name = 0 ); + virtual ~KOAgendaView(); + void setStartHour( int ); + void toggleAllDay(); + + + /** Returns maximum number of days supported by the koagendaview */ + virtual int maxDatesHint(); + + /** Returns number of currently shown dates. */ + virtual int currentDateCount(); + + /** returns the currently selected events */ + virtual QPtrList<Incidence> selectedIncidences(); + + /** returns the currently selected events */ + virtual DateList selectedDates(); + + /** Remove all events from view */ + void clearView(); + KOAgenda *agenda() { return mAgenda;} + virtual void printPreview(CalPrinter *calPrinter, + const QDate &, const QDate &); + + /** start-datetime of selection */ + QDateTime selectionStart() {return mTimeSpanBegin;} + /** end-datetime of selection */ + QDateTime selectionEnd() {return mTimeSpanEnd;} + /** returns true if selection is for whole day */ + bool selectedIsAllDay() {return mTimeSpanInAllDay;} + /** make selected start/end invalid */ + void deleteSelectedDateTime(); + void repaintAgenda(); + public slots: + virtual void updateView(); + virtual void updateConfig(); + virtual void showDates(const QDate &start, const QDate &end); + virtual void showEvents(QPtrList<Event> eventList); + + void updateTodo( Todo *, int ); + void changeEventDisplay(Event *, int); + + void clearSelection(); + + void newEvent(int gx,int gy); + void newEvent(int gxStart, int gyStart, int gxEnd, int gyEnd); + void newEventAllDay(int gx, int gy); + + void startDrag(Event *); + + void readSettings(); + void readSettings(KConfig *); + void writeSettings(KConfig *); + + void setContentsPos(int y); + + void setExpandedButton( bool expanded ); + void scrollOneHourUp(); + void scrollOneHourDown(); + void addToCalSlot(Incidence *, Incidence *); + + signals: + void toggleExpand(); + void todoMoved( Todo *, int ); + void incidenceChanged(Incidence * , int ); + // void cloneIncidenceSignal(Incidence *); + + protected: + bool mBlockUpdating; + int mUpcomingWidth; + /** Fill agenda beginning with date startDate */ + void fillAgenda(const QDate &startDate); + void resizeEvent( QResizeEvent* e ); + /** Fill agenda using the current set value for the start date */ + void fillAgenda(); + + /** Create labels for the selected dates. */ + void createDayLabels(); + + /** + Set the masks on the agenda widgets indicating, which days are holidays. + */ + void setHolidayMasks(); + + protected slots: + /** Update event belonging to agenda item */ + void updateEventDates(KOAgendaItem *item, int mode = -1); + //void updateMovedTodo(); + + void updateEventIndicatorTop(int newY); + void updateEventIndicatorBottom(int newY); + + /** Updates data for selected timespan */ + void newTimeSpanSelected(int gxStart, int gyStart, int gxEnd, int gyEnd); + /** Updates data for selected timespan for all day event*/ + void newTimeSpanSelectedAllDay(int gxStart, int gyStart, int gxEnd, int gyEnd); + + private: + // view widgets + QFrame *mDayLabels; + QHBox *mDayLabelsFrame; + QBoxLayout *mLayoutDayLabels; + QFrame *mAllDayFrame; + KOAgenda *mAllDayAgenda; + KOAgenda *mAgenda; + TimeLabels *mTimeLabels; + QWidget *mDummyAllDayLeft; + + KDGanttMinimizeSplitter* mSplitterAgenda; + QPushButton *mExpandButton; + + DateList mSelectedDates; // List of dates to be displayed + int mViewType; + + bool mWeekStartsMonday; + int mStartHour; + + KOEventPopupMenu *mAgendaPopup; + KOEventPopupMenu *mAllDayAgendaPopup; + + EventIndicator *mEventIndicatorTop; + EventIndicator *mEventIndicatorBottom; + + QMemArray<int> mMinY; + QMemArray<int> mMaxY; + + QMemArray<bool> mHolidayMask; + + QPixmap mExpandedPixmap; + QPixmap mNotExpandedPixmap; + QPtrList<QLabel> mDayLabelsList; + QDateTime mTimeSpanBegin; + QDateTime mTimeSpanEnd; + bool mTimeSpanInAllDay; + void keyPressEvent ( QKeyEvent * e ); +}; + +#endif // KOAGENDAVIEW_H diff --git a/korganizer/koagendaview.moc b/korganizer/koagendaview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koagendaview.moc diff --git a/korganizer/kocounterdialog.cpp b/korganizer/kocounterdialog.cpp new file mode 100644 index 0000000..8a9ae44 --- a/dev/null +++ b/korganizer/kocounterdialog.cpp @@ -0,0 +1,66 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include <klocale.h> + +#include <libkcal/event.h> +#include "koeventviewer.h" + +#include "kocounterdialog.h" +#include "kocounterdialog.moc" + +KOCounterDialog::KOCounterDialog(QWidget *parent,const char *name) + : KDialogBase(parent,name,false,i18n("Counter-event Viewer"),User1|User2,User1, + false,i18n("Decline"),i18n("Accept")) +{ + mEventViewer = new KOEventViewer(this); + setMainWidget(mEventViewer); + + connect(this,SIGNAL(user1Clicked()),this,SLOT(slotCancel())); + connect(this,SIGNAL(user2Clicked()),this,SLOT(slotOk())); + + // TODO: Set a sensible size (based on the content?). + setMinimumSize(300,200); + resize(320,300); +} + +KOCounterDialog::~KOCounterDialog() +{ +} + +void KOCounterDialog::setEvent(Event *event) +{ + mEventViewer->setEvent(event); +} + +void KOCounterDialog::addEvent(Event *event) +{ + mEventViewer->addEvent(event); +} + +void KOCounterDialog::setTodo(Todo *event) +{ + mEventViewer->setTodo(event); +} + +void KOCounterDialog::addText(QString text) +{ + mEventViewer->addText(text); +} diff --git a/korganizer/kocounterdialog.h b/korganizer/kocounterdialog.h new file mode 100644 index 0000000..c8dcf45 --- a/dev/null +++ b/korganizer/kocounterdialog.h @@ -0,0 +1,50 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000, 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef KOCOUNTERDIALOG_H +#define KOCOUNTERDIALOG_H +// +// Viewer dialog for counter events. +// + +#include <qtextview.h> + +#include <kdialogbase.h> + +#include <libkcal/event.h> + +using namespace KCal; + +class KOEventViewer; + +class KOCounterDialog : public KDialogBase { + Q_OBJECT + public: + KOCounterDialog(QWidget *parent=0,const char *name=0); + virtual ~KOCounterDialog(); + + void setEvent(Event *event); + void addEvent(Event *event); + void setTodo(Todo *event); + void addText(QString text); + + private: + KOEventViewer *mEventViewer; +}; + +#endif diff --git a/korganizer/kocounterdialog.moc b/korganizer/kocounterdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kocounterdialog.moc diff --git a/korganizer/kodaymatrix.cpp b/korganizer/kodaymatrix.cpp new file mode 100644 index 0000000..779d67c --- a/dev/null +++ b/korganizer/kodaymatrix.cpp @@ -0,0 +1,597 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Eitzenberger Thomas <thomas.eitzenberger@siemens.at> + Parts of the source code have been copied from kdpdatebutton.cpp + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qevent.h> +#include <qpainter.h> +#include <qptrlist.h> + +#include <kglobal.h> +#include <kdebug.h> +#include <klocale.h> + +#include <libkcal/vcaldrag.h> +#include <libkcal/icaldrag.h> +#include <libkcal/dndfactory.h> +#include <libkcal/calendarresources.h> +#include <libkcal/resourcecalendar.h> +#include <kresources/resourceselectdialog.h> + +#include <kcalendarsystem.h> + +#ifndef KORG_NOPLUGINS +#include "kocore.h" +#endif +#include "koprefs.h" +#include "koglobals.h" + +#include "kodaymatrix.h" +#include "kodaymatrix.moc" + +// ============================================================================ +// D Y N A M I C T I P +// ============================================================================ + +DynamicTip::DynamicTip( QWidget * parent ) + : QToolTip( parent ) +{ + matrix = (KODayMatrix*)parent; +} + + +void DynamicTip::maybeTip( const QPoint &pos ) +{ + //calculate which cell of the matrix the mouse is in + QRect sz = matrix->frameRect(); + int dheight = sz.height()*7 / 42; + int dwidth = sz.width() / 7; + int row = pos.y()/dheight; + int col = pos.x()/dwidth; + + QRect rct(col*dwidth, row*dheight, dwidth, dheight); + +// kdDebug() << "DynamicTip::maybeTip matrix cell index [" << +// col << "][" << row << "] => " <<(col+row*7) << endl; + + //show holiday names only + QString str = matrix->getHolidayLabel(col+row*7); + if (str.isEmpty()) return; + tip(rct, str); +} + + +// ============================================================================ +// K O D A Y M A T R I X +// ============================================================================ + +const int KODayMatrix::NOSELECTION = -1000; +const int KODayMatrix::NUMDAYS = 42; + +KODayMatrix::KODayMatrix(QWidget *parent, Calendar* calendar, QDate date, const char *name) : + QFrame(parent, name) +{ + mCalendar = calendar; + + // initialize dynamic arrays + days = new QDate[NUMDAYS]; + daylbls = new QString[NUMDAYS]; + events = new int[NUMDAYS]; + mToolTip = new DynamicTip(this); + + // set default values used for drawing the matrix + mDefaultBackColor = palette().active().base(); + mDefaultTextColor = palette().active().foreground(); + mDefaultTextColorShaded = getShadedColor(mDefaultTextColor); + mHolidayColorShaded = getShadedColor(KOPrefs::instance()->mHolidayColor); + mSelectedDaysColor = QColor("white"); + mTodayMarginWidth = 2; + mSelEnd = mSelStart = NOSELECTION; + + setAcceptDrops(true); + //setFont( QFont("Arial", 10) ); + updateView(date); +} + +QColor KODayMatrix::getShadedColor(QColor color) +{ + QColor shaded; + int h=0; + int s=0; + int v=0; + color.hsv(&h,&s,&v); + s = s/4; + v = 192+v/4; + shaded.setHsv(h,s,v); + + return shaded; +} + +KODayMatrix::~KODayMatrix() +{ + delete [] days; + delete [] daylbls; + delete [] events; + delete mToolTip; +} + +/* +void KODayMatrix::setStartDate(QDate start) +{ + updateView(start); +} +*/ + +void KODayMatrix::addSelectedDaysTo(DateList& selDays) +{ + kdDebug() << "KODayMatrix::addSelectedDaysTo() - " << "mSelStart:" << mSelStart << endl; + + if (mSelStart == NOSELECTION) { + return; + } + + //cope with selection being out of matrix limits at top (< 0) + int i0 = mSelStart; + if (i0 < 0) { + for (int i = i0; i < 0; i++) { + selDays.append(days[0].addDays(i)); + } + i0 = 0; + } + + //cope with selection being out of matrix limits at bottom (> NUMDAYS-1) + if (mSelEnd > NUMDAYS-1) { + for (int i = i0; i <= NUMDAYS-1; i++) { + selDays.append(days[i]); + } + for (int i = NUMDAYS; i < mSelEnd; i++) { + selDays.append(days[0].addDays(i)); + } + + // apply normal routine to selection being entirely within matrix limits + } else { + for (int i = i0; i <= mSelEnd; i++) { + selDays.append(days[i]); + } + } +} + +void KODayMatrix::setSelectedDaysFrom(const QDate& start, const QDate& end) +{ + mSelStart = startdate.daysTo(start); + mSelEnd = startdate.daysTo(end); +} + + +void KODayMatrix::recalculateToday() +{ + today = -1; + for (int i=0; i<NUMDAYS; i++) { + days[i] = startdate.addDays(i); + daylbls[i] = QString::number( KOGlobals::self()->calendarSystem()->day( days[i] )); + + // if today is in the currently displayed month, hilight today + if (days[i].year() == QDate::currentDate().year() && + days[i].month() == QDate::currentDate().month() && + days[i].day() == QDate::currentDate().day()) { + today = i; + } + } + // qDebug(QString("Today is visible at %1.").arg(today)); +} + +void KODayMatrix::updateView() +{ + updateView(startdate); +} + +void KODayMatrix::updateView(QDate actdate) +{ + +// kdDebug() << "KODayMatrix::updateView() " << actdate.toString() << endl; + + //flag to indicate if the starting day of the matrix has changed by this call + bool daychanged = false; + // if a new startdate is to be set then apply Cornelius's calculation + // of the first day to be shown + if (actdate != startdate) { + // reset index of selection according to shift of starting date from startdate to actdate + if (mSelStart != NOSELECTION) { + int tmp = actdate.daysTo(startdate); + //kdDebug() << "Shift of Selection1: " << mSelStart << " - " << mSelEnd << " -> " << tmp << "(" << offset << ")" << endl; + // shift selection if new one would be visible at least partly ! + + if (mSelStart+tmp < NUMDAYS && mSelEnd+tmp >= 0) { + // nested if is required for next X display pushed from a different month - correction required + // otherwise, for month forward and backward, it must be avoided + if( mSelStart > NUMDAYS || mSelStart < 0 ) + mSelStart = mSelStart + tmp; + if( mSelEnd > NUMDAYS || mSelEnd < 0 ) + mSelEnd = mSelEnd + tmp; + } + } + + startdate = actdate; + daychanged = true; + } + + if (daychanged) { + recalculateToday(); + } + + for(int i = 0; i < NUMDAYS; i++) { + + // if events are set for the day then remember to draw it bold + QPtrList<Event> eventlist = mCalendar->events(days[i]); + Event *event; + int numEvents = eventlist.count(); + + for(event=eventlist.first();event != 0;event=eventlist.next()) { + ushort recurType = event->recurrence()->doesRecur(); + + if ((recurType == Recurrence::rDaily && !KOPrefs::instance()->mDailyRecur) || + (recurType == Recurrence::rWeekly && !KOPrefs::instance()->mWeeklyRecur)) { + numEvents--; + } + } + events[i] = numEvents; + + //if it is a holy day then draw it red. Sundays are consider holidays, too +#ifndef KORG_NOPLUGINS + QString holiStr = KOCore::self()->holiday(days[i]); +#else + QString holiStr = QString::null; +#endif + if ( (KOGlobals::self()->calendarSystem()->dayOfWeek(days[i]) == KOGlobals::self()->calendarSystem()->weekDayOfPray()) || + !holiStr.isEmpty()) { + if (holiStr.isNull()) holiStr = ""; + mHolidays[i] = holiStr; + + } else { + mHolidays[i] = QString::null; + } + } +} + +const QDate& KODayMatrix::getDate(int offset) +{ + if (offset < 0 || offset > NUMDAYS-1) { + kdDebug() << "Wrong offset (" << offset << ") in KODayMatrix::getDate(int)" << endl; + return days[0]; + } + return days[offset]; +} + +QString KODayMatrix::getHolidayLabel(int offset) +{ + if (offset < 0 || offset > NUMDAYS-1) { + kdDebug() << "Wrong offset (" << offset << ") in KODayMatrix::getHolidayLabel(int)" << endl; + return 0; + } + return mHolidays[offset]; +} + +int KODayMatrix::getDayIndexFrom(int x, int y) +{ + return 7*(y/daysize.height()) + (KOGlobals::self()->reverseLayout() ? + 6 - x/daysize.width() : x/daysize.width()); +} + +// ---------------------------------------------------------------------------- +// M O U S E E V E N T H A N D L I N G +// ---------------------------------------------------------------------------- + +void KODayMatrix::mousePressEvent (QMouseEvent* e) +{ + mSelStart = getDayIndexFrom(e->x(), e->y()); + if (mSelStart > NUMDAYS-1) mSelStart=NUMDAYS-1; + mSelInit = mSelStart; +} + +void KODayMatrix::mouseReleaseEvent (QMouseEvent* e) +{ + + int tmp = getDayIndexFrom(e->x(), e->y()); + if (tmp > NUMDAYS-1) tmp=NUMDAYS-1; + + if (mSelInit > tmp) { + mSelEnd = mSelInit; + if (tmp != mSelStart) { + mSelStart = tmp; + repaint(); + } + } else { + mSelStart = mSelInit; + + //repaint only if selection has changed + if (tmp != mSelEnd) { + mSelEnd = tmp; + repaint(); + } + } + + DateList daylist; + if ( mSelStart < 0 ) + mSelStart = 0; + for (int i = mSelStart; i <= mSelEnd; i++) { + daylist.append(days[i]); + } + emit selected((const DateList)daylist); + +} + +void KODayMatrix::mouseMoveEvent (QMouseEvent* e) +{ + int tmp = getDayIndexFrom(e->x(), e->y()); + if (tmp > NUMDAYS-1) tmp=NUMDAYS-1; + + if (mSelInit > tmp) { + mSelEnd = mSelInit; + if (tmp != mSelStart) { + mSelStart = tmp; + repaint(); + } + } else { + mSelStart = mSelInit; + + //repaint only if selection has changed + if (tmp != mSelEnd) { + mSelEnd = tmp; + repaint(); + } + } +} + +// ---------------------------------------------------------------------------- +// D R A G ' N D R O P H A N D L I N G +// ---------------------------------------------------------------------------- + +void KODayMatrix::dragEnterEvent(QDragEnterEvent *e) +{ +#ifndef KORG_NODND + if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + // some visual feedback +// oldPalette = palette(); +// setPalette(my_HilitePalette); +// update(); +#endif +} + +void KODayMatrix::dragMoveEvent(QDragMoveEvent *e) +{ +#ifndef KORG_NODND + if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + e->accept(); +#endif +} + +void KODayMatrix::dragLeaveEvent(QDragLeaveEvent */*dl*/) +{ +#ifndef KORG_NODND +// setPalette(oldPalette); +// update(); +#endif +} + +void KODayMatrix::dropEvent(QDropEvent *e) +{ +#ifndef KORG_NODND +// kdDebug() << "KODayMatrix::dropEvent(e) begin" << endl; + + if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + DndFactory factory( mCalendar ); + Event *event = factory.createDrop(e); + + if (event) { + e->acceptAction(); + + Event *existingEvent = mCalendar->event(event->uid()); + + if(existingEvent) { + // uniquify event + event->recreate(); +/* + KMessageBox::sorry(this, + i18n("Event already exists in this calendar."), + i18n("Drop Event")); + delete event; + return; +*/ + } +// kdDebug() << "Drop new Event" << endl; + // Adjust date + QDateTime start = event->dtStart(); + QDateTime end = event->dtEnd(); + int duration = start.daysTo(end); + int idx = getDayIndexFrom(e->pos().x(), e->pos().y()); + + start.setDate(days[idx]); + end.setDate(days[idx].addDays(duration)); + + event->setDtStart(start); + event->setDtEnd(end); + mCalendar->addEvent(event); + + emit eventDropped(event); + } else { +// kdDebug() << "KODayMatrix::dropEvent(): Event from drop not decodable" << endl; + e->ignore(); + } +#endif +} + +// ---------------------------------------------------------------------------- +// P A I N T E V E N T H A N D L I N G +// ---------------------------------------------------------------------------- + +void KODayMatrix::paintEvent(QPaintEvent * pevent) +{ +//kdDebug() << "KODayMatrix::paintEvent() BEGIN" << endl; + + QPainter p(this); + + QRect sz = frameRect(); + int dheight = daysize.height(); + int dwidth = daysize.width(); + int row,col; + int selw, selh; + bool isRTL = KOGlobals::self()->reverseLayout(); + + // draw background and topleft frame + p.fillRect(pevent->rect(), mDefaultBackColor); + p.setPen(mDefaultTextColor); + p.drawRect(0, 0, sz.width()+1, sz.height()+1); + + // draw selected days with highlighted background color + if (mSelStart != NOSELECTION) { + + row = mSelStart/7; + col = mSelStart -row*7; + QColor selcol = KOPrefs::instance()->mHighlightColor; + + if (row == mSelEnd/7) { + // Single row selection + p.fillRect(isRTL ? (7 - (mSelEnd-mSelStart+1) - col)*dwidth : col*dwidth, + row*dheight, (mSelEnd-mSelStart+1)*dwidth, dheight, selcol); + } else { + // draw first row to the right + p.fillRect(isRTL ? 0 : col*dwidth, row*dheight, (7-col)*dwidth, + dheight, selcol); + // draw full block till last line + selh = mSelEnd/7-row; + if (selh > 1) { + p.fillRect(0, (row+1)*dheight, 7*dwidth, (selh-1)*dheight,selcol); + } + // draw last block from left to mSelEnd + selw = mSelEnd-7*(mSelEnd/7)+1; + p.fillRect(isRTL ? (7-selw)*dwidth : 0, (row+selh)*dheight, + selw*dwidth, dheight, selcol); + } + } + + // iterate over all days in the matrix and draw the day label in appropriate colors + QColor actcol = mDefaultTextColorShaded; + p.setPen(actcol); + QPen tmppen; + for(int i = 0; i < NUMDAYS; i++) { + row = i/7; + col = isRTL ? 6-(i-row*7) : i-row*7; + + // if it is the first day of a month switch color from normal to shaded and vice versa + if ( KOGlobals::self()->calendarSystem()->day( days[i] ) == 1) { + if (actcol == mDefaultTextColorShaded) { + actcol = mDefaultTextColor; + } else { + actcol = mDefaultTextColorShaded; + } + p.setPen(actcol); + } + + //Reset pen color after selected days block + if (i == mSelEnd+1) { + p.setPen(actcol); + } + + // if today then draw rectangle around day + if (today == i) { + tmppen = p.pen(); + QPen mTodayPen(p.pen()); + + mTodayPen.setWidth(mTodayMarginWidth); + //draw red rectangle for holidays + if (!mHolidays[i].isNull()) { + if (actcol == mDefaultTextColor) { + mTodayPen.setColor(KOPrefs::instance()->mHolidayColor); + } else { + mTodayPen.setColor(mHolidayColorShaded); + } + } + //draw gray rectangle for today if in selection + if (i >= mSelStart && i <= mSelEnd) { + QColor grey("grey"); + mTodayPen.setColor(grey); + } + p.setPen(mTodayPen); + p.drawRect(col*dwidth, row*dheight, dwidth, dheight); + p.setPen(tmppen); + } + + // if any events are on that day then draw it using a bold font + if (events[i] > 0) { + QFont myFont = font(); + myFont.setBold(true); + p.setFont(myFont); + } + + // if it is a holiday then use the default holiday color + if (!mHolidays[i].isNull()) { + if (actcol == mDefaultTextColor) { + p.setPen(KOPrefs::instance()->mHolidayColor); + } else { + p.setPen(mHolidayColorShaded); + } + } + + // draw selected days with special color + // DO NOT specially highlight holidays in selection ! + if (i >= mSelStart && i <= mSelEnd) { + p.setPen(mSelectedDaysColor); + } + + p.drawText(col*dwidth, row*dheight, dwidth, dheight, + Qt::AlignHCenter | Qt::AlignVCenter, daylbls[i]); + + // reset color to actual color + if (!mHolidays[i].isNull()) { + p.setPen(actcol); + } + // reset bold font to plain font + if (events[i] > 0) { + QFont myFont = font(); + myFont.setBold(false); + p.setFont(myFont); + } + } +} + +// ---------------------------------------------------------------------------- +// R E SI Z E E V E N T H A N D L I N G +// ---------------------------------------------------------------------------- + +void KODayMatrix::resizeEvent(QResizeEvent *) +{ + QRect sz = frameRect(); + daysize.setHeight(sz.height()*7 / NUMDAYS); + daysize.setWidth(sz.width() / 7); +} diff --git a/korganizer/kodaymatrix.h b/korganizer/kodaymatrix.h new file mode 100644 index 0000000..b4eb2a8 --- a/dev/null +++ b/korganizer/kodaymatrix.h @@ -0,0 +1,308 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Eitzenberger Thomas <thomas.eitzenberger@siemens.at> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KODAYMAT_H +#define _KODAYMAT_H + +#include <libkcal/calendar.h> + +#include <qstring.h> +#include <qframe.h> +#include <qcolor.h> +#include <qpen.h> +#include <qdatetime.h> +#include <qtooltip.h> + +#include <qmap.h> + +class QDragEnterEvent; +class QDragMoveEvent; +class QDragLeaveEvent; +class QDropEvent; + +class KODayMatrix; + +using namespace KCal; + + +/** + * small helper class to dynamically show tooltips inside the day matrix. + * This class asks the day matrix object for a appropriate label which + * is in our special case the name of the holiday or null if this day is no holiday. + */ +class DynamicTip : public QToolTip +{ +public: + + /** + * Constructor that expects a KODayMatrix object as parent. + * + * @param parent the parent KODayMatrix control. + */ + DynamicTip(QWidget* parent ); + +protected: + + /** + * Qt's callback to ask the object to provide an approrpiate text for the + * tooltip to be shown. + * + * @param pos coordinates of the mouse. + */ + void maybeTip( const QPoint & pos); + +private: + + /** the parent control this tooltip is designed for. */ + KODayMatrix* matrix; +}; + +/** + * replacement for kdpdatebuton.cpp that used 42 widgets for the day matrix to be displayed. + * Cornelius thought this was a waste of memory and a lot of overhead. + * In addition the selection was not very intuitive so I decided to rewrite it using a QFrame + * that draws the labels and allows for dragging selection while maintaining nearly full + * compatibility in behaviour with its predecessor. + * + * The following functionality has been changed: + * + * o when shifting events in the agenda view from one day to another the day matrix is updated now + * o TODO ET dragging an event to the matrix will MOVE not COPY the event to the new date. + * o no support for Ctrl+click to create groups of dates + * (This has not really been supported in the predecessor. It was not very intuitive nor was it + * user friendly.) + * This feature has been replaced with dragging a selection on the matrix. The matrix will + * automatically choose the appropriate selection (e.g. you are not any longer able to select + * two distinct groups of date selections as in the old class) + * o now that you can select more then a week it can happen that not all selected days are + * displayed in the matrix. However this is preferred to the alternative which would mean to + * adjust the selection and leave some days undisplayed while scrolling through the months + * + * @short day matrix widget of the KDateNavigator + * + * @author Eitzenberger Thomas + */ +class KODayMatrix: public QFrame { + + Q_OBJECT + +public: + + /** constructor to create a day matrix widget. + * + * @param parent widget that is the parent of the day matrix. Normally this should + * be a KDateNavigator + * @param calendar instance of a calendar on which all calculations are based + * @param date start date of the matrix (is expected to be already fixed). It is + * assumed that this date is the first week day to be shown in the matrix. + * @param name name of the widget + */ + KODayMatrix(QWidget *parent, Calendar* calendar, QDate date, const char *name ); + + /** destructor that deallocates all dynamically allocated private members. + */ + ~KODayMatrix(); + + /** updates the day matrix to start with the given date. Does all the necessary + * checks for holidays or events on a day and stores them for display later on. + * Does NOT update the view visually. Call repaint() for this. + * + * @param actdate recalculates the day matrix to show NUMDAYS starting from this + * date. + */ + void updateView(QDate actdate); + + /** returns the QDate object associated with day indexed by the + * supplied offset. + */ + const QDate& getDate(int offset); + + /** returns the official name of this holy day or 0 if there is no label + * for this day. + */ + QString getHolidayLabel(int offset); + + /** adds all actual selected days from mSelStart to mSelEnd to the supplied + * DateList. + */ + void addSelectedDaysTo(DateList&); + + /** sets the actual to be displayed selection in the day matrix starting from + * start and ending with end. Theview must be manually updated by calling + * repaint. (?) + */ + void setSelectedDaysFrom(const QDate& start, const QDate& end); + + + /** Is today visible in the view? Keep this in sync with + * the values today (below) can take. + */ + bool isTodayVisible() const { return today>=0; } ; + + /** If today is visible, then we can find out if today is + * near the beginning or the end of the month. + * This is dependent on today remaining the index + * in the array of visible dates and going from + * top left (0) to bottom right (41). + */ + bool isBeginningOfMonth() const { return today<=8; } ; + bool isEndOfMonth() const { return today>=27; } ; + +public slots: + /** Recalculates all the flags of the days in the matrix like holidays or events + * on a day (Actually calls above method with the actual startdate). + */ + void updateView(); + + /** + * Calculate which square in the matrix should be + * hilighted to indicate it's today. + */ + void recalculateToday(); + +/* + void setStartDate(QDate); +*/ + +signals: + + /** emitted if the user selects a block of days with the mouse by dragging a rectangle + * inside the matrix + * + * @param daylist list of days that have been selected by the user + */ + void selected( const KCal::DateList &daylist ); + + /** emitted if the user has dropped an event inside the matrix + * + * @param event the dropped calendar event + */ + void eventDropped(Event *event); + +protected: + + void paintEvent(QPaintEvent *ev); + + void mousePressEvent (QMouseEvent* e); + + void mouseReleaseEvent (QMouseEvent* e); + + void mouseMoveEvent (QMouseEvent* e); + + void dragEnterEvent(QDragEnterEvent *); + + void dragMoveEvent(QDragMoveEvent *); + + void dragLeaveEvent(QDragLeaveEvent *); + + void dropEvent(QDropEvent *); + + void resizeEvent(QResizeEvent *); + +private: + + /** returns the index of the day located at the matrix's widget (x,y) position. + * + * @param x horizontal coordinate + * @param y vertical coordinate + */ + int getDayIndexFrom(int x, int y); + + /** calculates a "shaded" color from the supplied color object. + * (Copied from Cornelius's kdpdatebutton.cpp) + * + * @param color source based on which a shaded color should be calculated. + */ + QColor getShadedColor(QColor color); + + /** number of days to be displayed. For now there is no support for any other number then 42. + so change it at your own risk :o) */ + static const int NUMDAYS; + + /** calendar instance to be queried for holidays, events, ... */ + Calendar *mCalendar; + + /** starting date of the matrix */ + QDate startdate; + + /** array of day labels to optimeize drawing performance. */ + QString *daylbls; + + /** array of days displayed to reduce memory consumption by + subsequently calling QDate::addDays(). */ + QDate *days; + + /** array of storing the number of events on a given day. + * used for drawing a bold font if there is at least one event on that day. + */ + int *events; + + /** stores holiday names of the days shown in the matrix. */ + QMap<int,QString> mHolidays; + + /** indey of today or -1 if today is not visible in the matrix. */ + int today; + + /** index of day where dragged selection was initiated. + used to detect "negative" timely selections */ + int mSelInit; + + /** if mSelStart has this value it indicates that there is no + actual selection in the matrix. */ + static const int NOSELECTION; + + /** index of first selected day. */ + int mSelStart; + + /** index of last selected day. */ + int mSelEnd; + + /** dynamic tooltip to handle mouse dependent tips for each day in the matrix. */ + DynamicTip* mToolTip; + + + /** default background colour of the matrix. */ + QColor mDefaultBackColor; + + /** default text color of the matrix. */ + QColor mDefaultTextColor; + + /** default text color for days not in the actual month. */ + QColor mDefaultTextColorShaded; + + /** default text color for holidays not in the actual month. */ + QColor mHolidayColorShaded; + + /** text color for selected days. */ + QColor mSelectedDaysColor; + + /** default width of the frame drawn around today if it is visible in the matrix. */ + int mTodayMarginWidth; + + /** stores actual size of each day in the widget so that I dont need to ask this data + * on every repaint. + */ + QRect daysize; + +}; + +#endif diff --git a/korganizer/kodaymatrix.moc b/korganizer/kodaymatrix.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kodaymatrix.moc diff --git a/korganizer/kodialogmanager.cpp b/korganizer/kodialogmanager.cpp new file mode 100644 index 0000000..caf7599 --- a/dev/null +++ b/korganizer/kodialogmanager.cpp @@ -0,0 +1,343 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2001 + Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <libkdepim/categoryeditdialog.h> + +#include "calendarview.h" +#include "incomingdialog.h" +#include "outgoingdialog.h" +#include "koprefsdialog.h" +#include "koeventeditor.h" +#include "koprefs.h" +#include "datenavigator.h" +#include "kotodoeditor.h" +#include "searchdialog.h" +#include "filtereditdialog.h" +#ifndef KORG_NOPLUGINS +#include "plugindialog.h" +#endif +#ifndef KORG_NOARCHIVE +#include "archivedialog.h" +#endif + +#include "kconfig.h" +#include "kodialogmanager.h" +#include "kodialogmanager.moc" + +KODialogManager::KODialogManager( CalendarView *mainView ) : + QObject(), mMainView( mainView ) +{ + mOutgoingDialog = 0; + mIncomingDialog = 0; + mOptionsDialog = 0; + mSearchDialog = 0; + mArchiveDialog = 0; + mFilterEditDialog = 0; + mPluginDialog = 0; + + // mCategoryEditDialog = new KPIM::CategoryEditDialog(KOPrefs::instance(),mMainView); + //KOGlobals::fitDialogToScreen( mCategoryEditDialog ); +} + +KODialogManager::~KODialogManager() +{ + delete mOutgoingDialog; + delete mIncomingDialog; + delete mOptionsDialog; + delete mSearchDialog; +#ifndef KORG_NOARCHIVE + delete mArchiveDialog; +#endif + delete mFilterEditDialog; +#ifndef KORG_NOPLUGINS + delete mPluginDialog; +#endif +} + +OutgoingDialog *KODialogManager::outgoingDialog() +{ + createOutgoingDialog(); + return mOutgoingDialog; +} + +void KODialogManager::createOutgoingDialog() +{ + if (!mOutgoingDialog) { + mOutgoingDialog = new OutgoingDialog(mMainView->calendar(),mMainView); + if (mIncomingDialog) mIncomingDialog->setOutgoingDialog(mOutgoingDialog); + connect(mOutgoingDialog,SIGNAL(numMessagesChanged(int)), + mMainView,SIGNAL(numOutgoingChanged(int))); + } +} + +void KODialogManager::showOptionsDialog( bool showSync ) +{ + int curLanguage = KOPrefs::instance()->mPreferredLanguage; + if (!mOptionsDialog) { + mOptionsDialog = new KOPrefsDialog(mMainView); + //mOptionsDialog->readConfig(); + connect(mOptionsDialog,SIGNAL(configChanged()), + mMainView,SLOT(updateConfig())); + //connect(mCategoryEditDialog,SIGNAL(categoryConfigChanged()), + // mOptionsDialog,SLOT(updateCategories())); + + } + mOptionsDialog->readConfig(); +#ifndef DESKTOP_VERSION + mOptionsDialog->showMaximized(); +#else + mOptionsDialog->show(); +#endif + if ( showSync ) + mOptionsDialog->showSyncPage(); + mOptionsDialog->exec(); + if ( curLanguage != KOPrefs::instance()->mPreferredLanguage ) + KOPrefs::instance()->mLanguageChanged = true; +} +void KODialogManager::showSyncOptions() +{ + showOptionsDialog( true ); + +} +void KODialogManager::showOutgoingDialog() +{ + createOutgoingDialog(); + mOutgoingDialog->show(); + mOutgoingDialog->raise(); +} + +IncomingDialog *KODialogManager::incomingDialog() +{ + createOutgoingDialog(); + if (!mIncomingDialog) { + mIncomingDialog = new IncomingDialog(mMainView->calendar(),mOutgoingDialog,mMainView); + connect(mIncomingDialog,SIGNAL(numMessagesChanged(int)), + mMainView,SIGNAL(numIncomingChanged(int))); + connect(mIncomingDialog,SIGNAL(calendarUpdated()), + mMainView,SLOT(updateView())); + } + return mIncomingDialog; +} + +void KODialogManager::createIncomingDialog() +{ + createOutgoingDialog(); + if (!mIncomingDialog) { + mIncomingDialog = new IncomingDialog(mMainView->calendar(),mOutgoingDialog,mMainView); + connect(mIncomingDialog,SIGNAL(numMessagesChanged(int)), + mMainView,SIGNAL(numIncomingChanged(int))); + connect(mIncomingDialog,SIGNAL(calendarUpdated()), + mMainView,SLOT(updateView())); + } +} + +void KODialogManager::showIncomingDialog() +{ + createIncomingDialog(); + mIncomingDialog->show(); + mIncomingDialog->raise(); +} +/* +void KODialogManager::showCategoryEditDialog() +{ + mCategoryEditDialog->show(); +} +*/ +void KODialogManager::hideSearchDialog() +{ + if (mSearchDialog) + mSearchDialog->hide(); +} + +void KODialogManager::showSearchDialog() +{ + if (!mSearchDialog) { + mSearchDialog = new SearchDialog(mMainView->calendar(),mMainView); + KOListView * lview = mSearchDialog->listview(); + + connect(lview, SIGNAL(showIncidenceSignal(Incidence *)), + mMainView, SLOT(showIncidence(Incidence *))); + connect(lview, SIGNAL(editIncidenceSignal(Incidence *)), + mMainView, SLOT(editIncidence(Incidence *))); + connect(lview, SIGNAL(deleteIncidenceSignal(Incidence *)), + mMainView, SLOT(deleteIncidence(Incidence *))); + connect(lview, SIGNAL(cloneIncidenceSignal(Incidence *)), + mMainView, SLOT(cloneIncidence(Incidence *))); + connect(lview, SIGNAL(beamIncidenceSignal(Incidence *)), + mMainView, SLOT(beamIncidence(Incidence *))); + connect(lview, SIGNAL(moveIncidenceSignal(Incidence *)), + mMainView, SLOT(moveIncidence(Incidence *))); + connect(lview, SIGNAL(beamIncidenceList(QPtrList<Incidence> )), + mMainView, SLOT(beamIncidenceList(QPtrList<Incidence> ))); + + connect(mMainView, SIGNAL(configChanged()), mSearchDialog, SLOT(updateConfig())); + connect(mMainView, SIGNAL(updateSearchDialog()), mSearchDialog, SLOT(updateList())); + // connect( lview, SIGNAL( incidenceSelected( Incidence * ) ), + // mMainView, SLOT( processMainViewSelection( Incidence * ) ) ); +#ifndef DESKTOP_VERSION + mSearchDialog->setMaximumSize( 640, 480 ); + //mSearchDialog->setGeometry( 40,40, 400, 300); + mSearchDialog->showMaximized(); +#else + KConfig *config = KOGlobals::config(); + config->setGroup("WidgetLayout"); + QStringList list; + list = config->readListEntry("SearchLayout"); + int x,y,w,h; + if ( ! list.isEmpty() ) { + x = list[0].toInt(); + y = list[1].toInt(); + w = list[2].toInt(); + h = list[3].toInt(); + mSearchDialog->setGeometry(x,y,w,h); + + } + +#endif + } + // make sure the widget is on top again + mSearchDialog->show(); + mSearchDialog->raise(); +} + +SearchDialog * KODialogManager::getSearchDialog() +{ + return mSearchDialog; +} +void KODialogManager::showArchiveDialog() +{ +#ifndef KORG_NOARCHIVE + if (!mArchiveDialog) { + mArchiveDialog = new ArchiveDialog(mMainView->calendar(),mMainView); + connect(mArchiveDialog,SIGNAL(eventsDeleted()), + mMainView,SLOT(updateView())); + } + mArchiveDialog->show(); + mArchiveDialog->raise(); + + // Workaround. + QApplication::restoreOverrideCursor(); +#endif +} + +void KODialogManager::showFilterEditDialog(QPtrList<CalFilter> *filters) +{ + if (!mFilterEditDialog) { + mFilterEditDialog = new FilterEditDialog(filters,mMainView); + connect(mFilterEditDialog,SIGNAL(filterChanged()), + mMainView,SLOT(filterEdited())); + + } + +#ifndef DESKTOP_VERSION + mFilterEditDialog->showMaximized(); +#else + mFilterEditDialog->show(); +#endif + mFilterEditDialog->raise(); +} + +void KODialogManager::showPluginDialog() +{ +#ifndef KORG_NOPLUGINS + if (!mPluginDialog) { + mPluginDialog = new PluginDialog(mMainView); + connect(mPluginDialog,SIGNAL(configChanged()), + mMainView,SLOT(updateConfig())); + } + mPluginDialog->show(); + mPluginDialog->raise(); +#endif +} + +KOEventEditor *KODialogManager::getEventEditor() +{ + KOEventEditor *eventEditor = new KOEventEditor( mMainView->calendar(), + mMainView ); + + connect(eventEditor,SIGNAL(eventAdded(Event *)), + mMainView,SLOT(eventAdded(Event *))); + connect(eventEditor,SIGNAL(eventChanged(Event *)), + mMainView,SLOT(eventChanged(Event *))); + connect(eventEditor,SIGNAL(eventDeleted()), + mMainView,SLOT(eventDeleted())); + connect(eventEditor,SIGNAL(deleteAttendee(Incidence *)), + mMainView,SLOT(schedule_cancel(Incidence *))); + connect( eventEditor, SIGNAL(jumpToTime( const QDate &)), + mMainView->dateNavigator(), SLOT( selectWeek( const QDate & ) ) ); + connect( eventEditor, SIGNAL( showAgendaView( bool)), + mMainView->viewManager(), SLOT( showAgendaView( bool) ) ); + + // connect(mCategoryEditDialog,SIGNAL(categoryConfigChanged()), + // eventEditor,SLOT(updateCategoryConfig())); + // connect(eventEditor,SIGNAL(editCategories()), + // mCategoryEditDialog,SLOT(show())); + connect(eventEditor,SIGNAL(dialogClose(Incidence*)), + mMainView,SLOT(dialogClosing(Incidence*))); + + //connect(mMainView,SIGNAL(closingDown()),eventEditor,SLOT(reject())); + + return eventEditor; +} + +KOTodoEditor *KODialogManager::getTodoEditor() +{ + KOTodoEditor *todoEditor = new KOTodoEditor( mMainView->calendar(), + mMainView ); + + // connect(mCategoryEditDialog,SIGNAL(categoryConfigChanged()), + // todoEditor,SLOT(updateCategoryConfig())); + // connect(todoEditor,SIGNAL(editCategories()),mCategoryEditDialog,SLOT(show())); + + connect(todoEditor,SIGNAL(todoAdded(Todo *)), + mMainView,SLOT(todoAdded(Todo *))); + connect(todoEditor,SIGNAL(todoChanged(Todo *)), + mMainView,SLOT(todoChanged(Todo *))); + connect(todoEditor,SIGNAL(todoDeleted()), + mMainView,SLOT(todoDeleted())); + connect(todoEditor,SIGNAL(dialogClose(Incidence*)), + mMainView,SLOT(dialogClosing(Incidence*))); + connect( todoEditor, SIGNAL(jumpToTime( const QDate &)), + mMainView->dateNavigator(), SLOT( selectWeek( const QDate & ) ) ); + connect( todoEditor, SIGNAL( showAgendaView( bool)), + mMainView->viewManager(), SLOT( showAgendaView( bool) ) ); + // connect(todoEditor,SIGNAL(deleteAttendee(Incidence *)), + // mMainView,SLOT(schedule_cancel(Incidence *))); + //connect(mMainView,SIGNAL(closingDown()),todoEditor,SLOT(reject())); + + return todoEditor; +} + +void KODialogManager::updateSearchDialog() +{ + if (mSearchDialog) mSearchDialog->updateView(); +} + +void KODialogManager::setDocumentId( const QString &id ) +{ + if (mOutgoingDialog) mOutgoingDialog->setDocumentId( id ); +} + +void KODialogManager::writeSettings( KConfig *config ) +{ + if (mSearchDialog) + mSearchDialog->listview()->writeSettings(config,"SearchListView Layout"); +} diff --git a/korganizer/kodialogmanager.h b/korganizer/kodialogmanager.h new file mode 100644 index 0000000..a6cc621 --- a/dev/null +++ b/korganizer/kodialogmanager.h @@ -0,0 +1,100 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 + Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KODIALOGMANAGER_H +#define KODIALOGMANAGER_H + +#include <qobject.h> +#include <qptrlist.h> + +#include <libkcal/calfilter.h> + +class CalendarView; +class OutgoingDialog; +class IncomingDialog; +class KOPrefsDialog; +//namespace KPIM { class CategoryEditDialog; } +class KOEventEditor; +class KOTodoEditor; +class SearchDialog; +class ArchiveDialog; +class PluginDialog; +class KConfig; +class FilterEditDialog; + +using namespace KCal; + +/** + This class manages the dialogs used by the calendar view. It owns the objects + and handles creation and selection. +*/ +class KODialogManager : public QObject +{ + Q_OBJECT + public: + KODialogManager( CalendarView * ); + virtual ~KODialogManager(); + + /** Get an editor dialog for an Event. */ + KOEventEditor *getEventEditor(); + + /** Get an editor dialog for a Todo. */ + KOTodoEditor *getTodoEditor(); + + OutgoingDialog *outgoingDialog(); + + IncomingDialog *incomingDialog(); + void writeSettings( KConfig *config); + void updateSearchDialog(); + SearchDialog * getSearchDialog(); + void setDocumentId( const QString &id ); + + public slots: + void showOptionsDialog( bool showSync = false); + void showSyncOptions(); + void showIncomingDialog(); + void showOutgoingDialog(); + // void showCategoryEditDialog(); + void showSearchDialog(); + void showArchiveDialog(); + void showFilterEditDialog(QPtrList<CalFilter> *filters); + void showPluginDialog(); + void hideSearchDialog(); + + private: + void createOutgoingDialog(); + void createIncomingDialog(); + + CalendarView *mMainView; + + OutgoingDialog *mOutgoingDialog; + IncomingDialog *mIncomingDialog; + KOPrefsDialog *mOptionsDialog; + // KPIM::CategoryEditDialog *mCategoryEditDialog; + SearchDialog *mSearchDialog; + ArchiveDialog *mArchiveDialog; + FilterEditDialog *mFilterEditDialog; + PluginDialog *mPluginDialog; +}; + +#endif diff --git a/korganizer/kodialogmanager.moc b/korganizer/kodialogmanager.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kodialogmanager.moc diff --git a/korganizer/koeditordetails.cpp b/korganizer/koeditordetails.cpp new file mode 100644 index 0000000..7c4c382 --- a/dev/null +++ b/korganizer/koeditordetails.cpp @@ -0,0 +1,398 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + 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 thse hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qtooltip.h> +#include <qfiledialog.h> +#include <qlayout.h> +#include <qvbox.h> +#include <qbuttongroup.h> +#include <qvgroupbox.h> +#include <qwidgetstack.h> +#include <qdatetime.h> +#include <qapp.h> + +#include <klocale.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#ifndef KORG_NOKABC +#include <kabc/addresseedialog.h> +#endif + +#include <libkcal/incidence.h> + +#include "koprefs.h" + +#include "koeditordetails.h" +#include "koeditordetails.moc" + +template <> +CustomListViewItem<class Attendee *>::~CustomListViewItem() +{ + delete mData; +} + +template <> +void CustomListViewItem<class Attendee *>::updateItem() +{ + setText(0,mData->name()); + setText(1,mData->email()); + setText(2,mData->roleStr()); + setText(3,mData->statusStr()); + if (mData->RSVP() && !mData->email().isEmpty()) + setPixmap(4,SmallIcon("mailappt")); + else + setPixmap(4,SmallIcon("nomailappt")); +} + + +KOEditorDetails::KOEditorDetails (int spacing,QWidget* parent,const char* name) + : QWidget( parent, name), mDisableItemUpdate( false ) +{ + QGridLayout *topLayout = new QGridLayout(this); + topLayout->setSpacing(spacing); + + QString organizer = KOPrefs::instance()->email(); + mOrganizerLabel = new QLabel(i18n("Organizer: %1").arg(organizer),this); + + mListView = new KListView(this,"mListView"); + mListView->addColumn(i18n("Name"),180); + mListView->addColumn(i18n("Email"),180); + mListView->addColumn(i18n("Role"),60); + mListView->addColumn(i18n("Status"),100); + mListView->addColumn(i18n("RSVP"),35); + if ( KOPrefs::instance()->mCompactDialogs ) { + //mListView->setFixedHeight(78); + } + + connect(mListView,SIGNAL(selectionChanged(QListViewItem *)), + SLOT(updateAttendeeInput())); + + QLabel *attendeeLabel = new QLabel(this); + attendeeLabel->setText(i18n("Name:")); + attendeeLabel->setFixedSize( attendeeLabel->sizeHint() ); + mNameEdit = new QLineEdit(this); + connect(mNameEdit,SIGNAL(textChanged(const QString &)), + SLOT(updateAttendeeItem())); + + mUidEdit = new QLineEdit(0); + mUidEdit->setText(""); + + QLabel *emailLabel = new QLabel(this); + emailLabel->setText(i18n("Email:")); + mEmailEdit = new QLineEdit(this); + connect(mEmailEdit,SIGNAL(textChanged(const QString &)), + SLOT(updateAttendeeItem())); + + QLabel *attendeeRoleLabel = new QLabel(this); + attendeeRoleLabel->setText(i18n("Role:")); + mRoleCombo = new QComboBox(false,this); + mRoleCombo->insertStringList(Attendee::roleList()); + connect(mRoleCombo,SIGNAL(activated(int)),SLOT(updateAttendeeItem())); + + QLabel *statusLabel = new QLabel(this); + statusLabel->setText( i18n("Status:") ); + + mStatusCombo = new QComboBox(false,this); + mStatusCombo->insertStringList(Attendee::statusList()); + connect(mStatusCombo,SIGNAL(activated(int)),SLOT(updateAttendeeItem())); + + mRsvpButton = new QCheckBox(this); + mRsvpButton->setText(i18n("Request response")); + connect(mRsvpButton,SIGNAL(clicked()),SLOT(updateAttendeeItem())); + QWidget *buttonBox = new QWidget(this); + QVBoxLayout *buttonLayout = new QVBoxLayout(buttonBox); + + QPushButton *newButton = new QPushButton(i18n("&New"),buttonBox); + buttonLayout->addWidget(newButton); + connect(newButton,SIGNAL(clicked()),SLOT(addNewAttendee())); + + mRemoveButton = new QPushButton(i18n("&Remove"),buttonBox); + buttonLayout->addWidget(mRemoveButton); + connect(mRemoveButton, SIGNAL(clicked()),SLOT(removeAttendee())); + + mAddressBookButton = new QPushButton(i18n("Address &Book..."),this); + // buttonLayout->addWidget(mAddressBookButton); + connect(mAddressBookButton,SIGNAL(clicked()),SLOT(openAddressBook())); + //mRoleCombo->setFixedSize( mRoleCombo->sizeHint () ); + + if (qApp->desktop()->width() < 300 ) { + mListView->setFixedHeight(80); + topLayout->addMultiCellWidget(mOrganizerLabel,0,0,0,3); + topLayout->addMultiCellWidget(mListView,1,1,0,3); + topLayout->addWidget(attendeeLabel,3,0); + topLayout->addMultiCellWidget(mNameEdit,3,3,1,2); + topLayout->addWidget(emailLabel,4,0); + topLayout->addMultiCellWidget(mEmailEdit,4,4,1,2); + topLayout->addWidget(attendeeRoleLabel,5,0); + topLayout->addMultiCellWidget(mRoleCombo,5,5,1,2); + topLayout->addWidget(statusLabel,6,0); + topLayout->addMultiCellWidget(mStatusCombo,6,6,1,2); + topLayout->addMultiCellWidget(mAddressBookButton,2,2,2,3); + topLayout->addMultiCellWidget(mRsvpButton,2,2,0,1); + topLayout->addMultiCellWidget(buttonBox,3,4,3,3); + topLayout->setRowStretch(1,2); + topLayout->setColStretch(0,0); + topLayout->setColStretch(1,2); + topLayout->setColStretch(2,1); + topLayout->setColStretch(3,1); + + } else { + topLayout->addMultiCellWidget(mOrganizerLabel,0,0,0,5); + topLayout->addMultiCellWidget(mListView,1,1,0,5); + topLayout->addWidget(attendeeLabel,3,0); + topLayout->addMultiCellWidget(mNameEdit,3,3,1,4); + topLayout->addWidget(emailLabel,4,0); + topLayout->addMultiCellWidget(mEmailEdit,4,4,1,4); + topLayout->addWidget(attendeeRoleLabel,5,0); + topLayout->addMultiCellWidget(mRoleCombo,5,5,1,2); + topLayout->addWidget(statusLabel,5,3); + topLayout->addMultiCellWidget(mStatusCombo,5,5,4,5); + topLayout->addMultiCellWidget(mAddressBookButton,2,2,4,5); + topLayout->addMultiCellWidget(mRsvpButton,2,2,0,1); + topLayout->addMultiCellWidget(buttonBox,3,4,5,5); + topLayout->setRowStretch(1,5); + topLayout->setColStretch(0,0); + } +// #if 0 +// topLayout->setColStretch(2,1); +// topLayout->addWidget(statusLabel,3,3); +// topLayout->addWidget(mStatusCombo,3,4); +// #else +// topLayout->addWidget(statusLabel,4,3); +// // topLayout->addWidget(mStatusCombo,4,3); +// topLayout->addMultiCellWidget(mStatusCombo,4,4,4,5); + +// #endif +// // topLayout->setRowStretch(5,1); +// topLayout->addMultiCellWidget(mRsvpButton,5,5,0,1); +// topLayout->addMultiCellWidget(buttonBox,2,3,5,5); +// topLayout->setRowStretch(1,5); +// topLayout->setColStretch(0,0); + +#ifdef KORG_NOKABC + mAddressBookButton->hide(); +#endif + + updateAttendeeInput(); +} + +KOEditorDetails::~KOEditorDetails() +{ +} + +void KOEditorDetails::removeAttendee() +{ + AttendeeListItem *aItem = (AttendeeListItem *)mListView->selectedItem(); + if (!aItem) return; + + Attendee *delA = new Attendee(aItem->data()->name(),aItem->data()->email(), + aItem->data()->RSVP(),aItem->data()->status(),aItem->data()->role(), + aItem->data()->uid()); + mdelAttendees.append(delA); + + delete aItem; + + updateAttendeeInput(); +} + + +void KOEditorDetails::openAddressBook() +{ +#ifndef KORG_NOKABC + + KABC::Addressee::List list = KABC::AddresseeDialog::getAddressees(this); + uint i=0; + for (i=0; i < list.count(); i++) { + insertAttendee( new Attendee( list[i].realName(), list[i].preferredEmail(),false,KCal::Attendee::NeedsAction,KCal::Attendee::ReqParticipant,list[i].uid()) ); + } + +#if 0 + KABC::Addressee a = KABC::AddresseeDialog::getAddressee(this); + if (!a.isEmpty()) { + insertAttendee( new Attendee( a.realName(), a.preferredEmail(),false,KCal::Attendee::NeedsAction,KCal::Attendee::ReqParticipant,a.uid()) ); + } +#endif +#endif +} + + +void KOEditorDetails::addNewAttendee() +{ +#if 0 + // this is cool. If they didn't enter an email address, + // try to look it up in the address book and fill it in for them. + if (QString(mEmailEdit->text()).stripWhiteSpace().isEmpty()) { + KabAPI addrBook; + QString name; + std::list<AddressBook::Entry> entries; + name = mNameEdit->text(); + if (addrBook.init() == AddressBook::NoError) { + if (addrBook.getEntryByName(name, entries, 1) == AddressBook::NoError) { + kdDebug() << "positive match" << endl; + // take first email address + if (!entries.front().emails.isEmpty() && + entries.front().emails.first().length()>0) + mEmailEdit->setText(entries.front().emails.first()); + } + } + } +#endif + + Attendee *a = new Attendee(i18n("(EmptyName)"),i18n("(EmptyEmail)")); + insertAttendee(a); +} + + +void KOEditorDetails::insertAttendee(Attendee *a) +{ + AttendeeListItem *item = new AttendeeListItem(a,mListView); + mListView->setSelected( item, true ); +} + +void KOEditorDetails::setDefaults() +{ + mRsvpButton->setChecked(true); + mListView->clear(); + mdelAttendees.clear(); + clearAttendeeInput(); + mOrganizerLabel->setText(i18n("Organizer: %1").arg(KOPrefs::instance()->email())); + + mNameEdit->setText(""); + mUidEdit->setText(""); + mEmailEdit->setText(""); + mRoleCombo->setCurrentItem( 0 ); + mStatusCombo->setCurrentItem( 0 ); + +} + +void KOEditorDetails::readEvent(Incidence *event) +{ + setDefaults(); + //mListView->clear(); + //mdelAttendees.clear(); + QPtrList<Attendee> tmpAList = event->attendees(); + Attendee *a; + for (a = tmpAList.first(); a; a = tmpAList.next()) + insertAttendee(new Attendee(*a)); + + mListView->setSelected( mListView->firstChild(), true ); + mOrganizerLabel->setText(i18n("Organizer: %1").arg(event->organizer())); +} + +void KOEditorDetails::writeEvent(Incidence *event) +{ + event->clearAttendees(); + QListViewItem *item; + AttendeeListItem *a; + for (item = mListView->firstChild(); item; + item = item->nextSibling()) { + a = (AttendeeListItem *)item; + event->addAttendee(new Attendee(*(a->data()))); + } + event->setOrganizer(KOPrefs::instance()->email()); +} + +void KOEditorDetails::cancelAttendeeEvent(Incidence *event) +{ + event->clearAttendees(); + Attendee * att; + for (att=mdelAttendees.first();att;att=mdelAttendees.next()) { + event->addAttendee(new Attendee(*att)); + } + mdelAttendees.clear(); +} + +bool KOEditorDetails::validateInput() +{ + return true; +} + +void KOEditorDetails::updateAttendeeInput() +{ + QListViewItem *item = mListView->selectedItem(); + AttendeeListItem *aItem = static_cast<AttendeeListItem *>( item ); + if (aItem) { + fillAttendeeInput( aItem ); + } else { + clearAttendeeInput(); + } +} + +void KOEditorDetails::clearAttendeeInput() +{ + mNameEdit->setText(""); + mUidEdit->setText(""); + mEmailEdit->setText(""); + mRoleCombo->setCurrentItem(0); + mStatusCombo->setCurrentItem(0); + mRsvpButton->setChecked(true); + setEnabledAttendeeInput( false ); +} + +void KOEditorDetails::fillAttendeeInput( AttendeeListItem *aItem ) +{ + Attendee *a = aItem->data(); + mDisableItemUpdate = true; + mNameEdit->setText(a->name()); + mUidEdit->setText(a->uid()); + mEmailEdit->setText(a->email()); + mRoleCombo->setCurrentItem(a->role()); + mStatusCombo->setCurrentItem(a->status()); + mRsvpButton->setChecked(a->RSVP()); + + mDisableItemUpdate = false; + + setEnabledAttendeeInput( true ); +} + +void KOEditorDetails::setEnabledAttendeeInput( bool enabled ) +{ + mNameEdit->setEnabled( enabled ); + mEmailEdit->setEnabled( enabled ); + mRoleCombo->setEnabled( enabled ); + mStatusCombo->setEnabled( enabled ); + mRsvpButton->setEnabled( enabled ); + + mRemoveButton->setEnabled( enabled ); +} + +void KOEditorDetails::updateAttendeeItem() +{ + if (mDisableItemUpdate) return; + + QListViewItem *item = mListView->selectedItem(); + AttendeeListItem *aItem = static_cast<AttendeeListItem *>( item ); + if ( !aItem ) return; + + Attendee *a = aItem->data(); + + a->setName( mNameEdit->text() ); + a->setUid( mUidEdit->text() ); + a->setEmail( mEmailEdit->text() ); + a->setRole( Attendee::Role( mRoleCombo->currentItem() ) ); + a->setStatus( Attendee::PartStat( mStatusCombo->currentItem() ) ); + a->setRSVP( mRsvpButton->isChecked() ); + aItem->updateItem(); +} diff --git a/korganizer/koeditordetails.h b/korganizer/koeditordetails.h new file mode 100644 index 0000000..930b296 --- a/dev/null +++ b/korganizer/koeditordetails.h @@ -0,0 +1,103 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOEDITORDETAILS_H +#define _KOEDITORDETAILS_H + +#include <qframe.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qmultilineedit.h> +#include <klistview.h> +#include <qradiobutton.h> +#include <qptrlist.h> + +#include <kapplication.h> + +#include <libkcal/event.h> + +#include "ktimeedit.h" +#include "customlistviewitem.h" + +class KDateEdit; + +using namespace KCal; + +typedef CustomListViewItem<Attendee *> AttendeeListItem; + + +class KOEditorDetails : public QWidget +{ + Q_OBJECT + public: + KOEditorDetails (int spacing = 8,QWidget* parent = 0, const char* name = 0); + virtual ~KOEditorDetails(); + + /** Set widgets to default values */ + void setDefaults(); + /** Read event object and setup widgets accordingly */ + void readEvent(Incidence *); + /** Write event settings to event object */ + void writeEvent(Incidence *); + + /** return a clone of the event with attendees to be canceld*/ + void cancelAttendeeEvent(Incidence *); + /** Check if the input is valid. */ + bool validateInput(); + + public slots: + void insertAttendee(Attendee *); + + protected slots: + void addNewAttendee(); + void removeAttendee(); + void openAddressBook(); + void updateAttendeeInput(); + void clearAttendeeInput(); + void fillAttendeeInput(AttendeeListItem *); + void updateAttendeeItem(); + void setEnabledAttendeeInput(bool); + + private: + bool mDisableItemUpdate; + + QLineEdit *mNameEdit; + QLineEdit *mUidEdit; + QLineEdit *mEmailEdit; + KListView *mListView; + QComboBox* mRoleCombo; + QCheckBox* mRsvpButton; + QComboBox* mStatusCombo; + QLabel *mOrganizerLabel; + + QPushButton* mAddButton; + QPushButton* mRemoveButton; + QPushButton* mAddressBookButton; + + QPtrList<Attendee> mdelAttendees; +}; + +#endif diff --git a/korganizer/koeditordetails.moc b/korganizer/koeditordetails.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeditordetails.moc diff --git a/korganizer/koeditorgeneral.cpp b/korganizer/koeditorgeneral.cpp new file mode 100644 index 0000000..ad1389f --- a/dev/null +++ b/korganizer/koeditorgeneral.cpp @@ -0,0 +1,505 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qwidget.h> +#include <qtooltip.h> +#include <qlayout.h> +#include <qvbox.h> +#include <qbuttongroup.h> +#include <qvgroupbox.h> +#include <qwidgetstack.h> +#include <qdatetime.h> +#include <qfile.h> + + +#include <kglobal.h> +#include <kdebug.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kfiledialog.h> +#include <kstandarddirs.h> + +#include <libkcal/todo.h> +#include <libkcal/event.h> +#include <libkdepim/categoryselectdialog.h> +#include <libkdepim/kdateedit.h> + +#include "koprefs.h" +#include "koglobals.h" + +#include "koeditorgeneral.h" +#include "kolocationbox.h" +#include "koeditorgeneral.moc" +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#else +#include <qapplication.h> +#endif + +KOEditorGeneral::KOEditorGeneral(QObject* parent, const char* name) : + QObject( parent, name) +{ +} + +KOEditorGeneral::~KOEditorGeneral() +{ +} + +void KOEditorGeneral::initHeader(QWidget *parent,QBoxLayout *topLayout) +{ + QGridLayout *headerLayout = new QGridLayout(topLayout); + +#if 0 + mOwnerLabel = new QLabel(i18n("Owner:"),parent); + headerLayout->addMultiCellWidget(mOwnerLabel,0,0,0,1); +#endif + + QLabel *summaryLabel = new QLabel(i18n("Summary:"),parent); + headerLayout->addWidget(summaryLabel,1,0); + + mSummaryEdit = new KOLocationBox(TRUE,parent, 10); + mSummaryEdit->setSizePolicy( QSizePolicy( QSizePolicy::Preferred ,QSizePolicy::MinimumExpanding ,FALSE) ); + //mSummaryEdit->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5 ,(QSizePolicy::SizeType)3 ,FALSE) ); + //qDebug("h %d %d ", summaryLabel->sizeHint().height(),mSummaryEdit->sizeHint().height() ); + int hei = (summaryLabel->sizeHint().height() + mSummaryEdit->sizeHint().height())/2; + if ( QApplication::desktop()->width() > 320 ) + mSummaryEdit->setMaximumHeight( hei +6 ); + //qDebug("%d %d %d %d %d %d ", QSizePolicy::Fixed , QSizePolicy::Minimum , QSizePolicy:: Maximum , QSizePolicy:: Preferred , QSizePolicy:: MinimumExpanding , QSizePolicy::Expanding ); + // SizeType { Fixed = 0, Minimum = MayGrow, Maximum = MayShrink, Preferred = MayGrow|MayShrink, MinimumExpanding = Minimum|ExpMask, Expanding = MinimumExpanding|MayShrink } + // mSummaryEdit = new QLineEdit(parent); + headerLayout->addWidget(mSummaryEdit,1,1); + connect ( mSummaryEdit->lineEdit(), SIGNAL ( returnPressed() ), this, SIGNAL (allAccepted () ) ); + + QLabel *locationLabel = new QLabel(i18n("Location:"),parent); + headerLayout->addWidget(locationLabel,2,0); + + mLocationEdit = new KOLocationBox(TRUE,parent,10); + mLocationEdit->setSizePolicy( QSizePolicy( QSizePolicy::Preferred ,QSizePolicy::MinimumExpanding ,FALSE) ); + if ( QApplication::desktop()->width() > 320 ) + mLocationEdit->setMaximumHeight( hei + 6); + + // mLocationEdit = new QLineEdit(parent); + connect ( mLocationEdit->lineEdit(), SIGNAL ( returnPressed() ), this, SIGNAL (allAccepted () ) ); + headerLayout->addWidget(mLocationEdit,2,1); + headerLayout->setColStretch( 1, 10); +} +void KOEditorGeneral::setFocusOn( int i ) +{ + qApp->processEvents(); + if ( i == 1 ) { + mDescriptionEdit->setFocus(); + mDescriptionEdit->setCursorPosition( mDescriptionEdit->numLines (), 333); + } + if ( i == 2 ) { + mSummaryEdit->setFocus(); + } + +} +void KOEditorGeneral::editCategories() +{ + // qDebug("KOEditorGeneral::editCategories() "); + KPIM::CategorySelectDialog* csd = new KPIM::CategorySelectDialog( KOPrefs::instance(), 0 ); + connect(csd,SIGNAL(categoriesSelected(const QString &)), this ,SLOT(setCategories(const QString &))); + //KOGlobals::fitDialogToScreen( csd ); + csd->setSelected( QStringList::split (",", mCategoriesLabel->text()) ); + csd->exec(); + delete csd; +} +void KOEditorGeneral::initCategories(QWidget *parent, QBoxLayout *topLayout) +{ + QBoxLayout *categoriesLayout = new QHBoxLayout( topLayout ); + + mCategoriesButton = new QPushButton(parent); + mCategoriesButton->setText(i18n("Categories...")); + connect(mCategoriesButton,SIGNAL(clicked()),this, SLOT(editCategories() )); + categoriesLayout->addWidget(mCategoriesButton); + + mCategoriesLabel = new QLabel(parent); + mCategoriesLabel->setFrameStyle(QFrame::Panel|QFrame::Sunken); + categoriesLayout->addWidget(mCategoriesLabel,1); +} + +void KOEditorGeneral::initSecrecy(QWidget *parent, QBoxLayout *topLayout) +{ + QBoxLayout *secrecyLayout = new QHBoxLayout( topLayout ); + + QLabel *secrecyLabel = new QLabel(i18n("Access:"),parent); + mCancelBox = new QCheckBox ( i18n("Cancelled"), parent); + secrecyLayout->addWidget(mCancelBox); + secrecyLayout->addWidget(secrecyLabel); + + mSecrecyCombo = new QComboBox(parent); + mSecrecyCombo->insertStringList(Incidence::secrecyList()); + secrecyLayout->addWidget(mSecrecyCombo); +} + +void KOEditorGeneral::initDescription(QWidget *parent,QBoxLayout *topLayout) +{ + mDescriptionEdit = new KTextEdit(parent); + mDescriptionEdit->setFont(KOPrefs::instance()->mEditBoxFont ); + mDescriptionEdit->append(""); + mDescriptionEdit->setReadOnly(false); + mDescriptionEdit->setOverwriteMode(false); + mDescriptionEdit->setWordWrap( KTextEdit::WidgetWidth ); + topLayout->addWidget(mDescriptionEdit); +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( mDescriptionEdit, QPEApplication::RightOnHold ); +#endif + +} + +void KOEditorGeneral::initAlarm(QWidget *parent,QBoxLayout *topLayout) +{ + QBoxLayout *alarmLayout = new QHBoxLayout(topLayout); + + //mAlarmBell = new QLabel(parent); + //mAlarmBell->setPixmap(SmallIcon("bell")); + //alarmLayout->addWidget(mAlarmBell); + if ( QApplication::desktop()->width() < 320 ) + mAlarmButton = new QCheckBox(i18n("Rem."),parent); + else + mAlarmButton = new QCheckBox(i18n("Reminder:"),parent); + + connect(mAlarmButton, SIGNAL(toggled(bool)), SLOT(enableAlarmEdit(bool))); + alarmLayout->addWidget(mAlarmButton); + + mAlarmTimeEdit = new QSpinBox ( 0, 9999, 1, parent, "mAlarmTimeEdit " ) ; + alarmLayout->addWidget(mAlarmTimeEdit); + mAlarmIncrCombo = new QComboBox(false, parent); + if ( QApplication::desktop()->width() < 320 ) { + mAlarmIncrCombo->insertItem(i18n("min")); + mAlarmIncrCombo->insertItem(i18n("hou")); + mAlarmIncrCombo->insertItem(i18n("day")); + mAlarmTimeEdit->setMaximumWidth( mAlarmTimeEdit->sizeHint().width() ); + mAlarmIncrCombo->setMaximumWidth( mAlarmIncrCombo->sizeHint().width() ); + } else { + mAlarmIncrCombo->insertItem(i18n("minute(s)")); + mAlarmIncrCombo->insertItem(i18n("hour(s)")); + mAlarmIncrCombo->insertItem(i18n("day(s)")); + } + + // mAlarmIncrCombo->setMinimumHeight(20); + alarmLayout->addWidget(mAlarmIncrCombo); + mAlarmSoundButton = new QPushButton(parent); + mAlarmSoundButton->setPixmap(SmallIcon("playsound")); + mAlarmSoundButton->setToggleButton(true); + QToolTip::add(mAlarmSoundButton, i18n("No sound set")); + connect(mAlarmSoundButton, SIGNAL(clicked()), SLOT(pickAlarmSound())); + alarmLayout->addWidget(mAlarmSoundButton); + + mAlarmProgramButton = new QPushButton(parent); + mAlarmProgramButton->setPixmap(SmallIcon("run")); + mAlarmProgramButton->setToggleButton(true); + QToolTip::add(mAlarmProgramButton, i18n("No program set")); + connect(mAlarmProgramButton, SIGNAL(clicked()), SLOT(pickAlarmProgram())); + alarmLayout->addWidget(mAlarmProgramButton); + mAlarmSoundButton->setMaximumWidth( mAlarmSoundButton->sizeHint().width() + 4 ); + mAlarmProgramButton->setMaximumWidth(mAlarmProgramButton->sizeHint().width() + 4 ); + // if ( KOPrefs::instance()->mCompactDialogs ) { + // mAlarmSoundButton->hide(); + // mAlarmProgramButton->hide(); + // } +} + +void KOEditorGeneral::pickAlarmSound() +{ + + //QString prefix = mAlarmSound; + if (!mAlarmSoundButton->isOn()) { + //mAlarmSound = ""; + QToolTip::remove(mAlarmSoundButton); + QToolTip::add(mAlarmSoundButton, i18n("No sound set")); + mAlarmProgramButton->setOn(true); + mAlarmSoundButton->setOn(false); + } else { + QString fileName(KFileDialog::getOpenFileName(mAlarmSound, + i18n("*.wav|Wav Files"), 0)); + if (!fileName.isEmpty()) { + mAlarmSound = fileName; + QToolTip::remove(mAlarmSoundButton); + QString dispStr = i18n("Playing '%1'").arg(fileName); + QToolTip::add(mAlarmSoundButton, dispStr); + mAlarmProgramButton->setOn(false); + mAlarmSoundButton->setOn(true); + } else { + mAlarmProgramButton->setOn(true); + mAlarmSoundButton->setOn(false); + + } + } + + if (mAlarmProgramButton->isOn()) + ((QWidget*)parent())->topLevelWidget()->setCaption(i18n("Proc.Al.: ") + mAlarmProgram ); + if ( mAlarmSoundButton->isOn()) + ((QWidget*)parent())->topLevelWidget()->setCaption(i18n("Audio.Al.: ") + mAlarmSound ); +} + +void KOEditorGeneral::pickAlarmProgram() +{ + if (!mAlarmProgramButton->isOn()) { + //mAlarmProgram = ""; + QToolTip::remove(mAlarmProgramButton); + QToolTip::add(mAlarmProgramButton, i18n("No program set")); + mAlarmProgramButton->setOn(false); + mAlarmSoundButton->setOn(true); + } else { + QString fileName(KFileDialog::getOpenFileName(mAlarmProgram,i18n("Procedure Alarm.: ") , 0)); + if (!fileName.isEmpty()) { + mAlarmProgram = fileName; + QToolTip::remove(mAlarmProgramButton); + QString dispStr = i18n("Running '%1'").arg(fileName); + QToolTip::add(mAlarmProgramButton, dispStr); + mAlarmSoundButton->setOn(false); + mAlarmProgramButton->setOn(true); + } else { + mAlarmProgramButton->setOn(false); + mAlarmSoundButton->setOn(true); + } + } + if (mAlarmProgramButton->isOn()) + ((QWidget*)parent())->topLevelWidget()->setCaption(i18n("Proc.Al.: ") + mAlarmProgram ); + if ( mAlarmSoundButton->isOn()) + ((QWidget*)parent())->topLevelWidget()->setCaption(i18n("Sound.Al.: ") + mAlarmSound ); +} + + + +void KOEditorGeneral::enableAlarmEdit(bool enable) +{ + if ( enable ) { + if (!mAlarmProgramButton->isOn() && !mAlarmSoundButton->isOn()) { + mAlarmSoundButton->setOn( true ); + if ( mAlarmSound.isEmpty() ) + mAlarmSound = KOPrefs::instance()->mDefaultAlarmFile; + else { + if ( ! QFile::exists( mAlarmSound ) ) + mAlarmSound = KOPrefs::instance()->mDefaultAlarmFile; + } + } + if (mAlarmProgramButton->isOn()) + ((QWidget*)parent())->topLevelWidget()->setCaption(i18n("Proc.Al.: ") + mAlarmProgram ); + if (!mAlarmSound.isEmpty() && mAlarmSoundButton->isOn()) + ((QWidget*)parent())->topLevelWidget()->setCaption(i18n("Sound.Al.: ") + mAlarmSound ); + } + else { + ((QWidget*)parent())->topLevelWidget()->setCaption(i18n("Alarm disabled")); + + } + mAlarmTimeEdit->setEnabled(enable); + mAlarmSoundButton->setEnabled(enable); + mAlarmProgramButton->setEnabled(enable); + mAlarmIncrCombo->setEnabled(enable); +} + +void KOEditorGeneral::disableAlarmEdit(bool disable) +{ + enableAlarmEdit( !disable ); +} + +void KOEditorGeneral::enableAlarm( bool enable ) +{ + enableAlarmEdit( enable ); +} + +void KOEditorGeneral::alarmDisable(bool disable) +{ + if (!disable) { + //mAlarmBell->setEnabled(true); + mAlarmButton->setEnabled(true); + } else { + //mAlarmBell->setEnabled(false); + mAlarmButton->setEnabled(false); + mAlarmButton->setChecked(false); + mAlarmTimeEdit->setEnabled(false); + mAlarmSoundButton->setEnabled(false); + mAlarmProgramButton->setEnabled(false); + mAlarmIncrCombo->setEnabled(false); + } +} + +void KOEditorGeneral::setCategories(const QString &str) +{ + mCategoriesLabel->setText(str); +} + +void KOEditorGeneral::setDefaults(bool allDay) +{ +#if 0 + mOwnerLabel->setText(i18n("Owner: ") + KOPrefs::instance()->fullName()); +#endif + + enableAlarmEdit( !allDay ); + + // TODO: Implement a KPrefsComboItem to solve this in a clean way. + int alarmTime; + int a[] = { 1,5,10,15,30,60,180, 1440 }; + int index = KOPrefs::instance()->mAlarmTime; + if (index < 0 || index > 7) { + alarmTime = 15; + } else { + alarmTime = a[index]; + } + mAlarmButton ->setChecked( false ); + mAlarmTimeEdit->setValue(alarmTime); + mAlarmIncrCombo->setCurrentItem(0); + enableAlarmEdit( false ); + //alarmDisable (false); + mSecrecyCombo->setCurrentItem(Incidence::SecrecyPublic); + mCancelBox->setChecked( false ); + mSummaryEdit->setEditText(""); + mLocationEdit->setEditText(""); + mDescriptionEdit->setText(""); + mAlarmSound = KOPrefs::instance()->mDefaultAlarmFile; + setCategories(""); +} +void KOEditorGeneral::setSecrecy( int num ) +{ + mSecrecyCombo->setCurrentItem(num); +} +void KOEditorGeneral::readIncidence(Incidence *event) +{ + + mAlarmIncrCombo->setCurrentItem(0); + mSummaryEdit->setEditText(event->summary()); + mLocationEdit->setEditText(event->location()); + mDescriptionEdit->setText(event->description()); + +#if 0 + // organizer information + mOwnerLabel->setText(i18n("Owner: ") + event->organizer()); +#endif + + enableAlarmEdit( event->isAlarmEnabled() ); + //qDebug("KOEditorGeneral::readIncidence(Incidence *event) "); + if(!event->isAlarmEnabled()) { + // TODO: Implement a KPrefsComboItem to solve this in a clean way. + int alarmTime; + int a[] = { 1,5,10,15,30,60,180, 1440 }; + int index = KOPrefs::instance()->mAlarmTime; + if (index < 0 || index > 7) { + alarmTime = 15; + } else { + alarmTime = a[index]; + } + mAlarmTimeEdit->setValue(alarmTime); + } + mAlarmButton->setChecked( event->isAlarmEnabled() ); + mSecrecyCombo->setCurrentItem(event->secrecy()); + mCancelBox->setChecked( event->cancelled() ); + mAlarmProgramButton->setOn(false); + mAlarmSoundButton->setOn(false); + + // set up alarm stuff + QPtrList<Alarm> alarms = event->alarms(); + Alarm* alarm; + mAlarmIncrCombo->setCurrentItem(0); + for ( alarm = alarms.first(); alarm; alarm = alarms.next() ) { + int offset; + if ( alarm->hasTime() ) { + QDateTime t = alarm->time(); + offset = event->dtStart().secsTo( t ); + } else { + offset = alarm->startOffset().asSeconds(); + } + if ( offset != 0 ) { + offset = offset / -60; // make minutes + if (offset % 60 == 0) { // divides evenly into hours? + offset = offset / 60; + mAlarmIncrCombo->setCurrentItem(1); + if (offset % 24 == 0) { // divides evenly into days? + offset = offset / 24; + mAlarmIncrCombo->setCurrentItem(2); + } + } + } + mAlarmTimeEdit->setValue( offset ); + if (alarm->type() == Alarm::Procedure) { + + mAlarmProgram = alarm->programFile(); + mAlarmProgramButton->setOn(true); + QString dispStr = i18n("Running '%1'").arg(mAlarmProgram); + QToolTip::add(mAlarmProgramButton, dispStr); + } + else if (alarm->type() == Alarm::Audio) { + mAlarmSound = alarm->audioFile(); + if ( ! QFile::exists( mAlarmSound ) ) + mAlarmSound = KOPrefs::instance()->mDefaultAlarmFile; + mAlarmSoundButton->setOn(true); + QString dispStr = i18n("Playing '%1'").arg(mAlarmSound); + QToolTip::add(mAlarmSoundButton, dispStr); + } + mAlarmButton->setChecked(alarm->enabled()); + enableAlarmEdit( alarm->enabled() ); + //qDebug("nableAlarmEdit( alarm->enabled() )********* "); + // TODO: Deal with multiple alarms + break; // For now, stop after the first alarm + } + + setCategories(event->categoriesStr()); +} + +void KOEditorGeneral::writeIncidence(Incidence *event) +{ + // kdDebug() << "KOEditorGeneral::writeEvent()" << endl; + mLocationEdit->save(KOLocationBox::LOCATION); + event->setSummary(mSummaryEdit->currentText()); + event->setLocation(mLocationEdit->currentText()); + event->setDescription(mDescriptionEdit->text()); + event->setCategories(mCategoriesLabel->text()); + event->setSecrecy(mSecrecyCombo->currentItem()); + event->setCancelled(mCancelBox->isChecked() );; + // alarm stuff + if (mAlarmButton->isChecked()) { + if (event->alarms().count() == 0) + event->newAlarm(); + QPtrList<Alarm> alarms = event->alarms(); + Alarm *alarm; + for (alarm = alarms.first(); alarm; alarm = alarms.next() ) { + alarm->setEnabled(true); + int j = mAlarmTimeEdit->value()* -60; + if (mAlarmIncrCombo->currentItem() == 1) + j = j * 60; + else if (mAlarmIncrCombo->currentItem() == 2) + j = j * (60 * 24); + alarm->setStartOffset( j ); + + if (!mAlarmProgram.isEmpty() && mAlarmProgramButton->isOn()) { + alarm->setProcedureAlarm(mAlarmProgram); + } + else if (!mAlarmSound.isEmpty() && mAlarmSoundButton->isOn()) + alarm->setAudioAlarm(mAlarmSound); + else + alarm->setType(Alarm::Invalid); + //alarm->setAudioAlarm("default"); + // TODO: Deal with multiple alarms + break; // For now, stop after the first alarm + } + } else { + Alarm* alarm = event->alarms().first(); + if ( alarm ) { + alarm->setEnabled(false); + alarm->setType(Alarm::Invalid); + } + } +} diff --git a/korganizer/koeditorgeneral.h b/korganizer/koeditorgeneral.h new file mode 100644 index 0000000..c58335e --- a/dev/null +++ b/korganizer/koeditorgeneral.h @@ -0,0 +1,112 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KOEDITORGENERAL_H +#define KOEDITORGENERAL_H + +#include <qframe.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qlistview.h> +#include <qradiobutton.h> +#include <qlayout.h> +#include <qspinbox.h> + +#include <ktextedit.h> +#include <krestrictedline.h> + +#include <libkcal/incidence.h> + +#include "ktimeedit.h" + +class KDateEdit; +class KOLocationBox; +using namespace KCal; + +class KOEditorGeneral : public QObject +{ + Q_OBJECT + public: + KOEditorGeneral (QObject* parent=0,const char* name=0); + virtual ~KOEditorGeneral(); + void setFocusOn( int i ); + void initHeader(QWidget *,QBoxLayout *); + void initDescription(QWidget *,QBoxLayout *); + void initSecrecy(QWidget *,QBoxLayout *); + void initCategories(QWidget *,QBoxLayout *); + void initAlarm(QWidget *,QBoxLayout *); + + /** Set widgets to default values */ + void setDefaults(bool allDay); + /** Read event object and setup widgets accordingly */ + void readIncidence(Incidence *); + /** Write event settings to event object */ + void writeIncidence(Incidence *); + + /** Check if the input is valid. */ + bool validateInput() { return true; } + + void enableAlarm( bool enable ); + void setSecrecy( int num ); + public slots: + void setCategories(const QString &); + void editCategories(); + + protected slots: + void enableAlarmEdit( bool enable ); + void disableAlarmEdit( bool disable ); + void alarmDisable( bool disable ); + void pickAlarmSound(); + void pickAlarmProgram(); + + signals: + void openCategoryDialog(); + void allAccepted(); + + protected: + //QLineEdit *mSummaryEdit; + //QLineEdit *mLocationEdit; + KOLocationBox *mSummaryEdit; + KOLocationBox *mLocationEdit; + QLabel *mAlarmBell; + QCheckBox *mAlarmButton; + QSpinBox *mAlarmTimeEdit; + QPushButton *mAlarmSoundButton; + QPushButton *mAlarmProgramButton; + QComboBox *mAlarmIncrCombo; + KTextEdit *mDescriptionEdit; + QLabel *mOwnerLabel; + QComboBox *mSecrecyCombo; + QCheckBox *mCancelBox; + QPushButton *mCategoriesButton; + QLabel *mCategoriesLabel; + + private: + QString mAlarmSound; + QString mAlarmProgram; +}; + +#endif diff --git a/korganizer/koeditorgeneral.moc b/korganizer/koeditorgeneral.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeditorgeneral.moc diff --git a/korganizer/koeditorgeneralevent.cpp b/korganizer/koeditorgeneralevent.cpp new file mode 100644 index 0000000..9b93e7e --- a/dev/null +++ b/korganizer/koeditorgeneralevent.cpp @@ -0,0 +1,443 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qtooltip.h> +#include <qlayout.h> +#include <qvbox.h> +#include <qbuttongroup.h> +#include <qvgroupbox.h> +#include <qwidgetstack.h> +#include <qdatetime.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kfiledialog.h> +#include <kstandarddirs.h> + +#include <libkcal/event.h> + +#include <libkdepim/kdateedit.h> + +#include "koprefs.h" + +#include "koeditorgeneralevent.h" +#include "kolocationbox.h" +#include "koeditorgeneralevent.moc" + +KOEditorGeneralEvent::KOEditorGeneralEvent(QObject* parent, + const char* name) : + KOEditorGeneral( parent, name) +{ + connect(this,SIGNAL(dateTimesChanged(QDateTime,QDateTime)), + SLOT(setDuration())); + connect(this,SIGNAL(dateTimesChanged(QDateTime,QDateTime)), + SLOT(emitDateTimeStr())); +} + +KOEditorGeneralEvent::~KOEditorGeneralEvent() +{ +} + +void KOEditorGeneralEvent::finishSetup() +{ + + //disabled +// QWidget::setTabOrder( mSummaryEdit, mLocationEdit ); +// QWidget::setTabOrder( mLocationEdit, mStartDateEdit ); +// QWidget::setTabOrder( mStartDateEdit, mStartTimeEdit ); +// QWidget::setTabOrder( mStartTimeEdit, mEndDateEdit ); +// QWidget::setTabOrder( mEndDateEdit, mEndTimeEdit ); +// QWidget::setTabOrder( mEndTimeEdit, mNoTimeButton ); +// QWidget::setTabOrder( mNoTimeButton, mAlarmButton ); +// QWidget::setTabOrder( mAlarmButton, mAlarmTimeEdit ); +// QWidget::setTabOrder( mFreeTimeCombo, mCategoriesButton ); +// QWidget::setTabOrder( mCategoriesButton, mSecrecyCombo ); +// QWidget::setTabOrder( mSecrecyCombo, mDescriptionEdit ); + + + + mSummaryEdit->load(KOLocationBox::SUMMARYEVENT); + mSummaryEdit->setFocus(); +} + +void KOEditorGeneralEvent::initTime(QWidget *parent,QBoxLayout *topLayout) +{ + QBoxLayout *timeLayout = new QVBoxLayout(topLayout); + + QGroupBox *timeGroupBox = new QGroupBox(1,QGroupBox::Horizontal, + i18n("Date && Time"),parent); + timeLayout->addWidget(timeGroupBox); + + timeGroupBox->layout()->setSpacing( 0 ); + timeGroupBox->layout()->setMargin( 5 ); + QFrame *timeBoxFrame = new QFrame(timeGroupBox); + + QGridLayout *layoutTimeBox = new QGridLayout(timeBoxFrame,2,3); + layoutTimeBox->setSpacing(topLayout->spacing()); + + mStartDateLabel = new QLabel(i18n("Start:"),timeBoxFrame); + layoutTimeBox->addWidget(mStartDateLabel,0,0); + + mStartDateEdit = new KDateEdit(timeBoxFrame); + layoutTimeBox->addWidget(mStartDateEdit,0,1); + + mStartTimeEdit = new KOTimeEdit(timeBoxFrame); + layoutTimeBox->addWidget(mStartTimeEdit,0,2); + + + mEndDateLabel = new QLabel(i18n("End:"),timeBoxFrame); + layoutTimeBox->addWidget(mEndDateLabel,1,0); + + mEndDateEdit = new KDateEdit(timeBoxFrame); + layoutTimeBox->addWidget(mEndDateEdit,1,1); + + mEndTimeEdit = new KOTimeEdit(timeBoxFrame); + layoutTimeBox->addWidget(mEndTimeEdit,1,2); + QWidget* duration = new QWidget( timeBoxFrame ); + QHBoxLayout *flagsBox = new QHBoxLayout( duration ); + mNoTimeButton = new QCheckBox(i18n("Allday"),duration); + flagsBox->addWidget(mNoTimeButton); + connect(mNoTimeButton, SIGNAL(toggled(bool)),SLOT(dontAssociateTime(bool))); + mDurationLabel = new QLabel( duration ); + // if ( KOPrefs::instance()->mCompactDialogs ) { + //layoutTimeBox->addMultiCellWidget( mDurationLabel, 3, 3, 0, 3 ); + //} else { + flagsBox->addWidget( mDurationLabel ); + //} + flagsBox->setStretchFactor(mDurationLabel, 10 ); + mDurationLabel->setAlignment( AlignRight | AlignVCenter); + layoutTimeBox->addMultiCellWidget( duration, 2, 2, 0, 3 ); + + // time widgets are checked if they contain a valid time + connect(mStartTimeEdit, SIGNAL(timeChanged(QTime)), + this, SLOT(startTimeChanged(QTime))); + connect(mEndTimeEdit, SIGNAL(timeChanged(QTime)), + this, SLOT(endTimeChanged(QTime))); + + // date widgets are checked if they contain a valid date + connect(mStartDateEdit, SIGNAL(dateChanged(QDate)), + this, SLOT(startDateChanged(QDate))); + connect(mEndDateEdit, SIGNAL(dateChanged(QDate)), + this, SLOT(endDateChanged(QDate))); +} + +void KOEditorGeneralEvent::initClass(QWidget *parent,QBoxLayout *topLayout) +{ + QBoxLayout *classLayout = new QHBoxLayout(topLayout); + + QLabel *freeTimeLabel = new QLabel(i18n("Show time as:"),parent); + classLayout->addWidget(freeTimeLabel); + + mFreeTimeCombo = new QComboBox(false, parent); + mFreeTimeCombo->insertItem(i18n("Busy")); + mFreeTimeCombo->insertItem(i18n("Free")); + classLayout->addWidget(mFreeTimeCombo); +} + +void KOEditorGeneralEvent::timeStuffDisable(bool disable) +{ + mStartTimeEdit->setEnabled( !disable ); + mEndTimeEdit->setEnabled( !disable ); + + setDuration(); + emitDateTimeStr(); +} + +void KOEditorGeneralEvent::dontAssociateTime(bool noTime) +{ + timeStuffDisable(noTime); + //if(alarmButton->isChecked()) alarmStuffDisable(noTime); + allDayChanged(noTime); +} + +void KOEditorGeneralEvent::setDateTimes(QDateTime start, QDateTime end) +{ +// kdDebug() << "KOEditorGeneralEvent::setDateTimes(): Start DateTime: " << start.toString() << endl; + + mStartDateEdit->setDate(start.date()); + // KTimeEdit seems to emit some signals when setTime() is called. + mStartTimeEdit->blockSignals( true ); + mStartTimeEdit->setTime(start.time()); + mStartTimeEdit->blockSignals( false ); + mEndDateEdit->setDate(end.date()); + mEndTimeEdit->setTime(end.time()); + + mCurrStartDateTime = start; + mCurrEndDateTime = end; + + setDuration(); + emitDateTimeStr(); +} + +void KOEditorGeneralEvent::startTimeChanged(QTime newtime) +{ + kdDebug() << "KOEditorGeneralEvent::startTimeChanged() " << newtime.toString() << endl; + + int secsep = mCurrStartDateTime.secsTo(mCurrEndDateTime); + + mCurrStartDateTime.setTime(newtime); + + // adjust end time so that the event has the same duration as before. + mCurrEndDateTime = mCurrStartDateTime.addSecs(secsep); + mEndTimeEdit->setTime(mCurrEndDateTime.time()); + mEndDateEdit->setDate(mCurrEndDateTime.date()); + + emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime); +} + +void KOEditorGeneralEvent::endTimeChanged(QTime newtime) +{ +// kdDebug() << "KOEditorGeneralEvent::endTimeChanged " << newtime.toString() << endl; + + QDateTime newdt(mCurrEndDateTime.date(), newtime); + mCurrEndDateTime = newdt; + + emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime); +} + +void KOEditorGeneralEvent::startDateChanged(QDate newdate) +{ + int daysep = mCurrStartDateTime.daysTo(mCurrEndDateTime); + + mCurrStartDateTime.setDate(newdate); + + // adjust end date so that the event has the same duration as before + mCurrEndDateTime.setDate(mCurrStartDateTime.date().addDays(daysep)); + mEndDateEdit->setDate(mCurrEndDateTime.date()); + + emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime); +} + +void KOEditorGeneralEvent::endDateChanged(QDate newdate) +{ + QDateTime newdt(newdate, mCurrEndDateTime.time()); + + if(newdt < mCurrStartDateTime) { + // oops, we can't let that happen. + newdt = mCurrStartDateTime; + mEndDateEdit->setDate(newdt.date()); + mEndTimeEdit->setTime(newdt.time()); + } + mCurrEndDateTime = newdt; + + emit dateTimesChanged(mCurrStartDateTime,mCurrEndDateTime); +} + +void KOEditorGeneralEvent::setDefaults(QDateTime from,QDateTime to,bool allDay) +{ + mSummaryEdit->load(KOLocationBox::SUMMARYEVENT); + mLocationEdit->load(KOLocationBox::LOCATION); + KOEditorGeneral::setDefaults(allDay); + + mNoTimeButton->setChecked(allDay); + timeStuffDisable(allDay); + mFreeTimeCombo->setCurrentItem( 0 ); + setDateTimes(from,to); +} + +void KOEditorGeneralEvent::readEvent( Event *event, bool tmpl ) +{ + QString tmpStr; + + if ( !tmpl ) { + // the rest is for the events only + mNoTimeButton->setChecked(event->doesFloat()); + timeStuffDisable(event->doesFloat()); + + setDateTimes(event->dtStart(),event->dtEnd()); + } + + switch( event->transparency() ) { + case Event::Transparent: + mFreeTimeCombo->setCurrentItem(1); + break; + case Event::Opaque: + mFreeTimeCombo->setCurrentItem(0); + break; + } + + mSummaryEdit->load(KOLocationBox::SUMMARYEVENT); + mLocationEdit->load(KOLocationBox::LOCATION); + readIncidence(event); +} + +void KOEditorGeneralEvent::writeEvent(Event *event) +{ +// kdDebug() << "KOEditorGeneralEvent::writeEvent()" << endl; + + writeIncidence(event); + + QDate tmpDate; + QTime tmpTime; + QDateTime tmpDT; + + // temp. until something better happens. + QString tmpStr; + + if (mNoTimeButton->isChecked()) { + event->setFloats(true); + // need to change this. + tmpDate = mStartDateEdit->date(); + tmpTime.setHMS(0,0,0); + tmpDT.setDate(tmpDate); + tmpDT.setTime(tmpTime); + event->setDtStart(tmpDT); + + tmpDate = mEndDateEdit->date(); + tmpTime.setHMS(0,0,0); + tmpDT.setDate(tmpDate); + tmpDT.setTime(tmpTime); + event->setDtEnd(tmpDT); + } else { + event->setFloats(false); + + // set date/time end + tmpDate = mEndDateEdit->date(); + tmpTime = mEndTimeEdit->getTime(); + tmpDT.setDate(tmpDate); + tmpDT.setTime(tmpTime); + event->setDtEnd(tmpDT); + + // set date/time start + tmpDate = mStartDateEdit->date(); + tmpTime = mStartTimeEdit->getTime(); + tmpDT.setDate(tmpDate); + tmpDT.setTime(tmpTime); + event->setDtStart(tmpDT); + } // check for float + mSummaryEdit->save(KOLocationBox::SUMMARYEVENT); + + event->setTransparency(mFreeTimeCombo->currentItem() > 0 + ? KCal::Event::Transparent + : KCal::Event::Opaque); + +// kdDebug() << "KOEditorGeneralEvent::writeEvent() done" << endl; +} + +void KOEditorGeneralEvent::setDuration() +{ + QString tmpStr = "", catStr; + int hourdiff, minutediff; + // end<date is an accepted temporary state while typing, but don't show + // any duration if this happens + if(mCurrEndDateTime >= mCurrStartDateTime) { + + if (mNoTimeButton->isChecked()) { + int daydiff = mCurrStartDateTime.date().daysTo(mCurrEndDateTime.date()) + 1; + tmpStr = i18n("Duration: "); + tmpStr.append(i18n("1 Day","%n Days",daydiff)); + } else { + int secto = mCurrStartDateTime.secsTo( mCurrEndDateTime ); + hourdiff = secto / 3600; + minutediff = (secto/60 ) % 60; + if (hourdiff || minutediff){ + tmpStr = i18n("Duration: "); + if (hourdiff){ + catStr = i18n("1 h","%n h",hourdiff); + tmpStr.append(catStr); + } + if (hourdiff && minutediff){ + tmpStr += i18n(", "); + } + if (minutediff){ + catStr = i18n("1 min","%n min",minutediff); + tmpStr += catStr; + } + } else tmpStr = ""; + } + } + mDurationLabel->setText(tmpStr); +} + +void KOEditorGeneralEvent::emitDateTimeStr() +{ + KLocale *l = KGlobal::locale(); + + QString from,to; + if (mNoTimeButton->isChecked()) { + from = l->formatDate(mCurrStartDateTime.date()); + to = l->formatDate(mCurrEndDateTime.date()); + } else { + from = l->formatDateTime(mCurrStartDateTime); + to = l->formatDateTime(mCurrEndDateTime); + } + + QString str = i18n("From: %1 To: %2 %3").arg(from).arg(to) + .arg(mDurationLabel->text()); + + emit dateTimeStrChanged(str); +} + +bool KOEditorGeneralEvent::validateInput() +{ +// kdDebug() << "KOEditorGeneralEvent::validateInput()" << endl; + + if (!mNoTimeButton->isChecked()) { + if (!mStartTimeEdit->inputIsValid()) { + KMessageBox::sorry( 0, + i18n("Please specify a valid start time, for example '%1'.") + .arg( KGlobal::locale()->formatTime( QTime::currentTime() ) ) ); + return false; + } + + if (!mEndTimeEdit->inputIsValid()) { + KMessageBox::sorry( 0, + i18n("Please specify a valid end time, for example '%1'.") + .arg( KGlobal::locale()->formatTime( QTime::currentTime() ) ) ); + return false; + } + } + + if (!mStartDateEdit->inputIsValid()) { + KMessageBox::sorry( 0, + i18n("Please specify a valid start date, for example '%1'.") + .arg( KGlobal::locale()->formatDate( QDate::currentDate() ) ) ); + return false; + } + + if (!mEndDateEdit->inputIsValid()) { + KMessageBox::sorry( 0, + i18n("Please specify a valid end date, for example '%1'.") + .arg( KGlobal::locale()->formatDate( QDate::currentDate() ) ) ); + return false; + } + + QDateTime startDt,endDt; + startDt.setDate(mStartDateEdit->date()); + endDt.setDate(mEndDateEdit->date()); + if (!mNoTimeButton->isChecked()) { + startDt.setTime(mStartTimeEdit->getTime()); + endDt.setTime(mEndTimeEdit->getTime()); + } + + if (startDt > endDt) { + KMessageBox::sorry(0,i18n("The event ends before it starts.\n" + "Please correct dates and times.")); + return false; + } + + return KOEditorGeneral::validateInput(); +} diff --git a/korganizer/koeditorgeneralevent.h b/korganizer/koeditorgeneralevent.h new file mode 100644 index 0000000..188dc93 --- a/dev/null +++ b/korganizer/koeditorgeneralevent.h @@ -0,0 +1,108 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOEDITORGENERALEVENT_H +#define _KOEDITORGENERALEVENT_H + +#include <qframe.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qmultilineedit.h> +#include <qlistview.h> +#include <qradiobutton.h> + +#include <krestrictedline.h> + +#include "koeditorgeneral.h" + +#include "ktimeedit.h" + +class KDateEdit; + +using namespace KCal; + +class KOEditorGeneralEvent : public KOEditorGeneral +{ + Q_OBJECT + public: + KOEditorGeneralEvent (QObject* parent=0,const char* name=0); + virtual ~KOEditorGeneralEvent(); + + void initTime(QWidget *,QBoxLayout *); + void initClass(QWidget *,QBoxLayout *); + + void finishSetup(); + + /** Set widgets to default values */ + void setDefaults(QDateTime from,QDateTime to,bool allDay); + /** + Read event object and setup widgets accordingly. If templ is true, the + event is read as template, i.e. the time and date information isn't set. + */ + void readEvent( Event *, bool tmpl = false ); + /** Write event settings to event object */ + void writeEvent(Event *); + + /** Check if the input is valid. */ + bool validateInput(); + + public slots: + void setDateTimes(QDateTime start, QDateTime end); + void setDuration(); + + protected slots: + void timeStuffDisable(bool disable); + void dontAssociateTime(bool noTime); + + void startTimeChanged(QTime); + void startDateChanged(QDate); + void endTimeChanged(QTime); + void endDateChanged(QDate); + + void emitDateTimeStr(); + + signals: + void dateTimesChanged(QDateTime start,QDateTime end); + void allDayChanged(bool); + void dateTimeStrChanged(const QString &); + + private: + QLabel *mStartDateLabel; + QLabel *mEndDateLabel; + KDateEdit *mStartDateEdit; + KDateEdit *mEndDateEdit; + KOTimeEdit *mStartTimeEdit; + KOTimeEdit *mEndTimeEdit; + QLabel *mDurationLabel; + QCheckBox *mNoTimeButton; + QComboBox *mFreeTimeCombo; + + // current start and end date and time + QDateTime mCurrStartDateTime; + QDateTime mCurrEndDateTime; +}; + +#endif diff --git a/korganizer/koeditorgeneralevent.moc b/korganizer/koeditorgeneralevent.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeditorgeneralevent.moc diff --git a/korganizer/koeditorgeneraltodo.cpp b/korganizer/koeditorgeneraltodo.cpp new file mode 100644 index 0000000..57837bb --- a/dev/null +++ b/korganizer/koeditorgeneraltodo.cpp @@ -0,0 +1,467 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qtooltip.h> +#include <qfiledialog.h> +#include <qlayout.h> +#include <qvbox.h> +#include <qbuttongroup.h> +#include <qvgroupbox.h> +#include <qwidgetstack.h> +#include <qdatetime.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kdebug.h> +#include <krestrictedline.h> +#include <kstandarddirs.h> +#include <kfiledialog.h> + +#include <libkcal/todo.h> + +#include <libkdepim/kdateedit.h> + +#include "koprefs.h" +#include "ktimeedit.h" + +#include "koeditorgeneraltodo.h" +#include "kolocationbox.h" +#include "koeditorgeneraltodo.moc" + +KOEditorGeneralTodo::KOEditorGeneralTodo(QObject* parent, + const char* name) + : KOEditorGeneral( parent, name) +{ +} + +KOEditorGeneralTodo::~KOEditorGeneralTodo() +{ +} + +void KOEditorGeneralTodo::finishSetup() +{ + +// QWidget::setTabOrder(mSummaryEdit, mLocationEdit); +// QWidget::setTabOrder(mLocationEdit, mDueCheck); +// QWidget::setTabOrder(mDueCheck, mDueDateEdit); +// QWidget::setTabOrder(mDueDateEdit, mDueTimeEdit); +// QWidget::setTabOrder(mDueTimeEdit, mStartCheck); +// QWidget::setTabOrder(mStartCheck, mStartDateEdit); +// QWidget::setTabOrder(mStartDateEdit, mStartTimeEdit); +// QWidget::setTabOrder(mStartTimeEdit, mTimeButton); +// QWidget::setTabOrder(mTimeButton, mCompletedCombo); +// QWidget::setTabOrder(mCompletedCombo, mPriorityCombo); +// QWidget::setTabOrder(mPriorityCombo, mAlarmButton); +// QWidget::setTabOrder(mAlarmButton, mCategoriesButton); +// QWidget::setTabOrder(mCategoriesButton, mSecrecyCombo); +// QWidget::setTabOrder(mSecrecyCombo, mDescriptionEdit); + mSummaryEdit->load(KOLocationBox::SUMMARYTODO); + mSummaryEdit->setFocus(); +} + +void KOEditorGeneralTodo::initTime(QWidget *parent,QBoxLayout *topLayout) +{ + QBoxLayout *timeLayout = new QVBoxLayout(topLayout); + + QGroupBox *timeGroupBox = new QGroupBox(1,QGroupBox::Horizontal, + i18n("Date && Time"),parent); + timeLayout->addWidget(timeGroupBox); + timeGroupBox->layout()->setSpacing( 0 ); + timeGroupBox->layout()->setMargin( 5 ); + QFrame *timeBoxFrame = new QFrame(timeGroupBox); + + QGridLayout *layoutTimeBox = new QGridLayout(timeBoxFrame,3,3); + layoutTimeBox->setSpacing(topLayout->spacing()); + layoutTimeBox->setColStretch( 1, 1 ); + + mDueCheck = new QCheckBox(i18n("Due:"),timeBoxFrame); + layoutTimeBox->addWidget(mDueCheck,0,0); + connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(enableDueEdit(bool))); + connect(mDueCheck,SIGNAL(toggled(bool)),SLOT(showAlarm())); + + + mDueDateEdit = new KDateEdit(timeBoxFrame); + layoutTimeBox->addWidget(mDueDateEdit,0,1); + + mDueTimeEdit = new KOTimeEdit(timeBoxFrame); + layoutTimeBox->addWidget(mDueTimeEdit,0,2); + + + mStartCheck = new QCheckBox(i18n("Start:"),timeBoxFrame); + layoutTimeBox->addWidget(mStartCheck,1,0); + connect(mStartCheck,SIGNAL(toggled(bool)),SLOT(enableStartEdit(bool))); + + mStartDateEdit = new KDateEdit(timeBoxFrame); + layoutTimeBox->addWidget(mStartDateEdit,1,1); + + mStartTimeEdit = new KOTimeEdit(timeBoxFrame); + layoutTimeBox->addWidget(mStartTimeEdit,1,2); + + + mTimeButton = new QCheckBox(i18n("Time associated"),timeBoxFrame); + layoutTimeBox->addMultiCellWidget(mTimeButton,2,2,0,1); + + connect(mTimeButton,SIGNAL(toggled(bool)),SLOT(enableTimeEdits(bool))); + + // some more layouting + //layoutTimeBox->setColStretch(3,1); +} + + +void KOEditorGeneralTodo::initCompletion(QWidget *parent, QBoxLayout *topLayout) +{ + mCompletedCombo = new QComboBox(parent); + // xgettext:no-c-format + mCompletedCombo->insertItem(i18n(" 0 %")); + // xgettext:no-c-format + mCompletedCombo->insertItem(i18n(" 20 %")); + // xgettext:no-c-format + mCompletedCombo->insertItem(i18n(" 40 %")); + // xgettext:no-c-format + mCompletedCombo->insertItem(i18n(" 60 %")); + // xgettext:no-c-format + mCompletedCombo->insertItem(i18n(" 80 %")); + // xgettext:no-c-format + mCompletedCombo->insertItem(i18n("100 %")); + connect(mCompletedCombo,SIGNAL(activated(int)),SLOT(completedChanged(int))); + topLayout->addWidget(mCompletedCombo); + + mCompletedLabel = new QLabel(i18n("completed"),parent); + topLayout->addWidget(mCompletedLabel); +} + +void KOEditorGeneralTodo::initPriority(QWidget *parent, QBoxLayout *topLayout) +{ + + QHBox* h = new QHBox ( parent ); + topLayout->addWidget( h ); + QLabel *priorityLabel = new QLabel(i18n("Priority:"), h); + // topLayout->addWidget(priorityLabel); + + mPriorityCombo = new QComboBox( h ); + mPriorityCombo->insertItem(i18n("1 (high)")); + mPriorityCombo->insertItem(i18n("2")); + mPriorityCombo->insertItem(i18n("3")); + mPriorityCombo->insertItem(i18n("4")); + mPriorityCombo->insertItem(i18n("5 (low)")); + //topLayout->addWidget(mPriorityCombo); +} + +void KOEditorGeneralTodo::initStatus(QWidget *parent,QBoxLayout *topLayout) +{ + QBoxLayout *statusLayout = new QHBoxLayout(topLayout); + + initCompletion( parent, statusLayout ); + + statusLayout->addStretch( 1 ); + + initPriority( parent, statusLayout ); +} + +void KOEditorGeneralTodo::setDefaults(QDateTime due,bool allDay) +{ + + mSummaryEdit->load(KOLocationBox::SUMMARYTODO); + mLocationEdit->load(KOLocationBox::LOCATION); + KOEditorGeneral::setDefaults(allDay); + + mTimeButton->setChecked( !allDay ); + if(mTimeButton->isChecked()) { + mTimeButton->setEnabled(true); + } + else { + mTimeButton->setEnabled(false); + } + + enableTimeEdits( !allDay ); + + mDueCheck->setChecked(false); + enableDueEdit(false); + + alarmDisable(true); + + mStartCheck->setChecked(false); + enableStartEdit(false); + + mDueDateEdit->setDate(due.date()); + mDueTimeEdit->setTime(due.time()); + + mStartDateEdit->setDate(QDate::currentDate()); + mStartTimeEdit->setTime(QTime::currentTime()); + + mPriorityCombo->setCurrentItem(2); + mCompletedLabel->setText(i18n("completed"));; + mCompletedCombo->setCurrentItem(0); +} + +void KOEditorGeneralTodo::readTodo(Todo *todo) +{ + + mSummaryEdit->load(KOLocationBox::SUMMARYTODO); + mLocationEdit->load(KOLocationBox::LOCATION); + KOEditorGeneral::readIncidence(todo); + + QDateTime dueDT; + + if (todo->hasDueDate()) { + enableAlarmEdit(true); + dueDT = todo->dtDue(); + mDueDateEdit->setDate(todo->dtDue().date()); + mDueTimeEdit->setTime(todo->dtDue().time()); + mDueCheck->setChecked(true); + } else { + alarmDisable(true); + mDueDateEdit->setEnabled(false); + mDueTimeEdit->setEnabled(false); + mDueDateEdit->setDate(QDate::currentDate()); + mDueTimeEdit->setTime(QTime::currentTime()); + mDueCheck->setChecked(false); + } + + if (todo->hasStartDate()) { + mStartDateEdit->setDate(todo->dtStart().date()); + mStartTimeEdit->setTime(todo->dtStart().time()); + mStartCheck->setChecked(true); + } else { + mStartDateEdit->setEnabled(false); + mStartTimeEdit->setEnabled(false); + mStartDateEdit->setDate(QDate::currentDate()); + mStartTimeEdit->setTime(QTime::currentTime()); + mStartCheck->setChecked(false); + } + + mTimeButton->setChecked( !todo->doesFloat() ); + + mCompletedCombo->setCurrentItem(todo->percentComplete() / 20); + if (todo->isCompleted() && todo->hasCompletedDate()) { + mCompleted = todo->completed(); + } + setCompletedDate(); + + mPriorityCombo->setCurrentItem(todo->priority()-1); +} + +void KOEditorGeneralTodo::writeTodo(Todo *todo) +{ + KOEditorGeneral::writeIncidence(todo); + + // temp. until something better happens. + QString tmpStr; + + todo->setHasDueDate(mDueCheck->isChecked()); + todo->setHasStartDate(mStartCheck->isChecked()); + + QDate tmpDate; + QTime tmpTime; + QDateTime tmpDT; + if ( mTimeButton->isChecked() ) { + todo->setFloats(false); + + // set due date/time + tmpDate = mDueDateEdit->date(); + tmpTime = mDueTimeEdit->getTime(); + tmpDT.setDate(tmpDate); + tmpDT.setTime(tmpTime); + todo->setDtDue(tmpDT); + + // set start date/time + tmpDate = mStartDateEdit->date(); + tmpTime = mStartTimeEdit->getTime(); + tmpDT.setDate(tmpDate); + tmpDT.setTime(tmpTime); + todo->setDtStart(tmpDT); + } else { + todo->setFloats(true); + + // need to change this. + tmpDate = mDueDateEdit->date(); + tmpTime.setHMS(0,0,0); + tmpDT.setDate(tmpDate); + tmpDT.setTime(tmpTime); + todo->setDtDue(tmpDT); + + tmpDate = mStartDateEdit->date(); + tmpTime.setHMS(0,0,0); + tmpDT.setDate(tmpDate); + tmpDT.setTime(tmpTime); + todo->setDtStart(tmpDT); + } + + todo->setPriority(mPriorityCombo->currentItem()+1); + + // set completion state + todo->setPercentComplete(mCompletedCombo->currentItem() * 20); + + if (mCompletedCombo->currentItem() == 5 && mCompleted.isValid()) { + todo->setCompleted(mCompleted); + } + mSummaryEdit->save(KOLocationBox::SUMMARYTODO); +} + +void KOEditorGeneralTodo::enableDueEdit(bool enable) +{ + mDueDateEdit->setEnabled( enable ); + + if(mDueCheck->isChecked() || mStartCheck->isChecked()) { + mTimeButton->setEnabled(true); + } + else { + mTimeButton->setEnabled(false); + mTimeButton->setChecked(false); + } + + if (enable) { + mDueTimeEdit->setEnabled( mTimeButton->isChecked() ); + } else { + mDueTimeEdit->setEnabled( false ); + } +} + +void KOEditorGeneralTodo::enableStartEdit( bool enable ) +{ + mStartDateEdit->setEnabled( enable ); + + if(mDueCheck->isChecked() || mStartCheck->isChecked()) { + mTimeButton->setEnabled(true); + } + else { + mTimeButton->setEnabled(false); + mTimeButton->setChecked(false); + } + + if (enable) { + mStartTimeEdit->setEnabled( mTimeButton->isChecked() ); + } else { + mStartTimeEdit->setEnabled( false ); + } +} + +void KOEditorGeneralTodo::enableTimeEdits(bool enable) +{ + if(mStartCheck->isChecked()) { + mStartTimeEdit->setEnabled( enable ); + } + if(mDueCheck->isChecked()) { + mDueTimeEdit->setEnabled( enable ); + } +} + +void KOEditorGeneralTodo::showAlarm() +{ + if ( mDueCheck->isChecked() ) { + alarmDisable(false); + } + else { + alarmDisable(true); + } +} + +bool KOEditorGeneralTodo::validateInput() +{ + if (mDueCheck->isChecked()) { + if (!mDueDateEdit->inputIsValid()) { + KMessageBox::sorry(0,i18n("Please specify a valid due date.")); + return false; + } + if (mTimeButton->isChecked()) { + if (!mDueTimeEdit->inputIsValid()) { + KMessageBox::sorry(0,i18n("Please specify a valid due time.")); + return false; + } + } + } + + if (mStartCheck->isChecked()) { + if (!mStartDateEdit->inputIsValid()) { + KMessageBox::sorry(0,i18n("Please specify a valid start date.")); + return false; + } + if (mTimeButton->isChecked()) { + if (!mStartTimeEdit->inputIsValid()) { + KMessageBox::sorry(0,i18n("Please specify a valid start time.")); + return false; + } + } + } + + if (mStartCheck->isChecked() && mDueCheck->isChecked()) { + QDateTime startDate; + QDateTime dueDate; + startDate.setDate(mStartDateEdit->date()); + dueDate.setDate(mDueDateEdit->date()); + if (mTimeButton->isChecked()) { + startDate.setTime(mStartTimeEdit->getTime()); + dueDate.setTime(mDueTimeEdit->getTime()); + } + if (startDate > dueDate) { + KMessageBox::sorry(0, + i18n("The start date cannot be after the due date.")); + return false; + } + } + + return KOEditorGeneral::validateInput(); +} + +void KOEditorGeneralTodo::completedChanged(int index) +{ + if (index == 5) { + mCompleted = QDateTime::currentDateTime(); + } + setCompletedDate(); +} + +void KOEditorGeneralTodo::setCompletedDate() +{ + if (mCompletedCombo->currentItem() == 5 && mCompleted.isValid()) { + mCompletedLabel->setText(i18n("completed on %1") + .arg(KGlobal::locale()->formatDateTime(mCompleted))); + } else { + mCompletedLabel->setText(i18n("completed")); + } +} + +void KOEditorGeneralTodo::modified (Todo* todo, int modification) +{ + switch (modification) { + case KOGlobals::PRIORITY_MODIFIED: + mPriorityCombo->setCurrentItem(todo->priority()-1); + break; + case KOGlobals::COMPLETION_MODIFIED: + mCompletedCombo->setCurrentItem(todo->percentComplete() / 20); + if (todo->isCompleted() && todo->hasCompletedDate()) { + mCompleted = todo->completed(); + } + setCompletedDate(); + break; + case KOGlobals::CATEGORY_MODIFIED: + setCategories (todo->categoriesStr ()); + break; + case KOGlobals::UNKNOWN_MODIFIED: // fall through + default: + readTodo( todo ); + break; + } +} diff --git a/korganizer/koeditorgeneraltodo.h b/korganizer/koeditorgeneraltodo.h new file mode 100644 index 0000000..f6c30f8 --- a/dev/null +++ b/korganizer/koeditorgeneraltodo.h @@ -0,0 +1,105 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOEDITORGENERALTODO_H +#define _KOEDITORGENERALTODO_H + +#include <qframe.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qmultilineedit.h> +#include <qlistview.h> +#include <qradiobutton.h> + +#include "koeditorgeneral.h" +#include "koglobals.h" + +class KRestrictedLine; + +class KDateEdit; + +using namespace KCal; + +class KOEditorGeneralTodo : public KOEditorGeneral +{ + Q_OBJECT + public: + KOEditorGeneralTodo (QObject* parent=0,const char* name=0); + virtual ~KOEditorGeneralTodo(); + + void initTime(QWidget *, QBoxLayout *); + void initStatus(QWidget *, QBoxLayout *); + void initCompletion(QWidget *, QBoxLayout *); + void initPriority(QWidget *, QBoxLayout *); + + void finishSetup(); + + /** Set widgets to default values */ + void setDefaults(QDateTime due,bool allDay); + /** Read todo object and setup widgets accordingly */ + void readTodo(Todo *); + /** Write todo settings to event object */ + void writeTodo(Todo *); + + /** Check if the input is valid. */ + bool validateInput(); + + /** The todo has been modified externally */ + void modified (Todo*, int); + + signals: + void openCategoryDialog(); + + protected slots: + void completedChanged(int); + + void enableDueEdit( bool enable ); + void enableStartEdit( bool enable ); + void enableTimeEdits( bool enable ); + void showAlarm(); + + protected: + void setCompletedDate(); + + private: + KDateEdit *mStartDateEdit; + KOTimeEdit *mStartTimeEdit; + QCheckBox *mTimeButton; + QCheckBox *mDueCheck; + KDateEdit *mDueDateEdit; + KOTimeEdit *mDueTimeEdit; + QComboBox *mCompletedCombo; + QLabel *mCompletedLabel; + QLabel *mPriorityLabel; + QComboBox *mPriorityCombo; + + QCheckBox *mStartCheck; + + QDateTime mCompleted; +}; + + +#endif diff --git a/korganizer/koeditorgeneraltodo.moc b/korganizer/koeditorgeneraltodo.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeditorgeneraltodo.moc diff --git a/korganizer/koeditorrecurrence.cpp b/korganizer/koeditorrecurrence.cpp new file mode 100644 index 0000000..d82172f --- a/dev/null +++ b/korganizer/koeditorrecurrence.cpp @@ -0,0 +1,1117 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qtooltip.h> +#include <qfiledialog.h> +#include <qlayout.h> +#include <qvbox.h> +#include <qbuttongroup.h> +#include <qvgroupbox.h> +#include <qwidgetstack.h> +#include <qdatetime.h> +#include <qlistbox.h> +#include <qspinbox.h> +#include <qcheckbox.h> +#include <qapplication.h> + +#include <kdialog.h> +#include <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kdebug.h> +#include <knumvalidator.h> + +#include <libkcal/event.h> + +#include <libkdepim/kdateedit.h> + +#include "koprefs.h" + +#include "koeditorrecurrence.h" +#include "koeditorrecurrence.moc" + +/////////////////////////// RecurBase /////////////////////////////// + +RecurBase::RecurBase( QWidget *parent, const char *name ) : + QWidget( parent, name ) +{ + mFrequencyEdit = new QSpinBox( 1, 9999, 1, this ); + mFrequencyEdit->setValue( 1 ); +} + +QWidget *RecurBase::frequencyEdit() +{ + return mFrequencyEdit; +} + +void RecurBase::setFrequency( int f ) +{ + if ( f < 1 ) f = 1; + + mFrequencyEdit->setValue( f ); +} + +int RecurBase::frequency() +{ + return mFrequencyEdit->value(); +} + +/////////////////////////// RecurDaily /////////////////////////////// + +RecurDaily::RecurDaily( QWidget *parent, const char *name ) : + RecurBase( parent, name ) +{ + QBoxLayout *topLayout = new QHBoxLayout( this ); + topLayout->setSpacing( KDialog::spacingHint() ); + + QLabel *preLabel = new QLabel( i18n("Recur every"), this ); + topLayout->addWidget( preLabel ); + + topLayout->addWidget( frequencyEdit() ); + + QLabel *postLabel = new QLabel( i18n("day(s)"), this ); + topLayout->addWidget( postLabel ); +} + + +/////////////////////////// RecurWeekly /////////////////////////////// + +RecurWeekly::RecurWeekly( QWidget *parent, const char *name ) : + RecurBase( parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); + topLayout->setSpacing( KDialog::spacingHint() ); + + topLayout->addStretch( 1 ); + + QBoxLayout *weeksLayout = new QHBoxLayout( topLayout ); + + QLabel *preLabel = new QLabel( i18n("Recur every"), this ); + weeksLayout->addWidget( preLabel ); + + weeksLayout->addWidget( frequencyEdit() ); + + QLabel *postLabel = new QLabel( i18n("week(s) on:"), this ); + weeksLayout->addWidget( postLabel ); + + QHBox *dayBox = new QHBox( this ); + topLayout->addWidget( dayBox, 1, AlignVCenter ); + // TODO: Respect start of week setting + for ( int i = 0; i < 7; ++i ) { + QString weekDayName = KGlobal::locale()->weekDayName( i + 1, true ); + if ( KOPrefs::instance()->mCompactDialogs ) { + weekDayName = weekDayName.left( 1 ); + } + mDayBoxes[ i ] = new QCheckBox( weekDayName, dayBox ); + } + + topLayout->addStretch( 1 ); +} + +void RecurWeekly::setDays( const QBitArray &days ) +{ + for ( int i = 0; i < 7; ++i ) { + mDayBoxes[ i ]->setChecked( days.testBit( i ) ); + } +} + +QBitArray RecurWeekly::days() +{ + QBitArray days( 7 ); + + for ( int i = 0; i < 7; ++i ) { + days.setBit( i, mDayBoxes[ i ]->isChecked() ); + } + + return days; +} + +/////////////////////////// RecurMonthly /////////////////////////////// + +RecurMonthly::RecurMonthly( QWidget *parent, const char *name ) : + RecurBase( parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); + topLayout->setSpacing( KDialog::spacingHint() ); + + + QBoxLayout *freqLayout = new QHBoxLayout( topLayout ); + + QLabel *preLabel = new QLabel( i18n("every"), this ); + freqLayout->addWidget( preLabel ); + + freqLayout->addWidget( frequencyEdit() ); + + QLabel *postLabel = new QLabel( i18n("month(s)"), this ); + freqLayout->addWidget( postLabel ); + + + QButtonGroup *buttonGroup = new QButtonGroup( this ); + buttonGroup->setFrameStyle( QFrame::NoFrame ); + topLayout->addWidget( buttonGroup, 1, AlignVCenter ); + + QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 ); + buttonLayout->setSpacing( KDialog::spacingHint() ); + + + QString recurOnText; + if ( !KOPrefs::instance()->mCompactDialogs ) { + recurOnText = i18n("Recur on the"); + } + + mByDayRadio = new QRadioButton( recurOnText, buttonGroup ); + buttonLayout->addWidget( mByDayRadio, 0, 0 ); + + mByDayCombo = new QComboBox( buttonGroup ); + mByDayCombo->setSizeLimit( 7 ); + mByDayCombo->insertItem( i18n("1st") ); + mByDayCombo->insertItem( i18n("2nd") ); + mByDayCombo->insertItem( i18n("3rd") ); + mByDayCombo->insertItem( i18n("4th") ); + mByDayCombo->insertItem( i18n("5th") ); + mByDayCombo->insertItem( i18n("6th") ); + mByDayCombo->insertItem( i18n("7th") ); + mByDayCombo->insertItem( i18n("8th") ); + mByDayCombo->insertItem( i18n("9th") ); + mByDayCombo->insertItem( i18n("10th") ); + mByDayCombo->insertItem( i18n("11th") ); + mByDayCombo->insertItem( i18n("12th") ); + mByDayCombo->insertItem( i18n("13th") ); + mByDayCombo->insertItem( i18n("14th") ); + mByDayCombo->insertItem( i18n("15th") ); + mByDayCombo->insertItem( i18n("16th") ); + mByDayCombo->insertItem( i18n("17th") ); + mByDayCombo->insertItem( i18n("18th") ); + mByDayCombo->insertItem( i18n("19th") ); + mByDayCombo->insertItem( i18n("20th") ); + mByDayCombo->insertItem( i18n("21st") ); + mByDayCombo->insertItem( i18n("22nd") ); + mByDayCombo->insertItem( i18n("23rd") ); + mByDayCombo->insertItem( i18n("24th") ); + mByDayCombo->insertItem( i18n("25th") ); + mByDayCombo->insertItem( i18n("26th") ); + mByDayCombo->insertItem( i18n("27th") ); + mByDayCombo->insertItem( i18n("28th") ); + mByDayCombo->insertItem( i18n("29th") ); + mByDayCombo->insertItem( i18n("30th") ); + mByDayCombo->insertItem( i18n("31st") ); + buttonLayout->addWidget( mByDayCombo, 0, 1 ); + + QLabel *byDayLabel = new QLabel( i18n("day"), buttonGroup ); + buttonLayout->addWidget( byDayLabel, 0, 2 ); + + + mByPosRadio = new QRadioButton( recurOnText, buttonGroup); + buttonLayout->addWidget( mByPosRadio, 1, 0 ); + + mByPosCountCombo = new QComboBox( buttonGroup ); + mByPosCountCombo->insertItem( i18n("1st") ); + mByPosCountCombo->insertItem( i18n("2nd") ); + mByPosCountCombo->insertItem( i18n("3rd") ); + mByPosCountCombo->insertItem( i18n("4th") ); + mByPosCountCombo->insertItem( i18n("5th") ); + buttonLayout->addWidget( mByPosCountCombo, 1, 1 ); + + mByPosWeekdayCombo = new QComboBox( buttonGroup ); + mByPosWeekdayCombo->insertItem( i18n("Monday") ); + mByPosWeekdayCombo->insertItem( i18n("Tuesday") ); + mByPosWeekdayCombo->insertItem( i18n("Wednesday") ); + mByPosWeekdayCombo->insertItem( i18n("Thursday") ); + mByPosWeekdayCombo->insertItem( i18n("Friday") ); + mByPosWeekdayCombo->insertItem( i18n("Saturday") ); + mByPosWeekdayCombo->insertItem( i18n("Sunday") ); + buttonLayout->addWidget( mByPosWeekdayCombo, 1, 2 ); +} + +void RecurMonthly::setByDay( int day ) +{ + mByDayRadio->setChecked( true ); + mByDayCombo->setCurrentItem( day ); +} + +void RecurMonthly::setByPos( int count, int weekday ) +{ + mByPosRadio->setChecked( true ); + mByPosCountCombo->setCurrentItem( count ); + mByPosWeekdayCombo->setCurrentItem( weekday ); +} + +bool RecurMonthly::byDay() +{ + return mByDayRadio->isChecked(); +} + +bool RecurMonthly::byPos() +{ + return mByPosRadio->isChecked(); +} + +int RecurMonthly::day() +{ + return mByDayCombo->currentItem() + 1; +} + +int RecurMonthly::count() +{ + return mByPosCountCombo->currentItem() + 1; +} + +int RecurMonthly::weekday() +{ + return mByPosWeekdayCombo->currentItem(); +} + +/////////////////////////// RecurYearly /////////////////////////////// + +RecurYearly::RecurYearly( QWidget *parent, const char *name ) : + RecurBase( parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); + topLayout->setSpacing( KDialog::spacingHint() ); + + + QBoxLayout *freqLayout = new QHBoxLayout( topLayout ); + + QLabel *preLabel = new QLabel( i18n("every"), this ); + freqLayout->addWidget( preLabel ); + + freqLayout->addWidget( frequencyEdit() ); + + QLabel *postLabel = new QLabel( i18n("year(s)"), this ); + freqLayout->addWidget( postLabel ); + + + QButtonGroup *buttonGroup = new QButtonGroup( this ); + buttonGroup->setFrameStyle( QFrame::NoFrame ); + topLayout->addWidget( buttonGroup, 1, AlignVCenter ); + + QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 ); + + QString recurInMonthText; + if ( !KOPrefs::instance()->mCompactDialogs ) { + recurInMonthText = i18n("Recur in the month of"); + } + + mByMonthRadio = new QRadioButton( recurInMonthText, buttonGroup); + buttonLayout->addWidget( mByMonthRadio, 0, 0 ); + + mByMonthCombo = new QComboBox( buttonGroup ); + mByMonthCombo->insertItem( i18n("January") ); + mByMonthCombo->insertItem( i18n("February") ); + mByMonthCombo->insertItem( i18n("March") ); + mByMonthCombo->insertItem( i18n("April") ); + mByMonthCombo->insertItem( i18n("May") ); + mByMonthCombo->insertItem( i18n("June") ); + mByMonthCombo->insertItem( i18n("July") ); + mByMonthCombo->insertItem( i18n("August") ); + mByMonthCombo->insertItem( i18n("September") ); + mByMonthCombo->insertItem( i18n("October") ); + mByMonthCombo->insertItem( i18n("November") ); + mByMonthCombo->insertItem( i18n("December") ); + buttonLayout->addWidget( mByMonthCombo, 0, 1 ); + + mByMonthCombo->setSizeLimit( 6 ); + + buttonLayout->setRowStretch( 1, 1 ); + + QString recurOnDayText; + if ( KOPrefs::instance()->mCompactDialogs ) { + recurOnDayText = i18n("This day"); + } else { + recurOnDayText = i18n("Recur on this day"); + } + + mByDayRadio = new QRadioButton( recurOnDayText, buttonGroup); + buttonLayout->addMultiCellWidget( mByDayRadio, 2, 2, 0, 1 ); +} + +void RecurYearly::setByDay() +{ + mByDayRadio->setChecked( true ); +} + +void RecurYearly::setByMonth( int month ) +{ + mByMonthRadio->setChecked( true ); + mByMonthCombo->setCurrentItem( month - 1 ); +} + +bool RecurYearly::byMonth() +{ + return mByMonthRadio->isChecked(); +} + +bool RecurYearly::byDay() +{ + return mByDayRadio->isChecked(); +} + +int RecurYearly::month() +{ + return mByMonthCombo->currentItem() + 1; +} + +//////////////////////////// ExceptionsWidget ////////////////////////// + +ExceptionsWidget::ExceptionsWidget( QWidget *parent, const char *name ) : + QWidget( parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); + + QGroupBox *groupBox = new QGroupBox( 1, Horizontal, i18n("Exceptions"), + this ); + topLayout->addWidget( groupBox ); + + QWidget *box = new QWidget( groupBox ); + + QGridLayout *boxLayout = new QGridLayout( box ); + + mExceptionDateEdit = new KDateEdit( box ); + boxLayout->addWidget( mExceptionDateEdit, 0, 0 ); + + QPushButton *addExceptionButton = new QPushButton( i18n("Add"), box ); + boxLayout->addWidget( addExceptionButton, 1, 0 ); + QPushButton *changeExceptionButton = new QPushButton( i18n("Change"), box ); + boxLayout->addWidget( changeExceptionButton, 2, 0 ); + QPushButton *deleteExceptionButton = new QPushButton( i18n("Delete"), box ); + boxLayout->addWidget( deleteExceptionButton, 3, 0 ); + + mExceptionList = new QListBox( box ); + boxLayout->addMultiCellWidget( mExceptionList, 0, 3, 1, 1 ); + + boxLayout->setRowStretch( 4, 1 ); + boxLayout->setColStretch( 1, 3 ); + + connect( addExceptionButton, SIGNAL( clicked() ), + SLOT( addException() ) ); + connect( changeExceptionButton, SIGNAL( clicked() ), + SLOT( changeException() ) ); + connect( deleteExceptionButton, SIGNAL( clicked() ), + SLOT( deleteException() ) ); + if ( QApplication::desktop()->width() < 480 ) { + setMinimumWidth( 220 ); + } else { + setMinimumWidth( 440 ); + mExceptionDateEdit->setMinimumWidth( 200 ); + } +} + +void ExceptionsWidget::setDefaults( const QDateTime &from ) +{ + mExceptionDateEdit->setDate( from.date() ); +} + +void ExceptionsWidget::addException() +{ + QDate date = mExceptionDateEdit->date(); + QString dateStr = KGlobal::locale()->formatDate( date ); + if( !mExceptionList->findItem( dateStr ) ) { + mExceptionDates.append( date ); + mExceptionList->insertItem( dateStr ); + } +} + +void ExceptionsWidget::changeException() +{ + int pos = mExceptionList->currentItem(); + if ( pos < 0 ) return; + + QDate date = mExceptionDateEdit->date(); + mExceptionDates[ pos ] = date; + mExceptionList->changeItem( KGlobal::locale()->formatDate( date ), pos ); +} + +void ExceptionsWidget::deleteException() +{ + int pos = mExceptionList->currentItem(); + if ( pos < 0 ) return; + + mExceptionDates.remove( mExceptionDates.at( pos ) ); + mExceptionList->removeItem( pos ); +} + +void ExceptionsWidget::setDates( const DateList &dates ) +{ + mExceptionList->clear(); + mExceptionDates.clear(); + DateList::ConstIterator dit; + for ( dit = dates.begin(); dit != dates.end(); ++dit ) { + mExceptionList->insertItem( KGlobal::locale()->formatDate(* dit ) ); + mExceptionDates.append( *dit ); + } +} + +DateList ExceptionsWidget::dates() +{ + return mExceptionDates; +} + +///////////////////////// ExceptionsDialog /////////////////////////// + +ExceptionsDialog::ExceptionsDialog( QWidget *parent, const char *name ) : + KDialogBase( parent, name, true, i18n("Edit exceptions"), Ok|Cancel ) +{ + mExceptions = new ExceptionsWidget( this ); + setMainWidget( mExceptions ); + resize(220,10); +} + +void ExceptionsDialog::setDefaults( const QDateTime &from ) +{ + mExceptions->setDefaults( from ); +} + +void ExceptionsDialog::setDates( const DateList &dates ) +{ + mExceptions->setDates( dates ); +} + +DateList ExceptionsDialog::dates() +{ + return mExceptions->dates(); +} + +///////////////////////// RecurrenceRangeWidget /////////////////////////// + +RecurrenceRangeWidget::RecurrenceRangeWidget( QWidget *parent, + const char *name ) + : QWidget( parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); + + mRangeGroupBox = new QGroupBox( 1, Horizontal, i18n("Recurrence Range"), + this ); + topLayout->addWidget( mRangeGroupBox ); + + QWidget *rangeBox = new QWidget( mRangeGroupBox ); + QVBoxLayout *rangeLayout = new QVBoxLayout( rangeBox ); + rangeLayout->setSpacing( KDialog::spacingHint() ); + + mStartDateLabel = new QLabel( i18n("Begin on:"), rangeBox ); + rangeLayout->addWidget( mStartDateLabel ); + + QButtonGroup *rangeButtonGroup = new QButtonGroup; + + mNoEndDateButton = new QRadioButton( i18n("No ending date"), rangeBox ); + rangeButtonGroup->insert( mNoEndDateButton ); + rangeLayout->addWidget( mNoEndDateButton ); + + QBoxLayout *durationLayout = new QHBoxLayout( rangeLayout ); + durationLayout->setSpacing( KDialog::spacingHint() ); + + mEndDurationButton = new QRadioButton( i18n("End after"), rangeBox ); + rangeButtonGroup->insert( mEndDurationButton ); + durationLayout->addWidget( mEndDurationButton ); + + mEndDurationEdit = new QSpinBox( 1, 9999, 1, rangeBox ); + durationLayout->addWidget( mEndDurationEdit ); + + QLabel *endDurationLabel = new QLabel( i18n("occurrence(s)"), rangeBox ); + durationLayout ->addWidget( endDurationLabel ); + + QBoxLayout *endDateLayout = new QHBoxLayout( rangeLayout ); + endDateLayout->setSpacing( KDialog::spacingHint() ); + + mEndDateButton = new QRadioButton( i18n("End by:"), rangeBox ); + rangeButtonGroup->insert( mEndDateButton ); + endDateLayout->addWidget( mEndDateButton ); + + mEndDateEdit = new KDateEdit( rangeBox ); + endDateLayout->addWidget( mEndDateEdit ); + + endDateLayout->addStretch( 1 ); + + connect( mNoEndDateButton, SIGNAL( toggled( bool ) ), + SLOT( showCurrentRange() ) ); + connect( mEndDurationButton, SIGNAL( toggled( bool ) ), + SLOT( showCurrentRange() ) ); + connect( mEndDateButton, SIGNAL( toggled( bool ) ), + SLOT( showCurrentRange() ) ); +} + +void RecurrenceRangeWidget::setDefaults( const QDateTime &from ) +{ + mNoEndDateButton->setChecked( true ); + + setDateTimes( from ); + mEndDateEdit->setDate( from.date() ); +} + +void RecurrenceRangeWidget::setDuration( int duration ) +{ + if ( duration == -1 ) { + mNoEndDateButton->setChecked( true ); + } else if ( duration == 0 ) { + mEndDateButton->setChecked( true ); + } else { + mEndDurationButton->setChecked( true ); + mEndDurationEdit->setValue( duration ); + } +} + +int RecurrenceRangeWidget::duration() +{ + if ( mNoEndDateButton->isChecked() ) { + return -1; + } else if ( mEndDurationButton->isChecked() ) { + return mEndDurationEdit->value(); + } else { + return 0; + } +} + +void RecurrenceRangeWidget::setEndDate( const QDate &date ) +{ + mEndDateEdit->setDate( date ); +} + +QDate RecurrenceRangeWidget::endDate() +{ + return mEndDateEdit->date(); +} + +void RecurrenceRangeWidget::showCurrentRange() +{ + mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() ); + mEndDateEdit->setEnabled( mEndDateButton->isChecked() ); +} + +void RecurrenceRangeWidget::setDateTimes( const QDateTime &start, + const QDateTime & ) +{ + mStartDateLabel->setText( i18n("Start date: %1") + .arg( KGlobal::locale()->formatDate( start.date() ) ) ); + + if(!mEndDateButton->isChecked()) + mEndDateEdit->setDate( start.date() ); +} + +///////////////////////// RecurrenceRangeDialog /////////////////////////// + +RecurrenceRangeDialog::RecurrenceRangeDialog( QWidget *parent, + const char *name ) : + KDialogBase( parent, name, true, i18n("Edit Recurrence Range"), Ok|Cancel ) +{ + mRecurrenceRangeWidget = new RecurrenceRangeWidget( this ); + setMainWidget( mRecurrenceRangeWidget ); +} + +void RecurrenceRangeDialog::setDefaults( const QDateTime &from ) +{ + mRecurrenceRangeWidget->setDefaults( from ); +} + +void RecurrenceRangeDialog::setDuration( int duration ) +{ + mRecurrenceRangeWidget->setDuration( duration ); +} + +int RecurrenceRangeDialog::duration() +{ + return mRecurrenceRangeWidget->duration(); +} + +void RecurrenceRangeDialog::setEndDate( const QDate &date ) +{ + mRecurrenceRangeWidget->setEndDate( date ); +} + +QDate RecurrenceRangeDialog::endDate() +{ + return mRecurrenceRangeWidget->endDate(); +} + +void RecurrenceRangeDialog::setDateTimes( const QDateTime &start, + const QDateTime &end ) +{ + mRecurrenceRangeWidget->setDateTimes( start, end ); +} + +//////////////////////////// RecurrenceChooser //////////////////////// + +RecurrenceChooser::RecurrenceChooser( QWidget *parent, const char *name ) : + QWidget( parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); + + if ( KOPrefs::instance()->mCompactDialogs ) { + mTypeCombo = new QComboBox( this ); + mTypeCombo->insertItem( i18n("Daily") ); + mTypeCombo->insertItem( i18n("Weekly") ); + mTypeCombo->insertItem( i18n("Monthly") ); + mTypeCombo->insertItem( i18n("Yearly") ); + + topLayout->addWidget( mTypeCombo ); + + connect( mTypeCombo, SIGNAL( activated( int ) ), SLOT( emitChoice() ) ); + } else { + mTypeCombo = 0; + + QButtonGroup *ruleButtonGroup = new QButtonGroup( 1, Horizontal, this ); + ruleButtonGroup->setFrameStyle( QFrame::NoFrame ); + topLayout->addWidget( ruleButtonGroup ); + + mDailyButton = new QRadioButton( i18n("Daily"), ruleButtonGroup ); + mWeeklyButton = new QRadioButton( i18n("Weekly"), ruleButtonGroup ); + mMonthlyButton = new QRadioButton( i18n("Monthly"), ruleButtonGroup ); + mYearlyButton = new QRadioButton( i18n("Yearly"), ruleButtonGroup ); + + connect( mDailyButton, SIGNAL( toggled( bool ) ), + SLOT( emitChoice() ) ); + connect( mWeeklyButton, SIGNAL( toggled( bool ) ), + SLOT( emitChoice() ) ); + connect( mMonthlyButton, SIGNAL( toggled( bool ) ), + SLOT( emitChoice() ) ); + connect( mYearlyButton, SIGNAL( toggled( bool ) ), + SLOT( emitChoice() ) ); + } +} + +int RecurrenceChooser::type() +{ + if ( mTypeCombo ) { + return mTypeCombo->currentItem(); + } else { + if ( mDailyButton->isChecked() ) return Daily; + else if ( mWeeklyButton->isChecked() ) return Weekly; + else if ( mMonthlyButton->isChecked() ) return Monthly; + else return Yearly; + } +} + +void RecurrenceChooser::setType( int type ) +{ + if ( mTypeCombo ) { + mTypeCombo->setCurrentItem( type ); + } else { + switch ( type ) { + case Daily: + mDailyButton->setChecked( true ); + break; + case Weekly: + mWeeklyButton->setChecked( true ); + break; + case Monthly: + mMonthlyButton->setChecked( true ); + break; + case Yearly: + default: + mYearlyButton->setChecked( true ); + break; + } + } +} + +void RecurrenceChooser::emitChoice() +{ + emit chosen ( type() ); +} + +/////////////////////////////// Main Widget ///////////////////////////// + +KOEditorRecurrence::KOEditorRecurrence( QWidget* parent, const char *name ) : + QWidget( parent, name ) +{ + QGridLayout *topLayout = new QGridLayout( this, 2,2 ); + topLayout->setSpacing( KDialog::spacingHint() ); + + mEnabledCheck = new QCheckBox( i18n("Enable Recurrence"), this ); + connect( mEnabledCheck, SIGNAL( toggled( bool ) ), + SLOT( setEnabled( bool ) ) ); + topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 ); + + + mTimeGroupBox = new QGroupBox( 1, Horizontal, i18n("Appointment Time "), + this ); + topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 ); + + if ( KOPrefs::instance()->mCompactDialogs ) { + mTimeGroupBox->hide(); + } + +// QFrame *timeFrame = new QFrame( mTimeGroupBox ); +// QBoxLayout *layoutTimeFrame = new QHBoxLayout( timeFrame ); +// layoutTimeFrame->setSpacing( KDialog::spacingHint() ); + + mDateTimeLabel = new QLabel( mTimeGroupBox ); +// mDateTimeLabel = new QLabel( timeFrame ); +// layoutTimeFrame->addWidget( mDateTimeLabel ); + + Qt::Orientation orientation; + if ( KOPrefs::instance()->mCompactDialogs ) orientation = Horizontal; + else orientation = Vertical; + + mRuleBox = new QGroupBox( 1, orientation, i18n("Recurrence Rule"), this ); + if ( KOPrefs::instance()->mCompactDialogs ) { + topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 ); + } else { + topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 ); + } + + mRecurrenceChooser = new RecurrenceChooser( mRuleBox ); + connect( mRecurrenceChooser, SIGNAL( chosen( int ) ), + SLOT( showCurrentRule( int ) ) ); + + if ( !KOPrefs::instance()->mCompactDialogs ) { + QFrame *ruleSepFrame = new QFrame( mRuleBox ); + ruleSepFrame->setFrameStyle( QFrame::VLine | QFrame::Sunken ); + } + + mRuleStack = new QWidgetStack( mRuleBox ); + + mDaily = new RecurDaily( mRuleStack ); + mRuleStack->addWidget( mDaily, 0 ); + + mWeekly = new RecurWeekly( mRuleStack ); + mRuleStack->addWidget( mWeekly, 0 ); + + mMonthly = new RecurMonthly( mRuleStack ); + mRuleStack->addWidget( mMonthly, 0 ); + + mYearly = new RecurYearly( mRuleStack ); + mRuleStack->addWidget( mYearly, 0 ); + + showCurrentRule( mRecurrenceChooser->type() ); + + if ( KOPrefs::instance()->mCompactDialogs ) { + mRecurrenceRangeWidget = 0; + mRecurrenceRangeDialog = new RecurrenceRangeDialog( this ); + mRecurrenceRange = mRecurrenceRangeDialog; + mRecurrenceRangeButton = new QPushButton( i18n("Recurrence Range..."), + this ); + + connect( mRecurrenceRangeButton, SIGNAL( clicked() ), + SLOT( showRecurrenceRangeDialog() ) ); + + mExceptionsWidget = 0; + mExceptionsDialog = new ExceptionsDialog( this ); + mExceptions = mExceptionsDialog; + mExceptionsButton = new QPushButton( i18n("Exceptions..."), this ); + if ( QApplication::desktop()->width() < 320 ) { + topLayout->addMultiCellWidget( mRecurrenceRangeButton, 3, 3, 0, 1 ); + topLayout->addMultiCellWidget( mExceptionsButton, 4, 4, 0, 1 ); + } else { + topLayout->addWidget( mRecurrenceRangeButton, 3, 0 ); + topLayout->addWidget( mExceptionsButton, 3, 1 ); + } + connect( mExceptionsButton, SIGNAL( clicked() ), + SLOT( showExceptionsDialog() ) ); + + } else { + mRecurrenceRangeWidget = new RecurrenceRangeWidget( this ); + mRecurrenceRangeDialog = 0; + mRecurrenceRange = mRecurrenceRangeWidget; + mRecurrenceRangeButton = 0; + topLayout->addWidget( mRecurrenceRangeWidget, 3, 0 ); + + mExceptionsWidget = new ExceptionsWidget( this ); + mExceptionsDialog = 0; + mExceptions = mExceptionsWidget; + mExceptionsButton = 0; + topLayout->addWidget( mExceptionsWidget, 3, 1 ); + } +} + +KOEditorRecurrence::~KOEditorRecurrence() +{ +} + +void KOEditorRecurrence::setEnabled( bool enabled ) +{ +// kdDebug() << "KOEditorRecurrence::setEnabled(): " << (enabled ? "on" : "off") << endl; + + mTimeGroupBox->setEnabled( enabled ); + if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled ); + if ( mRecurrenceRangeButton ) mRecurrenceRangeButton->setEnabled( enabled ); + if ( mExceptionsWidget ) mExceptionsWidget->setEnabled( enabled ); + if ( mExceptionsButton ) mExceptionsButton->setEnabled( enabled ); +} + +void KOEditorRecurrence::showCurrentRule( int current ) +{ + switch ( current ) { + case Daily: + mRuleStack->raiseWidget( mDaily ); + break; + case Weekly: + mRuleStack->raiseWidget( mWeekly ); + break; + case Monthly: + mRuleStack->raiseWidget( mMonthly ); + break; + default: + case Yearly: + mRuleStack->raiseWidget( mYearly ); + break; + } +} + +void KOEditorRecurrence::setDateTimes( QDateTime start, QDateTime end ) +{ +// kdDebug() << "KOEditorRecurrence::setDateTimes" << endl; + + mRecurrenceRange->setDateTimes( start, end ); + mExceptions->setDefaults( end ); + +} + +void KOEditorRecurrence::setDefaults( QDateTime from, QDateTime to, bool ) +{ + + // qDebug("KOEditorRecurrence::setDefaults %s %s ",from.toString().latin1(),to.toString().latin1() ); + setDateTimes( from, to ); + + bool enabled = false; + mEnabledCheck->setChecked( enabled ); + setEnabled( enabled ); + + mExceptions->setDefaults( to ); + mRecurrenceRange->setDefaults( to ); + + mRecurrenceChooser->setType( RecurrenceChooser::Weekly ); + showCurrentRule( mRecurrenceChooser->type() ); + + mDaily->setFrequency( 1 ); + + mWeekly->setFrequency( 1 ); + QBitArray days( 7 ); + days.fill( 0 ); + mWeekly->setDays( days ); + + mMonthly->setFrequency( 1 ); + mMonthly->setByDay( from.date().day()-1 ); + + mYearly->setFrequency( 1 ); + mYearly->setByDay(); +} + +void KOEditorRecurrence::readEvent(Event *event) +{ + QBitArray rDays( 7 ); + QPtrList<Recurrence::rMonthPos> rmp; + QPtrList<int> rmd; + int day = 0; + int count = 0; + int month = 0; + setDateTimes( event->dtStart(), event->dtEnd() ); + + Recurrence *r = event->recurrence(); + int f = r->frequency(); + + int recurs = r->doesRecur(); + + mEnabledCheck->setChecked( recurs ); + setEnabled( recurs ); + + int recurrenceType = RecurrenceChooser::Weekly; + + switch ( recurs ) { + case Recurrence::rNone: + setDefaults( event->dtStart(), event->dtEnd(), true ); + break; + case Recurrence::rDaily: + recurrenceType = RecurrenceChooser::Daily; + mDaily->setFrequency( f ); + break; + case Recurrence::rWeekly: + recurrenceType = RecurrenceChooser::Weekly; + mWeekly->setFrequency( f ); + mWeekly->setDays( r->days() ); + break; + case Recurrence::rMonthlyPos: + // we only handle one possibility in the list right now, + // so I have hardcoded calls with first(). If we make the GUI + // more extended, this can be changed. + recurrenceType = RecurrenceChooser::Monthly; + + rmp = r->monthPositions(); + if ( rmp.first()->negative ) + count = 5 - rmp.first()->rPos - 1; + else + count = rmp.first()->rPos - 1; + day = 0; + while ( !rmp.first()->rDays.testBit( day ) ) ++day; + mMonthly->setByPos( count, day ); + + mMonthly->setFrequency( f ); + + break; + case Recurrence::rMonthlyDay: + recurrenceType = RecurrenceChooser::Monthly; + + rmd = r->monthDays(); + day = *rmd.first() - 1; + mMonthly->setByDay( day ); + + mMonthly->setFrequency( f ); + + break; + case Recurrence::rYearlyMonth: + case Recurrence::rYearlyDay: + recurrenceType = RecurrenceChooser::Yearly; + + rmd = r->yearNums(); + month = *rmd.first(); + if ( month == event->dtStart().date().month() ) { + mYearly->setByDay(); + } else { + mYearly->setByMonth( month ); + } + + mYearly->setFrequency( f ); + break; + default: + setDefaults( event->dtStart(), event->dtEnd(), true ); + break; + } + + mRecurrenceChooser->setType( recurrenceType ); + showCurrentRule( recurrenceType ); + + mRecurrenceRange->setDateTimes( event->dtStart() ); + + if ( r->doesRecur() ) { + mRecurrenceRange->setDuration( r->duration() ); + if ( r->duration() == 0 ) + { + if ( r->endDate() < event->dtStart().date() ) + mRecurrenceRange->setEndDate( event->dtStart().date() ); + else + mRecurrenceRange->setEndDate( r->endDate() ); + } else + mRecurrenceRange->setEndDate( event->dtStart().date() ); + } + + mExceptions->setDates( event->exDates() ); +} + +void KOEditorRecurrence::writeEvent( Event *event ) +{ + Recurrence *r = event->recurrence(); + + // clear out any old settings; + r->unsetRecurs(); + + if ( mEnabledCheck->isChecked() ) { + int duration = mRecurrenceRange->duration(); + QDate endDate; + if ( duration == 0 ) endDate = mRecurrenceRange->endDate(); + + int recurrenceType = mRecurrenceChooser->type(); + + if ( recurrenceType == RecurrenceChooser::Daily ) { + int freq = mDaily->frequency(); + if ( duration != 0 ) r->setDaily( freq, duration ); + else r->setDaily( freq, endDate ); + } else if ( recurrenceType == RecurrenceChooser::Weekly ) { + int freq = mWeekly->frequency(); + QBitArray days = mWeekly->days(); + int j; + bool found = false; + for (j = 0; j < 7 ; ++j ) { + found |=days.at(j); + } + if ( !found ) { + days.setBit( event->dtStart().date().dayOfWeek()-1); + qDebug("bit set %d "); + } + if ( duration != 0 ) r->setWeekly( freq, days, duration ); + else r->setWeekly( freq, days, endDate ); + } else if ( recurrenceType == RecurrenceChooser::Monthly ) { + int freq = mMonthly->frequency(); + if ( mMonthly->byPos() ) { + int pos = mMonthly->count(); + + QBitArray days( 7 ); + days.fill( false ); + + days.setBit( mMonthly->weekday() ); + if ( duration != 0 ) + r->setMonthly( Recurrence::rMonthlyPos, freq, duration ); + else + r->setMonthly( Recurrence::rMonthlyPos, freq, endDate ); + r->addMonthlyPos( pos, days ); + } else { + // it's by day + int day = mMonthly->day(); + + if ( duration != 0 ) { + r->setMonthly( Recurrence::rMonthlyDay, freq, duration ); + } else { + r->setMonthly( Recurrence::rMonthlyDay, freq, endDate ); + } + r->addMonthlyDay( day ); + } + } else if ( recurrenceType == RecurrenceChooser::Yearly ) { + int freq = mYearly->frequency(); + + int month; + if ( mYearly->byMonth() ) { + month = mYearly->month(); + } else { + month = event->dtStart().date().month(); + } + if ( duration != 0 ) { + r->setYearly( Recurrence::rYearlyMonth, freq, duration ); + } else { + r->setYearly( Recurrence::rYearlyMonth, freq, endDate ); + } + + r->addYearlyNum( month ); + } + + event->setExDates( mExceptions->dates() ); + } +} + +void KOEditorRecurrence::setDateTimeStr( const QString &str ) +{ + mDateTimeLabel->setText( str ); +} + +bool KOEditorRecurrence::validateInput() +{ + // Check input here + + return true; +} + +void KOEditorRecurrence::showExceptionsDialog() +{ + DateList dates = mExceptions->dates(); + int result = mExceptionsDialog->exec(); + if ( result == QDialog::Rejected ) mExceptions->setDates( dates ); +} + +void KOEditorRecurrence::showRecurrenceRangeDialog() +{ + int duration = mRecurrenceRange->duration(); + QDate endDate = mRecurrenceRange->endDate(); + + int result = mRecurrenceRangeDialog->exec(); + if ( result == QDialog::Rejected ) { + mRecurrenceRange->setDuration( duration ); + mRecurrenceRange->setEndDate( endDate ); + } + +} diff --git a/korganizer/koeditorrecurrence.h b/korganizer/koeditorrecurrence.h new file mode 100644 index 0000000..4f0f0b2 --- a/dev/null +++ b/korganizer/koeditorrecurrence.h @@ -0,0 +1,321 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOEDITORRECURRENCE_H +#define _KOEDITORRECURRENCE_H + +#include <qframe.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qmultilineedit.h> +#include <qlistview.h> +#include <qradiobutton.h> + +#include <kdialogbase.h> + +#include <libkcal/event.h> + +#include "ktimeedit.h" + +class QWidgetStack; +class QSpinBox; + +class KDateEdit; + +using namespace KCal; + +class RecurBase : public QWidget +{ + public: + RecurBase( QWidget *parent = 0, const char *name = 0 ); + + void setFrequency( int ); + int frequency(); + + QWidget *frequencyEdit(); + + private: + QSpinBox *mFrequencyEdit; +}; + +class RecurDaily : public RecurBase +{ + public: + RecurDaily( QWidget *parent = 0, const char *name = 0 ); +}; + +class RecurWeekly : public RecurBase +{ + public: + RecurWeekly( QWidget *parent = 0, const char *name = 0 ); + + void setDays( const QBitArray & ); + QBitArray days(); + + private: + QCheckBox *mDayBoxes[7]; +}; + +class RecurMonthly : public RecurBase +{ + public: + RecurMonthly( QWidget *parent = 0, const char *name = 0 ); + + void setByDay( int day ); + void setByPos( int count, int weekday ); + + bool byDay(); + bool byPos(); + + int day(); + + int count(); + int weekday(); + + private: + QRadioButton *mByDayRadio; + QComboBox *mByDayCombo; + + QRadioButton *mByPosRadio; + QComboBox *mByPosCountCombo; + QComboBox *mByPosWeekdayCombo; +}; + +class RecurYearly : public RecurBase +{ + public: + RecurYearly( QWidget *parent = 0, const char *name = 0 ); + + void setByDay(); + void setByMonth( int month ); + + bool byMonth(); + bool byDay(); + + int month(); + + private: + QRadioButton *mByMonthRadio; + QComboBox *mByMonthCombo; + + QRadioButton *mByDayRadio; +}; + +class RecurrenceChooser : public QWidget +{ + Q_OBJECT + public: + RecurrenceChooser( QWidget *parent = 0, const char *name = 0 ); + + enum { Daily, Weekly, Monthly, Yearly }; + + void setType( int ); + int type(); + + signals: + void chosen( int ); + + protected slots: + void emitChoice(); + + private: + QComboBox *mTypeCombo; + + QRadioButton *mDailyButton; + QRadioButton *mWeeklyButton; + QRadioButton *mMonthlyButton; + QRadioButton *mYearlyButton; +}; + +class ExceptionsBase +{ + public: + virtual void setDefaults( const QDateTime &from ) = 0; + virtual void setDates( const DateList & ) = 0; + virtual DateList dates() = 0; +}; + +class ExceptionsWidget : public QWidget, public ExceptionsBase +{ + Q_OBJECT + public: + ExceptionsWidget( QWidget *parent = 0, const char *name = 0 ); + + void setDefaults( const QDateTime &from ); + + void setDates( const DateList & ); + DateList dates(); + + protected slots: + void addException(); + void changeException(); + void deleteException(); + + private: + KDateEdit *mExceptionDateEdit; + QListBox *mExceptionList; + DateList mExceptionDates; +}; + +class ExceptionsDialog : public KDialogBase, public ExceptionsBase +{ + public: + ExceptionsDialog( QWidget *parent, const char *name = 0 ); + + void setDefaults( const QDateTime &from ); + + void setDates( const DateList & ); + DateList dates(); + + private: + ExceptionsWidget *mExceptions; +}; + +class RecurrenceRangeBase +{ + public: + virtual void setDefaults( const QDateTime &from ) = 0; + + virtual void setDuration( int ) = 0; + virtual int duration() = 0; + + virtual void setEndDate( const QDate & ) = 0; + virtual QDate endDate() = 0; + + virtual void setDateTimes( const QDateTime &start, + const QDateTime &end = QDateTime() ) = 0; +}; + +class RecurrenceRangeWidget : public QWidget, public RecurrenceRangeBase +{ + Q_OBJECT + public: + RecurrenceRangeWidget( QWidget *parent = 0, const char *name = 0 ); + + void setDefaults( const QDateTime &from ); + + void setDuration( int ); + int duration(); + + void setEndDate( const QDate & ); + QDate endDate(); + + void setDateTimes( const QDateTime &start, + const QDateTime &end = QDateTime() ); + + protected slots: + void showCurrentRange(); + + private: + QGroupBox *mRangeGroupBox; + QLabel *mStartDateLabel; + QRadioButton *mNoEndDateButton; + QRadioButton *mEndDurationButton; + QSpinBox *mEndDurationEdit; + QRadioButton *mEndDateButton; + KDateEdit *mEndDateEdit; +}; + +class RecurrenceRangeDialog : public KDialogBase, public RecurrenceRangeBase +{ + public: + RecurrenceRangeDialog( QWidget *parent = 0, const char *name = 0 ); + + void setDefaults( const QDateTime &from ); + + void setDuration( int ); + int duration(); + + void setEndDate( const QDate & ); + QDate endDate(); + + void setDateTimes( const QDateTime &start, + const QDateTime &end = QDateTime() ); + + private: + RecurrenceRangeWidget *mRecurrenceRangeWidget; +}; + +class KOEditorRecurrence : public QWidget +{ + Q_OBJECT + public: + KOEditorRecurrence ( QWidget *parent = 0, const char *name = 0 ); + virtual ~KOEditorRecurrence(); + + enum { Daily, Weekly, Monthly, Yearly }; + + /** Set widgets to default values */ + void setDefaults( QDateTime from, QDateTime to, bool allday ); + /** Read event object and setup widgets accordingly */ + void readEvent( Event * ); + /** Write event settings to event object */ + void writeEvent( Event * ); + + /** Check if the input is valid. */ + bool validateInput(); + + public slots: + void setEnabled( bool ); + void setDateTimes( QDateTime start, QDateTime end ); + void setDateTimeStr( const QString & ); + + signals: + void dateTimesChanged( QDateTime start, QDateTime end ); + + protected slots: + void showCurrentRule( int ); + void showExceptionsDialog(); + void showRecurrenceRangeDialog(); + + private: + QCheckBox *mEnabledCheck; + + QGroupBox *mTimeGroupBox; + QLabel *mDateTimeLabel; + + QGroupBox *mRuleBox; + QWidgetStack *mRuleStack; + RecurrenceChooser *mRecurrenceChooser; + + RecurDaily *mDaily; + RecurWeekly *mWeekly; + RecurMonthly *mMonthly; + RecurYearly *mYearly; + + RecurrenceRangeBase *mRecurrenceRange; + RecurrenceRangeWidget *mRecurrenceRangeWidget; + RecurrenceRangeDialog *mRecurrenceRangeDialog; + QPushButton *mRecurrenceRangeButton; + + ExceptionsBase *mExceptions; + ExceptionsDialog *mExceptionsDialog; + ExceptionsWidget *mExceptionsWidget; + QPushButton *mExceptionsButton; + +}; + +#endif diff --git a/korganizer/koeditorrecurrence.moc b/korganizer/koeditorrecurrence.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeditorrecurrence.moc diff --git a/korganizer/koeventeditor.cpp b/korganizer/koeventeditor.cpp new file mode 100644 index 0000000..b3edec6 --- a/dev/null +++ b/korganizer/koeventeditor.cpp @@ -0,0 +1,378 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001,2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qtooltip.h> +#include <qframe.h> +#include <qpixmap.h> +#include <qhbox.h> +#include <qdir.h> +#include <qlayout.h> +#include <qwidgetstack.h> +#include <qapplication.h> + +#include <kiconloader.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <klocale.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <libkcal/calendarresources.h> +#include <libkcal/resourcecalendar.h> +#include <kresources/resourceselectdialog.h> + +#include <libkdepim/categoryselectdialog.h> +#include <libkcal/calendarlocal.h> +#include <libkcal/icalformat.h> + +#include "koprefs.h" + +#include "koeventeditor.h" +#include "koeventeditor.moc" +extern int globalFlagBlockAgenda; + +KOEventEditor::KOEventEditor( Calendar *calendar, QWidget *parent ) : + KOIncidenceEditor( i18n("Edit Event"), calendar, parent ) +{ + mEvent = 0; + init(); +} + +KOEventEditor::~KOEventEditor() +{ + //emit dialogClose( mEvent ); +} + +void KOEventEditor::init() +{ + + setupGeneral(); + setupAttendeesTab(); + setupRecurrence(); + + // Propagate date time settings to recurrence tab + connect(mGeneral,SIGNAL(dateTimesChanged(QDateTime,QDateTime)), + mRecurrence,SLOT(setDateTimes(QDateTime,QDateTime))); + connect(mGeneral,SIGNAL(dateTimeStrChanged(const QString &)), + mRecurrence,SLOT(setDateTimeStr(const QString &))); + + // Category dialog + // connect(mGeneral,SIGNAL(openCategoryDialog()),mCategoryDialog,SLOT(show())); + //connect(mCategoryDialog,SIGNAL(categoriesSelected(const QString &)), + // mGeneral,SLOT(setCategories(const QString &))); + + +} + +void KOEventEditor::reload() +{ + if ( mEvent ) readEvent( mEvent ); +} + +void KOEventEditor::setSecrecy( int sec ) +{ + mGeneral->setSecrecy( sec ); +} +void KOEventEditor::setCategories( QString s ) +{ + mGeneral->setCategories(s); + +} +void KOEventEditor::setupGeneral() +{ + mGeneral = new KOEditorGeneralEvent( this, "KOEditorGeneralEvent" ); + connect ( mGeneral, SIGNAL ( allAccepted() ), this, SLOT ( slotOk () ) ); + + if( KOPrefs::instance()->mCompactDialogs ) { + QFrame *topFrame = addPage(i18n("General")); + QBoxLayout *topLayout = new QVBoxLayout(topFrame); + topLayout->setSpacing(spacingHint()-1); + topLayout->setMargin(marginHint()-1); + mGeneral->initHeader(topFrame,topLayout); + mGeneral->initTime(topFrame,topLayout); +// QBoxLayout *alarmLineLayout = new QHBoxLayout(topLayout); + mGeneral->initAlarm(topFrame,topLayout); + mGeneral->enableAlarm( false ); + + QBoxLayout *buttonLayout; + if ( QApplication::desktop()->width() < 500 ) + buttonLayout = new QVBoxLayout( topLayout ); + else + buttonLayout = new QHBoxLayout( topLayout ); + QHBox* buttonWidget = new QHBox (topFrame); + QIconSet icon; + if ( QApplication::desktop()->width() < 321 ) + icon = SmallIcon("fileexport16"); + else + icon = SmallIcon("fileexport"); + QPushButton * loadTemplate = new QPushButton( buttonWidget); + QPushButton * saveTemplate = new QPushButton( buttonWidget); + saveTemplate->setIconSet (icon ) ; + int size = saveTemplate->sizeHint().height(); + saveTemplate->setFixedSize( size, size ); + if ( QApplication::desktop()->width() < 321 ) + icon = SmallIcon("fileimport16"); + else + icon = SmallIcon("fileimport"); + loadTemplate->setIconSet (icon ) ; + loadTemplate->setFixedSize( size, size ); + buttonLayout->addWidget( buttonWidget ); + mGeneral->initCategories( topFrame, buttonLayout ); + + topLayout->addStretch( 1 ); + + QFrame *topFrame2 = addPage(i18n("Details")); + + QBoxLayout *topLayout2 = new QVBoxLayout(topFrame2); + topLayout2->setSpacing(spacingHint()); + + mGeneral->initClass(topFrame2,topLayout2); + mGeneral->initSecrecy( topFrame2, topLayout2 ); + mGeneral->initDescription(topFrame2,topLayout2); + + connect( saveTemplate, SIGNAL( clicked() ), this , SLOT( slotSaveTemplate() ) ); + connect( loadTemplate, SIGNAL( clicked() ), this , SLOT( slotLoadTemplate() ) ); + } else { + QFrame *topFrame = addPage(i18n("General")); + + QBoxLayout *topLayout = new QVBoxLayout(topFrame); + topLayout->setSpacing(spacingHint()); + + mGeneral->initHeader(topFrame,topLayout); + mGeneral->initTime(topFrame,topLayout); + QBoxLayout *alarmLineLayout = new QHBoxLayout(topLayout); + mGeneral->initAlarm(topFrame,alarmLineLayout); + mGeneral->initClass(topFrame,alarmLineLayout); + mGeneral->initDescription(topFrame,topLayout); + QBoxLayout *detailsLayout = new QHBoxLayout(topLayout); + mGeneral->initCategories( topFrame, detailsLayout ); + mGeneral->initSecrecy( topFrame, detailsLayout ); + } + + mGeneral->finishSetup(); + +} + +void KOEventEditor::setupRecurrence() +{ + QFrame *topFrame = addPage( i18n("Recurrence") ); + QBoxLayout *topLayout = new QVBoxLayout( topFrame ); + + mRecurrence = new KOEditorRecurrence( topFrame ); + topLayout->addWidget( mRecurrence ); +} + +void KOEventEditor::editEvent(Event *event, bool showDescription) +{ + // init(); + + mEvent = event; + readEvent(mEvent); + qApp->processEvents(); + if ( showDescription ) { + showPage( 1 ); + mGeneral->setFocusOn( 1 ); + } else { + showPage( 0 ); + mGeneral->setFocusOn( 2 ); + } +} + +void KOEventEditor::newEvent( QDateTime from, QDateTime to, bool allDay ) +{ + // init(); + + mEvent = 0; + setDefaults(from,to,allDay); +} + +void KOEventEditor::loadDefaults() +{ + int fmt = KOPrefs::instance()->mStartTime; + + QDateTime from(QDate::currentDate(), QTime(fmt,0,0)); + QDateTime to(QDate::currentDate(), + QTime(fmt+KOPrefs::instance()->mDefaultDuration,0,0)); + + setDefaults(from,to,false); +} + +bool KOEventEditor::processInput( bool emitTime ) +{ + if (!validateInput()) return false; + + Event *event = 0; + + if (mEvent) event = mEvent; + else { + event = new Event; + event->setOrganizer(KOPrefs::instance()->email()); + } + + writeEvent(event); + if ( emitTime ) { + globalFlagBlockAgenda = 1; + emit showAgendaView( false ); + emit jumpToTime( event->dtStart().date() ); + globalFlagBlockAgenda = 2; + + } + if (mEvent) { + event->setRevision(event->revision()+1); + emit eventChanged(event); + } else { + mCalendar->addEvent(event); + mEvent = event; + emit eventAdded(event); + } + + return true; +} + +void KOEventEditor::deleteEvent() +{ + kdDebug() << "Delete event" << endl; + + if (mEvent) { + if (KOPrefs::instance()->mConfirm) { + switch (msgItemDelete()) { + case KMessageBox::Continue: // OK + emit eventToBeDeleted(mEvent); + emit dialogClose(mEvent); + mCalendar->deleteEvent(mEvent); + emit eventDeleted(); + reject(); + break; + } + } + else { + emit eventToBeDeleted(mEvent); + emit dialogClose(mEvent); + mCalendar->deleteEvent(mEvent); + emit eventDeleted(); + reject(); + } + } else { + reject(); + } +} + +void KOEventEditor::setDefaults(QDateTime from, QDateTime to, bool allDay) +{ + mGeneral->setDefaults(from,to,allDay); + mDetails->setDefaults(); + mRecurrence->setDefaults(from,to,allDay); + showPage( 0 ); + mGeneral->setFocusOn( 2 ); +} + +void KOEventEditor::readEvent( Event *event, bool tmpl ) +{ + mGeneral->readEvent( event, tmpl ); + mDetails->readEvent( event ); + mRecurrence->readEvent( event ); + + // categories + //mCategoryDialog->setSelected( event->categories() ); +} + +void KOEventEditor::writeEvent(Event *event) +{ + mGeneral->writeEvent( event ); + mDetails->writeEvent( event ); + + if ( event->organizer() == KOPrefs::instance()->email() ) { + Event *ev = new Event( *event ); + ev->registerObserver(0); + mDetails->cancelAttendeeEvent( ev ); + if ( ev->attendeeCount() > 0 ) { + emit deleteAttendee( ev ); + } + delete(ev); + } + + mRecurrence->writeEvent(event); +} + +bool KOEventEditor::validateInput() +{ + if (!mGeneral->validateInput()) return false; + if (!mDetails->validateInput()) return false; + if (!mRecurrence->validateInput()) return false; + return true; +} + +int KOEventEditor::msgItemDelete() +{ + return KMessageBox::warningContinueCancel(this, + i18n("This item will be permanently deleted."), + i18n("KOrganizer Confirmation"),i18n("Delete")); +} + +void KOEventEditor::slotLoadTemplate() +{ + + QString fileName =locateLocal( "templates", "events" ); + QDir t_dir; + if ( !t_dir.exists(fileName) ) + t_dir.mkdir ( fileName ); + fileName += "/event"; + fileName = KFileDialog::getSaveFileName( fileName , "Load Event template", this ); + if ( fileName.length() == 0 ) + return; + CalendarLocal cal; + ICalFormat format; + if ( !format.load( &cal, fileName ) ) { + KMessageBox::error( this, i18n("Error loading template file\n '%1'.") + .arg( fileName ) ); + return ; + } + QPtrList<Event> events = cal.events(); + Event* event = events.first(); + if ( !event ) { + KMessageBox::error( this, + i18n("Template does not contain\na valid Event.")); + } else { + kdDebug() << "KOEventEditor::slotLoadTemplate(): readTemplate" << endl; + readEvent( event, true ); + } +} + + +void KOEventEditor::slotSaveTemplate() +{ + QString fileName =locateLocal( "templates", "events" ); + QDir t_dir; + if ( !t_dir.exists(fileName) ) + t_dir.mkdir ( fileName ); + fileName += "/event"; + fileName = KFileDialog::getSaveFileName( fileName , "Save as Event template", this ); + if ( fileName.length() > 0 ) + saveTemplate( fileName ); +} + +void KOEventEditor::saveTemplate( const QString &templateName ) +{ + Event *event = new Event; + writeEvent( event ); + saveAsTemplate( event, templateName ); +} diff --git a/korganizer/koeventeditor.h b/korganizer/koeventeditor.h new file mode 100644 index 0000000..5303c27 --- a/dev/null +++ b/korganizer/koeventeditor.h @@ -0,0 +1,118 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOEVENTEDITOR_H +#define _KOEVENTEDITOR_H + +#include <kdialogbase.h> + +#include <qdatetime.h> + +#include <libkcal/calendar.h> + +#include "koeditorgeneralevent.h" +#include "koeditordetails.h" +#include "koeditorrecurrence.h" +#include "koincidenceeditor.h" + +class SaveTemplateDialog; + +using namespace KCal; + +/** + This class provides a dialog for editing an event. +*/ +class KOEventEditor : public KOIncidenceEditor +{ + Q_OBJECT + public: + /** + Construct new event editor. + */ + KOEventEditor( Calendar *calendar, QWidget *parent ); + virtual ~KOEventEditor(void); + + void init(); + + void reload(); + + /** + Clear eventwin for new event, and preset the dates and times with hint + */ + void newEvent( QDateTime from, QDateTime to, bool allDay = false ); + /** + Edit an existing event. + */ + void editEvent( Event * , bool showDescription = false); + + /** + Set widgets to default values + */ + void setDefaults( QDateTime from, QDateTime to, bool allDay ); + + /** + Read event object and setup widgets accordingly. If tmpl is true, the + event is read as template, i.e. the time and date information isn't set. + */ + void readEvent( Event *, bool tmpl = false ); + /** + Write event settings to event object + */ + void writeEvent( Event * ); + + void setCategories( QString s ); + void setSecrecy( int ); + signals: + void eventAdded(Event *); + void eventChanged(Event *); + void eventToBeDeleted(Event *); + void eventDeleted(); + void deleteAttendee(Incidence *); + + protected slots: + void loadDefaults(); + void deleteEvent(); + + void slotLoadTemplate(); + void slotSaveTemplate(); + + void saveTemplate( const QString & ); + + protected: + void setupGeneral(); + void setupRecurrence(); + + /** Check if the input is valid. */ + bool validateInput(); + /** Process user input and create or update event. Returns false if input + * is not valid */ + bool processInput( bool ); + int msgItemDelete(); + + private: + Event *mEvent; + + KOEditorGeneralEvent *mGeneral; + KOEditorRecurrence *mRecurrence; +}; + +#endif diff --git a/korganizer/koeventeditor.moc b/korganizer/koeventeditor.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeventeditor.moc diff --git a/korganizer/koeventpopupmenu.cpp b/korganizer/koeventpopupmenu.cpp new file mode 100644 index 0000000..410bceb --- a/dev/null +++ b/korganizer/koeventpopupmenu.cpp @@ -0,0 +1,114 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qcursor.h> + +#include <klocale.h> +#include <kdebug.h> +#include <kiconloader.h> + +#include <libkcal/event.h> + +#include "koeventpopupmenu.h" +#include "koeventpopupmenu.moc" + +KOEventPopupMenu::KOEventPopupMenu() +{ + mCurrentIncidence = 0; + mHasAdditionalItems = false; + + insertItem (i18n("&Show"),this,SLOT(popupShow())); + mEditOnlyItems.append(insertItem (i18n("&Edit..."),this,SLOT(popupEdit()))); + mEditOnlyItems.append(insertItem (i18n("&Delete"), + this,SLOT(popupDelete()))); + mEditOnlyItems.append(insertItem (i18n("&Clone..."), + this,SLOT(popupClone()))); + mEditOnlyItems.append(insertItem (i18n("&Move..."), + this,SLOT(popupMove()))); +#ifndef DESKTOP_VERSION + mEditOnlyItems.append(insertItem (i18n("&Beam..."), + this,SLOT(popupBeam()))); +#endif + mEditOnlyItems.append(insertItem (i18n("&Toggle Cancel"), + this,SLOT(popupCancel()))); +} + +void KOEventPopupMenu::showIncidencePopup(Incidence *incidence) +{ + mCurrentIncidence = incidence; + + if (mCurrentIncidence) { + // Enable/Disabled menu items only valid for editable events. + QValueList<int>::Iterator it; + for( it = mEditOnlyItems.begin(); it != mEditOnlyItems.end(); ++it ) { + setItemEnabled(*it,!mCurrentIncidence->isReadOnly()); + } + popup(QCursor::pos()); + } else { + kdDebug() << "KOEventPopupMenu::showEventPopup(): No event selected" << endl; + } +} + +void KOEventPopupMenu::addAdditionalItem(const QIconSet &icon,const QString &text, + const QObject *receiver, const char *member, + bool editOnly) +{ + if (!mHasAdditionalItems) { + mHasAdditionalItems = true; + insertSeparator(); + } + int id = insertItem(icon,text,receiver,member); + if (editOnly) mEditOnlyItems.append(id); +} + +void KOEventPopupMenu::popupShow() +{ + if (mCurrentIncidence) emit showIncidenceSignal(mCurrentIncidence); +} + +void KOEventPopupMenu::popupEdit() +{ + if (mCurrentIncidence) emit editIncidenceSignal(mCurrentIncidence); +} + +void KOEventPopupMenu::popupDelete() +{ + if (mCurrentIncidence) emit deleteIncidenceSignal(mCurrentIncidence); +} +void KOEventPopupMenu::popupClone() +{ + if (mCurrentIncidence) emit cloneIncidenceSignal(mCurrentIncidence); +} +void KOEventPopupMenu::popupCancel() +{ + if (mCurrentIncidence) emit cancelIncidenceSignal(mCurrentIncidence); +} +void KOEventPopupMenu::popupMove() +{ + if (mCurrentIncidence) emit moveIncidenceSignal(mCurrentIncidence); +} + +void KOEventPopupMenu::popupBeam() +{ + if (mCurrentIncidence) emit beamIncidenceSignal(mCurrentIncidence); +} diff --git a/korganizer/koeventpopupmenu.h b/korganizer/koeventpopupmenu.h new file mode 100644 index 0000000..6993899 --- a/dev/null +++ b/korganizer/koeventpopupmenu.h @@ -0,0 +1,73 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KOEVENTPOPUPMENU_H +#define KOEVENTPOPUPMENU_H +// +// Context menu for event views with standard event actions +// + +#include <qpopupmenu.h> + +#include <libkcal/incidence.h> + +using namespace KCal; + +class KOEventPopupMenu : public QPopupMenu { + Q_OBJECT + public: + KOEventPopupMenu(); + + void addAdditionalItem(const QIconSet &icon,const QString &text, + const QObject *receiver, const char *member, + bool editOnly=false); + + + public slots: + void showIncidencePopup(Incidence *); + + protected slots: + void popupShow(); + void popupEdit(); + void popupDelete(); + void popupClone(); + void popupCancel(); + void popupMove(); + void popupBeam(); + + signals: + void editIncidenceSignal(Incidence *); + void showIncidenceSignal(Incidence *); + void deleteIncidenceSignal(Incidence *); + void cloneIncidenceSignal(Incidence *); + void cancelIncidenceSignal(Incidence *); + void moveIncidenceSignal(Incidence *); + void beamIncidenceSignal(Incidence *); + + private: + Incidence *mCurrentIncidence; + + bool mHasAdditionalItems; + QValueList<int> mEditOnlyItems; +}; + +#endif diff --git a/korganizer/koeventpopupmenu.moc b/korganizer/koeventpopupmenu.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeventpopupmenu.moc diff --git a/korganizer/koeventview.cpp b/korganizer/koeventview.cpp new file mode 100644 index 0000000..4553b0b --- a/dev/null +++ b/korganizer/koeventview.cpp @@ -0,0 +1,133 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000, 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qpopupmenu.h> +#include <qcursor.h> + +#include <klocale.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kmessagebox.h> + +#include <libkcal/calendar.h> +#include "koprefs.h" +#include "koeventview.h" +using namespace KOrg; +#include "koeventview.moc" + +//--------------------------------------------------------------------------- + +KOEventView::KOEventView(Calendar *cal,QWidget *parent,const char *name) + : KOrg::BaseView(cal,parent,name) +{ +} + +//--------------------------------------------------------------------------- + +KOEventView::~KOEventView() +{ +} + +//--------------------------------------------------------------------------- + +KOEventPopupMenu *KOEventView::eventPopup() +{ + KOEventPopupMenu *eventPopup = new KOEventPopupMenu; + + connect(eventPopup,SIGNAL(editIncidenceSignal(Incidence *)), + SIGNAL(editIncidenceSignal(Incidence *))); + connect(eventPopup,SIGNAL(showIncidenceSignal(Incidence *)), + SIGNAL(showIncidenceSignal(Incidence *))); + connect(eventPopup,SIGNAL(deleteIncidenceSignal(Incidence *)), + SIGNAL(deleteIncidenceSignal(Incidence *))); + connect(eventPopup,SIGNAL(cancelIncidenceSignal(Incidence *)), + SIGNAL(cancelIncidenceSignal(Incidence *))); + connect(eventPopup,SIGNAL(cloneIncidenceSignal(Incidence *)), + SIGNAL(cloneIncidenceSignal(Incidence *))); + connect(eventPopup,SIGNAL(beamIncidenceSignal(Incidence *)), + SIGNAL(beamIncidenceSignal(Incidence *))); + connect(eventPopup,SIGNAL(moveIncidenceSignal(Incidence *)), + SIGNAL(moveIncidenceSignal(Incidence *))); + + return eventPopup; +} + +//--------------------------------------------------------------------------- + +void KOEventView::showIncidencePopup(QPopupMenu *popup,Incidence *event) +{ + mCurrentIncidence = event; + if (event) popup->popup(QCursor::pos()); + else kdDebug() << "KOEventView::showEventPopup(): No event selected" << endl; +} + +//--------------------------------------------------------------------------- + +void KOEventView::popupShow() +{ + emit showIncidenceSignal(mCurrentIncidence); +} + +//--------------------------------------------------------------------------- + +void KOEventView::popupEdit() +{ + emit editIncidenceSignal(mCurrentIncidence); +} + +//--------------------------------------------------------------------------- + +void KOEventView::popupDelete() +{ + emit deleteIncidenceSignal(mCurrentIncidence); +} +void KOEventView::popupClone() +{ + emit cloneIncidenceSignal(mCurrentIncidence); +} +void KOEventView::popupCancel() +{ + emit cancelIncidenceSignal(mCurrentIncidence); +} + +//--------------------------------------------------------------------------- + +void KOEventView::defaultAction( Incidence *incidence ) +{ + + if ( !incidence ) return; + + if ( incidence->isReadOnly() ) + emit showIncidenceSignal(incidence); + else { + if ( KOPrefs::instance()->mEditOnDoubleClick ) + emit editIncidenceSignal(incidence); + else + emit showIncidenceSignal(incidence); + } +} + +//--------------------------------------------------------------------------- + +#include "baseview.moc" + diff --git a/korganizer/koeventview.h b/korganizer/koeventview.h new file mode 100644 index 0000000..77ec111 --- a/dev/null +++ b/korganizer/koeventview.h @@ -0,0 +1,172 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1999 Preston Brown <pbrown@kde.org> + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOEVENTVIEW_H +#define _KOEVENTVIEW_H + +#include <libkcal/calendar.h> +#include <libkcal/event.h> + +#include <korganizer/baseview.h> + +#include "koeventpopupmenu.h" + +using namespace KCal; + +class CalPrinter; + +/** + KOEventView is the abstract base class from which all other + calendar views for event data are derived. It provides methods for + displaying + appointments and events on one or more days. The actual number of + days that a view actually supports is not defined by this abstract class; + that is up to the classes that inherit from it. It also provides + methods for updating the display, retrieving the currently selected + event (or events), and the like. + + @short Abstract class from which all event views are derived. + @author Preston Brown <pbrown@kde.org> + @see KOListView, KOAgendaView, KOWeekView, KOMonthView +*/ +class KOEventView : public KOrg::BaseView +{ + Q_OBJECT + + public: + /** + * Constructs a view. + * @param cal is a pointer to the calendar object from which events + * will be retrieved for display. + */ + KOEventView(Calendar *cal,QWidget *parent=0,const char *name=0); + + /** + * Destructor. Views will do view-specific cleanups here. + */ + virtual ~KOEventView(); + + /** + * provides a hint back to the caller on the maximum number of dates + * that the view supports. A return value of 0 means no maximum. + */ + virtual int maxDatesHint() = 0; + + /** + * Construct a standard context menu for an event. + */ + KOEventPopupMenu *eventPopup(); + + /** This view is an view for displaying events. */ + bool isEventView() { return true; } + + public slots: + + /** + * Show context menu for event. + * @param event event, which is to be manipulated by the menu actions + * @param popup a popop menu created with eventPopup() + */ + void showIncidencePopup(QPopupMenu *popup, Incidence *event); + + /** + Perform the default action for an incidence, e.g. open the event editor, + when double-clicking an event in the agenda view. + */ + void defaultAction( Incidence * ); + + signals: + /** + * when the view changes the dates that are selected in one way or + * another, this signal is emitted. It should be connected back to + * the @see KDateNavigator object so that it changes appropriately, + * and any other objects that need to be aware that the list of + * selected dates has changed. + */ + void datesSelected(const DateList); + + /** + * instructs the receiver to show the incidence in read-only mode. + */ + void showIncidenceSignal(Incidence *); + + /** + * instructs the receiver to begin editing the incidence specified in + * some manner. Doesn't make sense to connect to more than one + * receiver. + */ + void editIncidenceSignal(Incidence *); + void cloneIncidenceSignal(Incidence *); + void cancelIncidenceSignal(Incidence *); + void beamIncidenceSignal(Incidence *); + void moveIncidenceSignal(Incidence *); + + /** + * instructs the receiver to delete the Incidence in some manner; some + * possibilities include automatically, with a confirmation dialog + * box, etc. Doesn't make sense to connect to more than one receiver. + */ + void deleteIncidenceSignal(Incidence *); + + /** + * instructs the receiver to create a new event. Doesn't make + * sense to connect to more than one receiver. + */ + void newEventSignal(); + /** + * instructs the receiver to create a new event with the specified beginning + * time. Doesn't make sense to connect to more than one receiver. + */ + void newEventSignal(QDate); + /** + * instructs the receiver to create a new event with the specified beginning + * time. Doesn't make sense to connect to more than one receiver. + */ + void newEventSignal(QDateTime); + /** + * instructs the receiver to create a new event, with the specified + * beginning end ending times. Doesn't make sense to connect to more + * than one receiver. + */ + void newEventSignal(QDateTime, QDateTime); + + //ET CVS MERGE ! + /** + * Emitted when an event is moved using the mouse in an agenda + * view (week / month). + */ + void shiftedEvent(const QDate& olddate, const QDate& newdate); + + + protected slots: + void popupShow(); + void popupEdit(); + void popupDelete(); + void popupClone(); + void popupCancel(); + + protected: + Incidence *mCurrentIncidence; // Incidence selected e.g. for a context menu +}; + +#endif diff --git a/korganizer/koeventview.moc b/korganizer/koeventview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeventview.moc diff --git a/korganizer/koeventviewer.cpp b/korganizer/koeventviewer.cpp new file mode 100644 index 0000000..9f8bd9b --- a/dev/null +++ b/korganizer/koeventviewer.cpp @@ -0,0 +1,510 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <qcstring.h> +#include <qwhatsthis.h> +#include <qdialog.h> +#include <qapplication.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <klocale.h> +#include <kapplication.h> +#include <libkcal/event.h> +#include <libkcal/todo.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <krun.h> +#include <kglobal.h> +#include <kprocess.h> +#include "koprefs.h" + +#include <libkdepim/addresseeview.h> +#include <kabc/stdaddressbook.h> + +#ifndef KORG_NODCOP +#include <dcopclient.h> +#include "korganizer.h" +#include "koprefs.h" +#include "actionmanager.h" +#endif + +#include "koeventviewer.h" +#include "koeventviewer.moc" +#ifndef KORG_NOKABC +#include <kabc/stdaddressbook.h> +#define size count +#endif +KOEventViewer::KOEventViewer(QWidget *parent,const char *name) + : QTextBrowser(parent,name) +{ + mSyncMode = false; + mColorMode = 0; +} + +KOEventViewer::~KOEventViewer() +{ +} + +void KOEventViewer::setSource(const QString& n) +{ + KABC::StdAddressBook* AddressBook = KABC::StdAddressBook::self( true ); + KABC::AddressBook::Iterator it; + for( it = AddressBook->begin(); it != AddressBook->end(); ++it ) { + // LR I do not understand, why the uid string is different on zaurus and desktop +#ifdef DESKTOP_VERSION + QString uid = "uid://"+(*it).uid(); +#else + QString uid = "uid:"+(*it).uid(); +#endif + //qDebug("for *%s* +%s+ ", n.latin1(), uid.latin1()); + if (n == uid ) { + //qDebug("found %s ",(*it).mobileHomePhone().latin1() ); + QDialog dia( this,"dia123", true ); + dia.setCaption( i18n("Details of attendee") ); + QVBoxLayout lay ( &dia ); + KPIM::AddresseeView av ( &dia ); + av.setAddressee( (*it) ); + lay.addWidget( &av ); + if ( QApplication::desktop()->width() < 480 ) + dia.resize( 220, 240); + else { + dia.resize( 400,400); + + } + dia.exec(); + break; + } + } + + +#ifndef KORG_NODCOP + kdDebug() << "KOEventViewer::setSource(): " << n << endl; + QString tmpStr; + if (n.startsWith("mailto:")) { + KApplication::kApplication()->invokeMailer(n.mid(7),QString::null); + //emit showIncidence(n); + return; + } else if (n.startsWith("uid:")) { + DCOPClient *client = KApplication::kApplication()->dcopClient(); + const QByteArray noParamData; + const QByteArray paramData; + QByteArray replyData; + QCString replyTypeStr; +#define PING_ABBROWSER (client->call("kaddressbook", "KAddressBookIface", "interfaces()", noParamData, replyTypeStr, replyData)) + bool foundAbbrowser = PING_ABBROWSER; + + if (foundAbbrowser) { + //KAddressbook is already running, so just DCOP to it to bring up the contact editor + //client->send("kaddressbook","KAddressBookIface", + QDataStream arg(paramData, IO_WriteOnly); + arg << n.mid(6); + client->send("kaddressbook", "KAddressBookIface", "showContactEditor( QString )", paramData); + return; + } else { + /* + KaddressBook is not already running. Pass it the UID of the contact via the command line while starting it - its neater. + We start it without its main interface + */ + KIconLoader* iconLoader = new KIconLoader(); + QString iconPath = iconLoader->iconPath("go",KIcon::Small); + ActionManager::setStartedKAddressBook(true); + tmpStr = "kaddressbook --editor-only --uid "; + tmpStr += KProcess::quote(n.mid(6)); + KRun::runCommand(tmpStr,"KAddressBook",iconPath); + return; + } + } else { + //QTextBrowser::setSource(n); + } +#endif +} + +void KOEventViewer::addTag(const QString & tag,const QString & text) +{ + int number=text.contains("\n"); + QString str = "<" + tag + ">"; + QString tmpText=text; + QString tmpStr=str; + if(number !=-1) + { + if (number > 0) { + int pos=0; + QString tmp; + for(int i=0;i<=number;i++) { + pos=tmpText.find("\n"); + tmp=tmpText.left(pos); + tmpText=tmpText.right(tmpText.length()-pos-1); + tmpStr+=tmp+"<br>"; + } + } + else tmpStr += tmpText; + tmpStr+="</" + tag + ">"; + mText.append(tmpStr); + } + else + { + str += text + "</" + tag + ">"; + mText.append(str); + } +} + +void KOEventViewer::setColorMode( int m ) +{ + mColorMode = m; +} +void KOEventViewer::appendEvent(Event *event, int mode ) +{ + mCurrentIncidence = event; + bool shortDate = KOPrefs::instance()->mShortDateInViewer; + topLevelWidget()->setCaption(i18n("Event Viewer")); + if ( mode == 0 ) { + addTag("h2",event->summary()); + } + else { + if ( mColorMode == 1 ) { + mText +="<font color=\"#00A000\">"; + } + if ( mColorMode == 2 ) { + mText +="<font color=\"#C00000\">"; + } + // mText +="<font color=\"#F00000\">" + i18n("O-due!") + "</font>"; + if ( mode == 1 ) { + addTag("h2",i18n( "Local: " ) +event->summary()); + } else { + addTag("h2",i18n( "Remote: " ) +event->summary()); + } + addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) ); + if ( mColorMode ) + mText += "</font>"; + } + if (event->cancelled ()) { + mText +="<font color=\"#B00000\">"; + addTag("i",i18n("This event has been cancelled!")); + mText.append("<br>"); + mText += "</font>"; + } + if (!event->location().isEmpty()) { + addTag("b",i18n("Location: ")); + mText.append(event->location()+"<br>"); + } + if (event->doesFloat()) { + if (event->isMultiDay()) { + mText.append(i18n("<p><b>From:</b> %1 </p><p><b>To:</b> %2</p>") + .arg(event->dtStartDateStr(shortDate)) + .arg(event->dtEndDateStr(shortDate))); + } else { + mText.append(i18n("<p><b>On:</b> %1</p>").arg(event->dtStartDateStr( shortDate ))); + } + } else { + if (event->isMultiDay()) { + mText.append(i18n("<p><b>From:</b> %1</p> ") + .arg(event->dtStartStr( shortDate))); + mText.append(i18n("<p><b>To:</b> %1</p>") + .arg(event->dtEndStr(shortDate))); + } else { + mText.append(i18n("<p><b>On:</b> %1</p> ") + .arg(event->dtStartDateStr( shortDate ))); + mText.append(i18n("<p><b>From:</b> %1 <b>To:</b> %2</p>") + .arg(event->dtStartTimeStr()) + .arg(event->dtEndTimeStr())); + } + } + + if (event->recurrence()->doesRecur()) { + + QString recurText = event->recurrence()->recurrenceText(); + addTag("p","<em>" + i18n("This is a %1 recurring event.").arg(recurText ) + "</em>"); + bool last; + QDate start = QDate::currentDate(); + QDate next; + next = event->recurrence()->getPreviousDate( start , &last ); + if ( !last ) { + next = event->recurrence()->getNextDate( start.addDays( - 1 ) ); + addTag("p",i18n("<b>Next recurrence is on:</b>") ); + addTag("p", KGlobal::locale()->formatDate( next, shortDate )); + } else { + addTag("p",i18n("<b>Last recurrence was on:</b>") ); + addTag("p", KGlobal::locale()->formatDate( next, shortDate )); + } + } + + + if (event->isAlarmEnabled()) { + Alarm *alarm =event->alarms().first() ; + QDateTime t = alarm->time(); + int min = t.secsTo( event->dtStart() )/60; + QString s =i18n("( %1 min before )").arg( min ); + addTag("p",i18n("<b>Alarm on: ") + s +" </b>"); + addTag("p", KGlobal::locale()->formatDateTime( t, shortDate )); + //addTag("p",s); + } + + addTag("b",i18n("Access: ")); + mText.append(event->secrecyStr()+"<br>"); + if (!event->description().isEmpty()) { + addTag("p",i18n("<b>Details: </b>")); + addTag("p",event->description()); + } + + formatCategories(event); + + formatReadOnly(event); + formatAttendees(event); + + setText(mText); + //QWhatsThis::add(this,mText); + +} + +void KOEventViewer::appendTodo(Todo *event, int mode ) +{ + mCurrentIncidence = event; + topLevelWidget()->setCaption(i18n("Todo Viewer")); + bool shortDate = KOPrefs::instance()->mShortDateInViewer; + if (mode == 0 ) + addTag("h2",event->summary()); + else { + if ( mColorMode == 1 ) { + mText +="<font color=\"#00A000\">"; + } + if ( mColorMode == 2 ) { + mText +="<font color=\"#B00000\">"; + } + if ( mode == 1 ) { + addTag("h2",i18n( "Local: " ) +event->summary()); + } else { + addTag("h2",i18n( "Remote: " ) +event->summary()); + } + addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) ); + if ( mColorMode ) + mText += "</font>"; + } + if (event->cancelled ()) { + mText +="<font color=\"#B00000\">"; + addTag("i",i18n("This todo has been cancelled!")); + mText.append("<br>"); + mText += "</font>"; + } + + if (!event->location().isEmpty()) { + addTag("b",i18n("Location: ")); + mText.append(event->location()+"<br>"); + } + if (event->hasDueDate()) { + mText.append(i18n("<p><b>Due on:</b> %1</p>").arg(event->dtDueStr(KOPrefs::instance()->mShortDateInViewer))); + } + addTag("b",i18n("Access: ")); + mText.append(event->secrecyStr()+"<br>"); + if (!event->description().isEmpty()) { + addTag("p",i18n("<b>Details: </b>")); + addTag("p",event->description()); + } + + formatCategories(event); + + mText.append(i18n("<p><b>Priority:</b> %2</p>") + .arg(QString::number(event->priority()))); + + mText.append(i18n("<p><i>%1 % completed</i></p>") + .arg(event->percentComplete())); + + formatReadOnly(event); + formatAttendees(event); + + setText(mText); +} + +void KOEventViewer::formatCategories(Incidence *event) +{ + if (!event->categoriesStr().isEmpty()) { + if (event->categories().count() == 1) { + addTag("h3",i18n("Category")); + } else { + addTag("h3",i18n("Categories")); + } + addTag("p",event->categoriesStr()); + } +} +void KOEventViewer::formatAttendees(Incidence *event) +{ + QPtrList<Attendee> attendees = event->attendees(); + if (attendees.count()) { + + + QString iconPath = KGlobal::iconLoader()->iconPath("mailappt",KIcon::Small); + addTag("h3",i18n("Organizer")); + mText.append("<ul><li>"); +#ifndef KORG_NOKABC + + KABC::AddressBook *add_book = KABC::StdAddressBook::self(); + KABC::Addressee::List addressList; + addressList = add_book->findByEmail(event->organizer()); + KABC::Addressee o = addressList.first(); + if (!o.isEmpty() && addressList.size()<2) { + mText += "<a href=\"uid:" + o.uid() + "\">"; + mText += o.formattedName(); + mText += "</a>\n"; + } else { + mText.append(event->organizer()); + } +#else + mText.append(event->organizer()); +#endif + + if (iconPath) { + mText += " <a href=\"mailto:" + event->organizer() + "\">"; + mText += "<IMG src=\"" + iconPath + "\">"; + mText += "</a>\n"; + } + mText.append("</li></ul>"); + + addTag("h3",i18n("Attendees")); + Attendee *a; + mText.append("<ul>"); + for(a=attendees.first();a;a=attendees.next()) { +#ifndef KORG_NOKABC + if (a->name().isEmpty()) { + addressList = add_book->findByEmail(a->email()); + KABC::Addressee o = addressList.first(); + if (!o.isEmpty() && addressList.size()<2) { + mText += "<a href=\"uid:" + o.uid() + "\">"; + mText += o.formattedName(); + mText += "</a>\n"; + } else { + mText += "<li>"; + mText.append(a->email()); + mText += "\n"; + } + } else { + mText += "<li><a href=\"uid:" + a->uid() + "\">"; + if (!a->name().isEmpty()) mText += a->name(); + else mText += a->email(); + mText += "</a>\n"; + } +#else + //qDebug("nokabc "); + mText += "<li><a href=\"uid:" + a->uid() + "\">"; + if (!a->name().isEmpty()) mText += a->name(); + else mText += a->email(); + mText += "</a>\n"; +#endif + + if (!a->email().isEmpty()) { + if (iconPath) { + mText += "<a href=\"mailto:" + a->name() +" "+ "<" + a->email() + ">" + "\">"; + mText += "<IMG src=\"" + iconPath + "\">"; + mText += "</a>\n"; + } + } + if (a->status() != Attendee::NeedsAction ) + mText +="[" + a->statusStr() + "] "; + if (a->role() == Attendee::Chair ) + mText +="(" + a->roleStr().left(1) + ".)"; + } + mText.append("</li></ul>"); + } + +} +void KOEventViewer::appendJournal(Journal *jour, int mode ) +{ + bool shortDate = KOPrefs::instance()->mShortDateInViewer; + if (mode == 0 ) + addTag("h2",i18n("Journal from: ")); + else { + if ( mode == 1 ) { + addTag("h2",i18n( "Local: " ) +i18n("Journal from: ")); + } else { + addTag("h2",i18n( "Remote: " ) +i18n("Journal from: ")); + } + addTag("h3",i18n( "Last modified " ) + KGlobal::locale()->formatDateTime(jour->lastModified(),shortDate ) ); + } + topLevelWidget()->setCaption("Journal Viewer"); + mText.append(i18n("<h3> %1 </h3> ").arg(jour->dtStartDateStr(KOPrefs::instance()->mShortDateInViewer))); + if (!jour->description().isEmpty()) { + addTag("p",jour->description()); + } + setText(mText); +} + +void KOEventViewer::formatReadOnly(Incidence *event) +{ + if (event->isReadOnly()) { + addTag("p","<em>(" + i18n("read-only") + ")</em>"); + } +} +void KOEventViewer::setSyncMode( bool b ) +{ + mSyncMode = b; +} + + +void KOEventViewer::setTodo(Todo *event, bool clearV ) +{ + if ( clearV ) + clearEvents(); + if ( mSyncMode ) { + if ( clearV ) + appendTodo(event,1 ); + else + appendTodo(event,2); + } else + appendTodo(event); +} +void KOEventViewer::setJournal(Journal *event, bool clearV ) +{ + if ( clearV ) + clearEvents(); + if ( mSyncMode ) { + if ( clearV ) + appendJournal(event, 1); + else + appendJournal(event, 2); + } else + appendJournal(event); +} + +void KOEventViewer::setEvent(Event *event) +{ + clearEvents(); + if ( mSyncMode ) + appendEvent(event, 1); + else + appendEvent(event); +} + +void KOEventViewer::addEvent(Event *event) +{ + if ( mSyncMode ) + appendEvent(event, 2); + else + appendEvent(event); +} + +void KOEventViewer::clearEvents(bool now) +{ + mText = ""; + if (now) setText(mText); +} + +void KOEventViewer::addText(QString text) +{ + mText.append(text); + setText(mText); +} diff --git a/korganizer/koeventviewer.h b/korganizer/koeventviewer.h new file mode 100644 index 0000000..74f1135 --- a/dev/null +++ b/korganizer/koeventviewer.h @@ -0,0 +1,73 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef KOEVENTVIEWER_H +#define KOEVENTVIEWER_H +// +// Viewer widget for events. +// + +#include <qtextbrowser.h> + +#include <libkcal/event.h> +#include <libkcal/journal.h> + + +using namespace KCal; + +class KOEventViewer : public QTextBrowser { + Q_OBJECT + public: + KOEventViewer(QWidget *parent=0,const char *name=0); + virtual ~KOEventViewer(); + + void setSource(const QString &); + void setEvent(Event *event); + void addEvent(Event *event); + void setTodo(Todo *event, bool clearV = true ); + void setJournal(Journal *jour, bool clearV = true ); + + void appendEvent(Event *event, int mode = 0 ); + void appendTodo(Todo *event, int mode = 0 ); + void appendJournal(Journal *jour, int mode = 0 ); + + void clearEvents(bool now=false); + + void addText(QString text); + void setSyncMode( bool ); + void setColorMode( int ); + + protected: + int mColorMode; + void addTag(const QString & tag,const QString & text); + + void formatCategories(Incidence *event); + void formatAttendees(Incidence *event); + void formatReadOnly(Incidence *event); + + private: + QTextBrowser *mEventTextView; + bool mSyncMode; + + QString mText; + Incidence* mCurrentIncidence; + signals: + void launchaddressbook(QString uid); +}; + +#endif diff --git a/korganizer/koeventviewer.moc b/korganizer/koeventviewer.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeventviewer.moc diff --git a/korganizer/koeventviewerdialog.cpp b/korganizer/koeventviewerdialog.cpp new file mode 100644 index 0000000..64ab94d --- a/dev/null +++ b/korganizer/koeventviewerdialog.cpp @@ -0,0 +1,240 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <klocale.h> + +#include <libkcal/event.h> +#include <qpushbutton.h> + +#include "koeventviewer.h" +#include "koprefs.h" +#include <libkcal/todo.h> +#include "qapp.h" + +#include "koeventviewerdialog.h" +#include "koeventviewerdialog.moc" +extern int globalFlagBlockAgenda; + +KOEventViewerDialog::KOEventViewerDialog(QWidget *parent,const char *name) + : KDialogBase(parent,name, +#ifndef DESKTOP_VERSION + true , +#else + false, +#endif + i18n("Event Viewer"),Ok|User1|Close,Close, false, i18n("Agenda")) +{ + + mEventViewer = new KOEventViewer(this); + mEventViewer->setFont( KOPrefs::instance()->mEventViewFont ); + setMainWidget(mEventViewer); + setButtonText(Ok, i18n("Edit") ); + + QObject::connect(findButton( Ok ),SIGNAL(clicked()), + SLOT(editIncidence())); + QObject::connect(this,SIGNAL(user1Clicked()), + SLOT(showIncidence())); + mIncidence = 0; + // TODO: Set a sensible size (based on the content?). + //showMaximized(); + //qDebug("++++++++++++KOEventViewerDialog() "); + // if ( KOPrefs::instance()->mCompactDialogs ) { +// setFixedSize( 240,284 ); +// move( 0, 15 ); +// } else { +// setMinimumSize(300,200); +// resize(320,300); +// } + mSyncMode = false; + mSyncResult = 0; + +} + +KOEventViewerDialog::~KOEventViewerDialog() +{ + //qDebug("-------~KOEventViewerDialog() "); +} +void KOEventViewerDialog::showMe() +{ + +#ifdef DESKTOP_VERSION + show(); +#else + showMaximized(); +#endif + setFocus(); + setActiveWindow(); + +} +void KOEventViewerDialog::setSyncMode( bool b ) +{ + mSyncMode = b; + //qDebug("KOEventViewerDialog::setSyncMode %d ",mSyncMode ); + if ( mSyncMode ) { + findButton( Close )->setText( i18n("Cancel Sync")); + findButton( Ok )->setText( i18n("Remote")); + findButton( User1 )->setText( i18n("Local")); + } else { + findButton( Close )->setText( i18n("Close")); + findButton( Ok )->setText( i18n("Edit")); + findButton( User1 )->setText( i18n("Agenda")); + } + mEventViewer->setSyncMode( b ); +} +void KOEventViewerDialog::setColorMode( int m ) +{ + mEventViewer->setColorMode( m ); +} +int KOEventViewerDialog::executeS( bool local ) +{ + mSyncResult = 3; + if ( local ) + findButton( User1 )->setFocus(); + else + findButton( Ok )->setFocus(); + exec(); + return mSyncResult; +} + +void KOEventViewerDialog::updateConfig() +{ + mEventViewer->setFont( KOPrefs::instance()->mEventViewFont ); + +} +void KOEventViewerDialog::setEvent(Event *event) +{ + mEventViewer->setEvent(event); + mIncidence = event; + findButton( Close )->setFocus(); +} +void KOEventViewerDialog::setIncidence(Incidence *in ) +{ + if ( in->type() == "Event" ) + setEvent( (Event*) in ); + else if ( in->type() =="Todo" ) + setTodo( (Todo*) in ); + else if ( in->type() =="Journal" ) + setJournal( (Journal*) in ); +} +void KOEventViewerDialog::addIncidence(Incidence *in) +{ + if ( in->type() == "Event" ) + addEvent( (Event*) in ); + else if ( in->type() =="Todo" ) + mEventViewer->setTodo( (Todo*) in, false ); + else if ( in->type() =="Journal" ) + mEventViewer->setJournal( (Journal*) in, false ); + if ( mSyncMode ) { + findButton( User1 )->setFocus(); + setCaption(i18n("Conflict! Please choose entry")); + } +} + +void KOEventViewerDialog::addEvent(Event *event) +{ + mEventViewer->addEvent(event); + mIncidence = event; + findButton( Close )->setFocus(); +} + +void KOEventViewerDialog::setTodo(Todo *event) +{ + mEventViewer->setTodo(event); + mIncidence = (Incidence*)event; + findButton( Close )->setFocus(); +} +void KOEventViewerDialog::setJournal(Journal *j) +{ + mEventViewer->setJournal(j); + mIncidence = (Incidence*)j; + findButton( Close )->setFocus(); +} + +void KOEventViewerDialog::addText(QString text) +{ + mEventViewer->addText(text); + findButton( Close )->setFocus(); +} +void KOEventViewerDialog::editIncidence() +{ + if ( mSyncMode ) { + mSyncResult = 2; + accept(); + return; + } + if ( mIncidence ){ +#ifndef DESKTOP_VERSION + hide(); +#endif + emit editIncidence( mIncidence ); + } +} +void KOEventViewerDialog::showIncidence() +{ + + if ( mSyncMode ) { + mSyncResult = 1; + accept(); + return; + } + + if ( mIncidence ){ +#ifndef DESKTOP_VERSION + hide(); +#endif + QDate date; + if ( mIncidence->type() == "Todo" ) { + if ( ((Todo*)mIncidence)->hasDueDate() ) + date = ((Todo*)mIncidence)->dtDue().date(); + else { + globalFlagBlockAgenda = 2; + emit showAgendaView( false ); + return; + } + } else + date = mIncidence->dtStart().date(); + globalFlagBlockAgenda = 1; + emit showAgendaView( false ); + globalFlagBlockAgenda = 2; + emit jumpToTime( date ); + } +} +void KOEventViewerDialog::keyPressEvent ( QKeyEvent * e ) +{ + switch ( e->key() ) { + + case Qt::Key_A : + case Qt::Key_L : + showIncidence(); + break; + case Qt::Key_E : + case Qt::Key_R : + editIncidence(); + break; + case Qt::Key_C: + close(); + break; + case Qt::Key_I: + accept(); + break; + default: + break; + } + +} diff --git a/korganizer/koeventviewerdialog.h b/korganizer/koeventviewerdialog.h new file mode 100644 index 0000000..21cb3ee --- a/dev/null +++ b/korganizer/koeventviewerdialog.h @@ -0,0 +1,70 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000, 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef KOEVENTVIEWERDIALOG_H +#define KOEVENTVIEWERDIALOG_H +// +// Viewer dialog for events. +// + +#include <qtextview.h> + +#include <kdialogbase.h> + +#include <libkcal/event.h> + +using namespace KCal; + +class KOEventViewer; + +class KOEventViewerDialog : public KDialogBase { + Q_OBJECT + public: + KOEventViewerDialog(QWidget *parent=0,const char *name=0); + virtual ~KOEventViewerDialog(); + + void setEvent(Event *event); + void addEvent(Event *event); + void setTodo(Todo *event); + void setJournal(Journal *journal); + void setIncidence(Incidence *inc); + void addIncidence(Incidence *inc); + void addText(QString text); + void showMe(); + void setSyncMode( bool ); + void setColorMode( int m ); + int executeS( bool ); + public slots: + void updateConfig(); + signals: + void editIncidence( Incidence* ); + void jumpToTime( const QDate &); + void showAgendaView( bool ); +private slots: + void editIncidence(); + void showIncidence(); + + private: + bool mSyncMode; + int mSyncResult; + KOEventViewer *mEventViewer; + Incidence* mIncidence; + void keyPressEvent ( QKeyEvent * e ); +}; + +#endif diff --git a/korganizer/koeventviewerdialog.moc b/korganizer/koeventviewerdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koeventviewerdialog.moc diff --git a/korganizer/kofilterview.cpp b/korganizer/kofilterview.cpp new file mode 100644 index 0000000..b22bc54 --- a/dev/null +++ b/korganizer/kofilterview.cpp @@ -0,0 +1,96 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qpushbutton.h> + +#include <libkcal/calfilter.h> + +#include "kofilterview.h" +#include "kofilterview.moc" + +KOFilterView::KOFilterView(QPtrList<CalFilter> *filterList,QWidget* parent, + const char* name,WFlags fl ) + : KOFilterView_base(parent,name,fl) +{ + mFilters = filterList; + + connect(mSelectionCombo,SIGNAL(activated(int)),SIGNAL(filterChanged())); + connect(mEnabledCheck,SIGNAL(clicked()),SIGNAL(filterChanged())); + connect(mEditButton,SIGNAL(clicked()),SIGNAL(editFilters())); +} + +KOFilterView::~KOFilterView() +{ + // no need to delete child widgets, Qt does it all for us +} + +bool KOFilterView::filtersEnabled() +{ + return mEnabledCheck->isChecked(); +} + +void KOFilterView::setFiltersEnabled(bool set) +{ + mEnabledCheck->setChecked(set); + emit filterChanged(); +} + + +void KOFilterView::updateFilters() +{ + mSelectionCombo->clear(); + + CalFilter *filter = mFilters->first(); + while(filter) { + mSelectionCombo->insertItem(filter->name()); + filter = mFilters->next(); + } +} + +CalFilter *KOFilterView::selectedFilter() +{ + CalFilter *f = mFilters->at(mSelectionCombo->currentItem()); + return f; +} + +void KOFilterView::setSelectedFilter(QString filterName) +{ + int filter_num = mSelectionCombo->count(); + int i; + for (i=0;i<filter_num;i++) { + if (mSelectionCombo->text(i)==filterName) + mSelectionCombo->setCurrentItem(i); + } + emit filterChanged(); +} +void KOFilterView::setSelectedFilter( int fil ) +{ + if ( fil >= mSelectionCombo->count() ) + return; + mSelectionCombo->setCurrentItem( fil ); + emit filterChanged(); +} + + diff --git a/korganizer/kofilterview.h b/korganizer/kofilterview.h new file mode 100644 index 0000000..9ba2673 --- a/dev/null +++ b/korganizer/kofilterview.h @@ -0,0 +1,57 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KOFILTERVIEW_H +#define KOFILTERVIEW_H + +#include <qstring.h> + +#include "kofilterview_base.h" + +#include <libkcal/calfilter.h> + +using namespace KCal; + +class KOFilterView : public KOFilterView_base +{ + Q_OBJECT + public: + KOFilterView(QPtrList<CalFilter> *filterList,QWidget* parent=0,const char* name=0, WFlags fl=0); + ~KOFilterView(); + + void updateFilters(); + + bool filtersEnabled(); + void setFiltersEnabled(bool); + CalFilter *selectedFilter(); + void setSelectedFilter(QString); + void setSelectedFilter( int ); + + signals: + void filterChanged(); + void editFilters(); + + private: + QPtrList<CalFilter> *mFilters; +}; + +#endif // KOFILTERVIEW_H diff --git a/korganizer/kofilterview.moc b/korganizer/kofilterview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kofilterview.moc diff --git a/korganizer/kofilterview_base.cpp b/korganizer/kofilterview_base.cpp new file mode 100644 index 0000000..6709630 --- a/dev/null +++ b/korganizer/kofilterview_base.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** Form implementation generated from reading ui file 'kofilterview_base.ui' +** +** Created: Sat Jun 26 17:24:07 2004 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#include "kofilterview_base.h" + +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qframe.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qvariant.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a KOFilterView_base which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + */ +KOFilterView_base::KOFilterView_base( QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) +{ + if ( !name ) + setName( "KOFilterView_base" ); + resize( 100, 100 ); + setCaption( tr( "Form2" ) ); + KOFilterView_baseLayout = new QVBoxLayout( this ); + KOFilterView_baseLayout->setSpacing( 2 ); + KOFilterView_baseLayout->setMargin( 2 ); + + Frame11 = new QFrame( this, "Frame11" ); + Frame11->setFrameShadow( QFrame::Raised ); + Frame11->setFrameShape( QFrame::StyledPanel ); + Frame11Layout = new QVBoxLayout( Frame11 ); + Frame11Layout->setSpacing( 1 ); + Frame11Layout->setMargin( 2 ); + + mEnabledCheck = new QCheckBox( Frame11, "mEnabledCheck" ); + mEnabledCheck->setText( tr( "Filter enabled" ) ); + Frame11Layout->addWidget( mEnabledCheck ); + + mSelectionCombo = new QComboBox( FALSE, Frame11, "mSelectionCombo" ); + Frame11Layout->addWidget( mSelectionCombo ); + KOFilterView_baseLayout->addWidget( Frame11 ); + + mEditButton = new QPushButton( this, "mEditButton" ); + mEditButton->setText( tr( "Edit Filters" ) ); + KOFilterView_baseLayout->addWidget( mEditButton ); +} + +/* + * Destroys the object and frees any allocated resources + */ +KOFilterView_base::~KOFilterView_base() +{ + // no need to delete child widgets, Qt does it all for us +} + diff --git a/korganizer/kofilterview_base.h b/korganizer/kofilterview_base.h new file mode 100644 index 0000000..ed084ce --- a/dev/null +++ b/korganizer/kofilterview_base.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** Form interface generated from reading ui file 'kofilterview_base.ui' +** +** Created: Sat Jun 26 17:22:53 2004 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#ifndef KOFILTERVIEW_BASE_H +#define KOFILTERVIEW_BASE_H + +#include <qvariant.h> +#include <qwidget.h> +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QCheckBox; +class QComboBox; +class QFrame; +class QPushButton; + +class KOFilterView_base : public QWidget +{ + Q_OBJECT + +public: + KOFilterView_base( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~KOFilterView_base(); + + QFrame* Frame11; + QCheckBox* mEnabledCheck; + QComboBox* mSelectionCombo; + QPushButton* mEditButton; + +protected: + QVBoxLayout* KOFilterView_baseLayout; + QVBoxLayout* Frame11Layout; +}; + +#endif // KOFILTERVIEW_BASE_H diff --git a/korganizer/kofilterview_base.ui b/korganizer/kofilterview_base.ui new file mode 100644 index 0000000..b1b7c61 --- a/dev/null +++ b/korganizer/kofilterview_base.ui @@ -0,0 +1,96 @@ +<!DOCTYPE UI><UI> +<class>KOFilterView_base</class> +<widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>KOFilterView_base</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>100</width> + <height>100</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Form2</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>2</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>2</number> + </property> + <widget> + <class>QFrame</class> + <property stdset="1"> + <name>name</name> + <cstring>Frame11</cstring> + </property> + <property stdset="1"> + <name>frameShadow</name> + <enum>Raised</enum> + </property> + <property stdset="1"> + <name>frameShape</name> + <enum>StyledPanel</enum> + </property> + <property> + <name>layoutMargin</name> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>2</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>1</number> + </property> + <widget> + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>mEnabledCheck</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Filter enabled</string> + </property> + </widget> + <widget> + <class>QComboBox</class> + <property stdset="1"> + <name>name</name> + <cstring>mSelectionCombo</cstring> + </property> + </widget> + </vbox> + </widget> + <widget> + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>mEditButton</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Edit Filters</string> + </property> + </widget> + </vbox> +</widget> +</UI> diff --git a/korganizer/koglobals.cpp b/korganizer/koglobals.cpp new file mode 100644 index 0000000..8016034 --- a/dev/null +++ b/korganizer/koglobals.cpp @@ -0,0 +1,143 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qapplication.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kstandarddirs.h> +#include <kglobalsettings.h> +#include <klocale.h> + +#include <kcalendarsystem.h> + +#ifndef KORG_NOKALARMD +#include "kalarmdclient.h" +#endif +#include "simplealarmclient.h" + +#include "koglobals.h" +#include "koprefs.h" + +class NopAlarmClient : public AlarmClient +{ + public: + void startDaemon() {} + bool setCalendars( const QStringList & ) { return false; } + bool addCalendar( const QString & ) { return false; } + bool removeCalendar( const QString & ) { return false; } + bool reloadCalendar( const QString & ) { return false; } +}; + +KOGlobals *KOGlobals::mSelf = 0; + +KOGlobals *KOGlobals::self() +{ + if (!mSelf) { + mSelf = new KOGlobals; + } + + return mSelf; +} + +KOGlobals::KOGlobals() +{ + KConfig *cfg = KOGlobals::config(); + + cfg->setGroup("General"); + mCalendarSystem = KGlobal::locale()->calendar(); + + cfg->setGroup("AlarmDaemon"); + QString alarmClient = cfg->readEntry( "Daemon", "kalarmd" ); + if ( alarmClient == "simple" ) { + mAlarmClient = new SimpleAlarmClient; +#ifndef KORG_NOKALARMD + } else if ( alarmClient == "kalarmd" ) { + mAlarmClient = new KalarmdClient; +#endif + } else { + mAlarmClient = new NopAlarmClient; + } +} + +KConfig* KOGlobals::config() +{ + static KConfig *mConfig = 0; + if (!mConfig) { + KOPrefs *p = KOPrefs::instance(); + mConfig = p->getConfig(); + //mConfig = new KConfig( locateLocal( "config", "korganizerrc" ) ); + } + return mConfig; +} + +KOGlobals::~KOGlobals() +{ + delete mAlarmClient; +} + +const KCalendarSystem *KOGlobals::calendarSystem() const +{ + return mCalendarSystem; +} + +AlarmClient *KOGlobals::alarmClient() const +{ + return mAlarmClient; +} + +void KOGlobals::fitDialogToScreen( QWidget *wid, bool force ) +{ + bool resized = false; + + int w = wid->frameSize().width(); + int h = wid->frameSize().height(); + + QRect desk = KGlobalSettings::desktopGeometry(wid); + if ( w > desk.width() ) { + w = desk.width(); + resized = true; + } + // Yuck this hack is ugly. Is the -30 really to circumvent the size of + // kicker?! + if ( h > desk.height() - 30 ) { + h = desk.height() - 30; + resized = true; + } + + if ( resized || force ) { + wid->resize( w, h ); + wid->move( desk.x(), desk.y()+15 ); + if ( force ) wid->setFixedSize( w, h ); + } +} + +bool KOGlobals::reverseLayout() +{ +#if QT_VERSION >= 0x030000 + return QApplication::reverseLayout(); +#else + return false; +#endif +} diff --git a/korganizer/koglobals.h b/korganizer/koglobals.h new file mode 100644 index 0000000..357ff5f --- a/dev/null +++ b/korganizer/koglobals.h @@ -0,0 +1,59 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KORG_GLOBALS_H +#define KORG_GLOBALS_H + +class KCalendarSystem; +class AlarmClient; + +class KConfig; + +class KOGlobals +{ + public: + static KOGlobals *self(); + + enum { EVENTADDED, EVENTEDITED, EVENTDELETED }; + enum { PRIORITY_MODIFIED, COMPLETION_MODIFIED, CATEGORY_MODIFIED, UNKNOWN_MODIFIED }; + + static void fitDialogToScreen( QWidget *widget, bool force=false ); + static KConfig *config(); + + static bool reverseLayout(); + + const KCalendarSystem *calendarSystem() const; + + AlarmClient *alarmClient() const; + + protected: + KOGlobals(); + ~KOGlobals(); + + private: + static KOGlobals *mSelf; + + const KCalendarSystem *mCalendarSystem; + AlarmClient *mAlarmClient; +}; + +#endif diff --git a/korganizer/koincidenceeditor.cpp b/korganizer/koincidenceeditor.cpp new file mode 100644 index 0000000..e10a188 --- a/dev/null +++ b/korganizer/koincidenceeditor.cpp @@ -0,0 +1,187 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qtooltip.h> +#include <qframe.h> +#include <qpixmap.h> +#include <qlayout.h> +#include <qwidgetstack.h> +#include <qdatetime.h> +#include <qdir.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <kfiledialog.h> + +#include <libkdepim/categoryselectdialog.h> +#include <libkdepim/kinputdialog.h> + +#include <libkcal/calendarlocal.h> +#include <libkcal/icalformat.h> + +#include "koprefs.h" +#include "koglobals.h" + +#include "koincidenceeditor.h" +#include "koincidenceeditor.moc" + +KOIncidenceEditor::KOIncidenceEditor( const QString &caption, + Calendar *calendar, QWidget *parent ) : + KDialogBase( Tabbed, caption, Ok | Apply | Cancel |/* Default | */User1, Ok, + parent, caption, true, false ), + mSaveTemplateDialog( 0 ) +{ + mCalendar = calendar; + + setButtonText( Default, i18n("Template...") ); + + QString saveTemplateText; + // if ( KOPrefs::instance()->mCompactDialogs ) { +// showButton( User1, false ); +// showButton( Apply, false ); +// } else { + showButton( Apply, false ); + saveTemplateText = i18n("Ok+Agenda"); + // } + setButtonText( User1, saveTemplateText ); + + //mCategoryDialog = new KPIM::CategorySelectDialog( KOPrefs::instance(), this ); + // KOGlobals::fitDialogToScreen( mCategoryDialog ); + + //connect(mCategoryDialog,SIGNAL(editCategories()),SIGNAL(editCategories())); + + //connect( this, SIGNAL( defaultClicked() ), SLOT( slotLoadTemplate() ) ); + // connect( this, SIGNAL( user1Clicked() ), SLOT( slotSaveTemplate() ) ); + connect( this, SIGNAL( user1Clicked() ), SLOT( slotShowIncidence() ) ); +} + +KOIncidenceEditor::~KOIncidenceEditor() +{ + //delete mCategoryDialog; +} + +void KOIncidenceEditor::setupAttendeesTab() +{ + QFrame *topFrame = addPage(i18n("Attendees")); + + QBoxLayout *topLayout = new QVBoxLayout(topFrame); + + mDetails = new KOEditorDetails(spacingHint(),topFrame); + topLayout->addWidget(mDetails); +} + + +void KOIncidenceEditor::slotApply() +{ + processInput( false ); +} +void KOIncidenceEditor::accept() +{ + slotOk(); +} +void KOIncidenceEditor::slotOk() +{ + if ( processInput( false ) ) QDialog::accept(); +} + +void KOIncidenceEditor::updateCategoryConfig() +{ + qDebug("KOIncidenceEditor::updateCategoryConfig() is dead! "); + //mCategoryDialog->updateCategoryConfig(); +} + +void KOIncidenceEditor::slotCancel() +{ + reject(); +} + +void KOIncidenceEditor::slotLoadTemplate() +{ + kdDebug() << "KOIncidenceEditor::loadTemplate()" << endl; +} +void KOIncidenceEditor::slotShowIncidence() +{ + + if ( processInput(true ) ) { + accept(); + } +} + +void KOIncidenceEditor::slotSaveTemplate() +{ + kdDebug() << "KOIncidenceEditor::saveTemplate()" << endl; +} + +void KOIncidenceEditor::createSaveTemplateDialog( SaveTemplateDialog::IncidenceType type ) +{ + if ( !mSaveTemplateDialog ) { + mSaveTemplateDialog = new SaveTemplateDialog( type, this ); + connect( mSaveTemplateDialog, SIGNAL( templateSelected( const QString & ) ), + SLOT( saveTemplate( const QString & ) ) ); + } + mSaveTemplateDialog->show(); + mSaveTemplateDialog->raise(); +} + +void KOIncidenceEditor::saveAsTemplate( Incidence *incidence, + const QString &templateName ) +{ + CalendarLocal cal; + cal.addIncidence( incidence ); + ICalFormat format; + format.save( &cal, templateName ); +} + +QString KOIncidenceEditor::loadTemplate( Calendar *cal, const QString &type, + const QStringList &templates ) +{ + // bool ok = false; +// QString templateName = KInputDialog::getItem( i18n("Load Template"), +// i18n("Select a template to load:"), templates, 0, &ok ); +// if ( !ok || templateName.isEmpty() ) return QString::null; + +// QString fileName = locateLocal( "data", "korganizer/templates/" + type + "/" + +// templateName ); +// fn =KFileDialog:: getOpenFileName( fn, "Import filename(*.ics/*.vcs)", this ); + + // QString fileName;// =locateLocal( "templates", incidence->type() ); +// fileName=KFileDialog:: getOpenFileName( fileName, "Load "+incidence()->type(), this ); +// if ( fileNamelength() == 0) +// return QString::null; +// if ( fileName.isEmpty() ) { +// KMessageBox::error( this, i18n("Unable to find template '%1'.") +// .arg( fileName ) ); +// return QString::null; +// } else { +// ICalFormat format; +// if ( !format.load( cal, fileName ) ) { +// KMessageBox::error( this, i18n("Error loading template file '%1'.") +// .arg( fileName ) ); +// return QString::null; +// } +// } + + return ""; +} diff --git a/korganizer/koincidenceeditor.h b/korganizer/koincidenceeditor.h new file mode 100644 index 0000000..bfd6cc6 --- a/dev/null +++ b/korganizer/koincidenceeditor.h @@ -0,0 +1,105 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KOINCIDENCEEDITOR_H +#define KOINCIDENCEEDITOR_H + +#include <kdialogbase.h> + +#include <libkcal/calendar.h> + +#include "koeditordetails.h" +#include "savetemplatedialog.h" + +class QDateTime; +namespace KPIM { class CategorySelectDialog; } + +using namespace KCal; + +/** + This is the base class for the calendar component editors. +*/ +class KOIncidenceEditor : public KDialogBase +{ + Q_OBJECT + public: + /** + Construct new IncidenceEditor. + */ + KOIncidenceEditor( const QString &caption, Calendar *calendar, + QWidget *parent ); + virtual ~KOIncidenceEditor(); + + /** Initialize editor. This function creates the tab widgets. */ + virtual void init() = 0; + void accept(); + virtual void setCategories( QString )= 0; + + virtual void reload() = 0; + + public slots: + void updateCategoryConfig(); + + signals: + void editCategories(); + void showAgendaView( bool ); + void dialogClose( Incidence * ); + void jumpToTime( const QDate & ); + + protected slots: + void slotApply(); + void slotOk(); + void slotCancel(); + void slotShowIncidence(); + + virtual void slotLoadTemplate(); + virtual void slotSaveTemplate(); + + virtual void saveTemplate( const QString & ) = 0; + + protected: + void setupAttendeesTab(); + + void createSaveTemplateDialog( SaveTemplateDialog::IncidenceType ); + + QString loadTemplate( Calendar *cal, const QString &type, + const QStringList &templates ); + void saveAsTemplate( Incidence *, const QString &name ); + + /** + Process user input and create or update event. Returns false if input is invalid. + */ + virtual bool processInput( bool emitTime ) { return false; } + + Calendar *mCalendar; + + //KPIM::CategorySelectDialog *mCategoryDialog; + + KOEditorDetails *mDetails; + + private: + SaveTemplateDialog *mSaveTemplateDialog; +}; + +#endif + + diff --git a/korganizer/koincidenceeditor.moc b/korganizer/koincidenceeditor.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koincidenceeditor.moc diff --git a/korganizer/kojournalview.cpp b/korganizer/kojournalview.cpp new file mode 100644 index 0000000..579f24d --- a/dev/null +++ b/korganizer/kojournalview.cpp @@ -0,0 +1,113 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +// +// View of Journal entries + +#include <qlayout.h> +#include <qpopupmenu.h> + +#include <klocale.h> +#include <kdebug.h> +#include "koprefs.h" + +#include <libkcal/calendar.h> + +#include "journalentry.h" + +#include "kojournalview.h" +using namespace KOrg; +#include "kojournalview.moc" + +KOJournalView::KOJournalView(Calendar *calendar, QWidget *parent, + const char *name) + : KOrg::BaseView(calendar, parent, name) +{ + mEntry = new JournalEntry(calendar,this); + mEntry->setFont ( KOPrefs::instance()->mJornalViewFont ); + QBoxLayout *topLayout = new QVBoxLayout(this); + topLayout->addWidget(mEntry); + connect ( mEntry,SIGNAL(deleteJournal(Journal *) ),this ,SIGNAL(deleteJournal(Journal *) ) ) ; +} + +KOJournalView::~KOJournalView() +{ +} + +int KOJournalView::currentDateCount() +{ + return 0; +} + +QPtrList<Incidence> KOJournalView::selectedIncidences() +{ + QPtrList<Incidence> eventList; + + return eventList; +} +void KOJournalView::updateConfig() +{ + mEntry->setFont ( KOPrefs::instance()->mJornalViewFont ); +} +void KOJournalView::updateView() +{ + mEntry->setFont ( KOPrefs::instance()->mJornalViewFont ); +} + +void KOJournalView::flushView() +{ + mEntry->flushEntry(); +} + +void KOJournalView::showDates(const QDate &start, const QDate &) +{ +// kdDebug() << "KOJournalView::selectDates()" << endl; + + mEntry->setDate(start); + + Journal *j = calendar()->journal(start); + if (j) mEntry->setJournal(j); + else mEntry->clear(); + +// emit incidenceSelected( 0 ); +} + +void KOJournalView::showEvents(QPtrList<Event>) +{ + // After new creation of list view no events are selected. +// emit incidenceSelected( 0 ); +} + +void KOJournalView::changeEventDisplay(Event *, int /*action*/) +{ + updateView(); +} + +void KOJournalView::keyPressEvent ( QKeyEvent * e ) +{ + //qDebug("keyPressEven "); + if ( e->state() == Qt::ControlButton ) { + if ( e->key () == Qt::Key_Right || e->key () == Qt::Key_Left ) + e->ignore(); + } +} diff --git a/korganizer/kojournalview.h b/korganizer/kojournalview.h new file mode 100644 index 0000000..1c0be82 --- a/dev/null +++ b/korganizer/kojournalview.h @@ -0,0 +1,67 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOJOURNALVIEW_H +#define _KOJOURNALVIEW_H + +#include <korganizer/baseview.h> + +class JournalEntry; + +/** + * This class provides a journal view. + + * @short View for Journal components. + * @author Cornelius Schumacher <schumacher@kde.org> + * @see KOBaseView + */ +class KOJournalView : public KOrg::BaseView +{ + Q_OBJECT + public: + KOJournalView(Calendar *calendar, QWidget *parent = 0, + const char *name = 0); + ~KOJournalView(); + + virtual int currentDateCount(); + virtual QPtrList<Incidence> selectedIncidences(); + DateList selectedDates() + {DateList q; + return q;}; + signals: + void deleteJournal(Journal *); + public slots: + void updateView(); + void flushView(); + void updateConfig(); + void showDates( const QDate &start, const QDate &end ); + void showEvents(QPtrList<Event> eventList); + + void changeEventDisplay(Event *, int); + + private: + JournalEntry *mEntry; + void keyPressEvent ( QKeyEvent * ) ; + +}; + +#endif diff --git a/korganizer/kojournalview.moc b/korganizer/kojournalview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kojournalview.moc diff --git a/korganizer/kolistview.cpp b/korganizer/kolistview.cpp new file mode 100644 index 0000000..b6061d0 --- a/dev/null +++ b/korganizer/kolistview.cpp @@ -0,0 +1,1062 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1999 Preston Brown + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlistview.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qpopupmenu.h> +#include <qprogressbar.h> +#include <qfileinfo.h> +#include <qmessagebox.h> +#include <qdialog.h> +#include <qtextstream.h> +#include <qdir.h> + +#include <klocale.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kglobal.h> + +#include <libkcal/calendar.h> +#include <libkcal/calendarlocal.h> +#include <libkcal/icalformat.h> +#include <libkcal/vcalformat.h> +#include <libkcal/recurrence.h> +#include <libkcal/filestorage.h> +#include <libkdepim/categoryselectdialog.h> +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#else +#include <qapplication.h> +#endif + +#ifndef KORG_NOPRINTER +#include "calprinter.h" +#endif +#include "koglobals.h" +#include "koprefs.h" +#include "kfiledialog.h" + +#include "kolistview.h" +#include "kolistview.moc" + +ListItemVisitor::ListItemVisitor(KOListViewItem *item, QDate date ) +{ + mItem = item; + mDate = date; +} + +ListItemVisitor::~ListItemVisitor() +{ +} + +bool ListItemVisitor::visit(Event *e) +{ + + bool ok = false; + QString start, end; + if ( e->doesRecur() ) { + QDate d = e->getNextOccurence( QDateTime( mDate, QTime(0,0,0)), &ok ).date(); + if ( ok ) { + int days = e->dtStart().date().daysTo(e->dtEnd().date() ); + start = KGlobal::locale()->formatDate(d,true); + end = KGlobal::locale()->formatDate(d.addDays( days),true); + } + + } + if ( ! ok ) { + start =e->dtStartDateStr(); + end = e->dtEndDateStr(); + } + mItem->setText(0,e->summary()); + mItem->setText(1,start); + mItem->setText(2,e->dtStartTimeStr()); + mItem->setText(3,end); + mItem->setText(4,e->dtEndTimeStr()); + mItem->setText(5,e->isAlarmEnabled() ? i18n("Yes") : i18n("No")); + mItem->setText(6, e->recurrence()->recurrenceText()); + mItem->setText(7,"---"); + mItem->setText(8,"---"); + mItem->setText(9, e->cancelled() ? i18n("Yes") : i18n("No")); + mItem->setText(10,e->categoriesStr()); + + QString key; + QDate d = e->dtStart().date(); + QTime t = e->doesFloat() ? QTime(0,0) : e->dtStart().time(); + key.sprintf("%04d%02d%02d%02d%02d",d.year(),d.month(),d.day(),t.hour(),t.minute()); + mItem->setSortKey(1,key); + + d = e->dtEnd().date(); + t = e->doesFloat() ? QTime(0,0) : e->dtEnd().time(); + key.sprintf("%04d%02d%02d%02d%02d",d.year(),d.month(),d.day(),t.hour(),t.minute()); + mItem->setSortKey(3,key); + + return true; +} + +bool ListItemVisitor::visit(Todo *t) +{ + mItem->setText(0,i18n("To-Do: %1").arg(t->summary())); + if (t->hasStartDate()) { + mItem->setText(1,t->dtStartDateStr()); + if (t->doesFloat()) { + mItem->setText(2,"---"); + } else { + mItem->setText(2,t->dtStartTimeStr()); + } + } else { + mItem->setText(1,"---"); + mItem->setText(2,"---"); + } + mItem->setText(3,"---"); + mItem->setText(4,"---"); + mItem->setText(5,"---"); + mItem->setText(6,"---"); + if (t->hasDueDate()) { + mItem->setText(7,t->dtDueDateStr()); + if (t->doesFloat()) { + mItem->setText(8,"---"); + } else { + mItem->setText(8,t->dtDueTimeStr()); + } + } else { + mItem->setText(7,"---"); + mItem->setText(8,"---"); + } + mItem->setText(9, t->cancelled() ? i18n("Yes") : i18n("No")); + mItem->setText(10,t->categoriesStr()); + + QString key; + QDate d; + if (t->hasDueDate()) { + d = t->dtDue().date(); + QTime tm = t->doesFloat() ? QTime(0,0) : t->dtDue().time(); + key.sprintf("%04d%02d%02d%02d%02d",d.year(),d.month(),d.day(),tm.hour(),tm.minute()); + mItem->setSortKey(7,key); + } + if ( t->hasStartDate() ) { + d = t->dtStart().date(); + QTime tm = t->doesFloat() ? QTime(0,0) : t->dtStart().time(); + key.sprintf("%04d%02d%02d%02d%02d",d.year(),d.month(),d.day(),tm.hour(),tm.minute()); + mItem->setSortKey(1,key); + } + return true; +} + +bool ListItemVisitor::visit(Journal * j) +{ + mItem->setText(0,i18n("Journal")); + mItem->setText(1,j->dtStartDateStr()); + mItem->setText(2,"---"); + mItem->setText(3,"---"); + mItem->setText(4,"---"); + mItem->setText(5,"---"); + mItem->setText(6,"---"); + mItem->setText(7,j->dtStartDateStr()); + mItem->setText(8,"---"); + mItem->setText(9,"---"); + + QString key; + QDate d = j->dtStart().date(); + key.sprintf("%04d%02d%02d",d.year(),d.month(),d.day()); + mItem->setSortKey(1,key); + mItem->setSortKey(7,key); + + return true; +} + +KOListView::KOListView(Calendar *calendar, QWidget *parent, + const char *name) + : KOEventView(calendar, parent, name) +{ + mActiveItem = 0; + mListView = new KOListViewListView(this); + mListView->addColumn(i18n("Summary")); + mListView->addColumn(i18n("Start Date")); + mListView->addColumn(i18n("Start Time")); + mListView->addColumn(i18n("End Date")); + mListView->addColumn(i18n("End Time")); + mListView->addColumn(i18n("Alarm")); // alarm set? + mListView->addColumn(i18n("Recurs")); // recurs? + mListView->addColumn(i18n("Due Date")); + mListView->addColumn(i18n("Due Time")); + mListView->addColumn(i18n("Cancelled")); + mListView->addColumn(i18n("Categories")); + + mListView->setColumnAlignment(0,AlignLeft); + mListView->setColumnAlignment(1,AlignLeft); + mListView->setColumnAlignment(2,AlignHCenter); + mListView->setColumnAlignment(3,AlignLeft); + mListView->setColumnAlignment(4,AlignHCenter); + mListView->setColumnAlignment(5,AlignLeft); + mListView->setColumnAlignment(6,AlignLeft); + mListView->setColumnAlignment(7,AlignLeft); + mListView->setColumnAlignment(8,AlignLeft); + mListView->setColumnAlignment(9,AlignLeft); + mListView->setColumnAlignment(10,AlignLeft); + + int iii = 0; + for ( iii = 0; iii< 10 ; ++iii ) + mListView->setColumnWidthMode( iii, QListView::Manual ); + + QBoxLayout *layoutTop = new QVBoxLayout(this); + layoutTop->addWidget(mListView); + mListView->setFont ( KOPrefs::instance()->mListViewFont ); + mPopupMenu = eventPopup(); + mPopupMenu->addAdditionalItem(QIconSet(QPixmap()), + i18n("Select all"),this, + SLOT(allSelection()),true); + mPopupMenu->addAdditionalItem(QIconSet(QPixmap()), + i18n("Deselect All"),this, + SLOT(clearSelection()),true); + mPopupMenu->addAdditionalItem(QIconSet(QPixmap()), + i18n("Delete all selected"),this, + SLOT(deleteAll()),true); + mPopupMenu->insertSeparator(); + mPopupMenu->addAdditionalItem(QIconSet(QPixmap()), + i18n("Save selected to file..."),this, + SLOT(saveToFile()),true); + mPopupMenu->addAdditionalItem(QIconSet(QPixmap()), + i18n("Save Journal/Description..."),this, + SLOT(saveDescriptionToFile()),true); + mPopupMenu->insertSeparator(); + mPopupMenu->addAdditionalItem(QIconSet(QPixmap()), + i18n("Add Categ. to selected..."),this, + SLOT(addCat()),true); + mPopupMenu->addAdditionalItem(QIconSet(QPixmap()), + i18n("Set Categ. for selected..."),this, + SLOT(setCat()),true); + mPopupMenu->insertSeparator(); + + +#ifndef DESKTOP_VERSION + mPopupMenu->addAdditionalItem(QIconSet(QPixmap()), + i18n("Beam selected via IR"),this, + SLOT(beamSelected()),true); +#endif + /* + mPopupMenu = new QPopupMenu; + mPopupMenu->insertItem(i18n("Edit Event"), this, + SLOT (editEvent())); + mPopupMenu->insertItem(SmallIcon("delete"), i18n("Delete Event"), this, + SLOT (deleteEvent())); + mPopupMenu->insertSeparator(); + mPopupMenu->insertItem(i18n("Show Dates"), this, + SLOT(showDates())); + mPopupMenu->insertItem(i18n("Hide Dates"), this, + SLOT(hideDates())); + */ + QObject::connect(mListView,SIGNAL( newEvent()), + this,SIGNAL(signalNewEvent())); + QObject::connect(mListView,SIGNAL(doubleClicked(QListViewItem *)), + this,SLOT(defaultItemAction(QListViewItem *))); + QObject::connect(mListView,SIGNAL(rightButtonClicked ( QListViewItem *, + const QPoint &, int )), + this,SLOT(popupMenu(QListViewItem *,const QPoint &,int))); + QObject::connect(mListView,SIGNAL(currentChanged(QListViewItem *)), + SLOT(processSelectionChange(QListViewItem *))); + QObject::connect(mListView,SIGNAL(showIncidence(Incidence *)), + SIGNAL(showIncidenceSignal(Incidence *)) ); + + readSettings(KOGlobals::config(),"KOListView Layout"); +} + +KOListView::~KOListView() +{ + delete mPopupMenu; +} + +void KOListView::updateList() +{ + // qDebug(" KOListView::updateList() "); + +} + +void KOListView::addCat( ) +{ + setCategories( false ); +} +void KOListView::setCat() +{ + setCategories( true ); +} +void KOListView::setCategories( bool removeOld ) +{ + + KPIM::CategorySelectDialog* csd = new KPIM::CategorySelectDialog( KOPrefs::instance(), 0 ); + if (! csd->exec()) { + delete csd; + return; + } + QStringList catList = csd->selectedCategories(); + delete csd; + // if ( catList.count() == 0 ) + // return; + catList.sort(); + QString categoriesStr = catList.join(","); + int i; + QStringList itemList; + QPtrList<KOListViewItem> sel ; + QListViewItem *qitem = mListView->firstChild (); + while ( qitem ) { + if ( qitem->isSelected() ) { + sel.append(((KOListViewItem *)qitem)); + } + qitem = qitem->nextSibling(); + } + KOListViewItem * item, *temp; + item = sel.first(); + Incidence* inc; + while ( item ) { + inc = item->data(); + if ( removeOld ) { + inc->setCategories( categoriesStr ); + } else { + itemList = QStringList::split (",", inc->categoriesStr() ); + for( i = 0; i< catList.count(); ++i ) { + if ( !itemList.contains (catList[i])) + itemList.append( catList[i] ); + } + itemList.sort(); + inc->setCategories( itemList.join(",") ); + } + temp = item; + item = sel.next(); + mUidDict.remove( inc->uid() ); + delete temp;; + addIncidence( inc ); + } +} + +void KOListView::beamSelected() +{ + int icount = 0; + QPtrList<Incidence> delSel ; + QListViewItem *item = mListView->firstChild (); + while ( item ) { + if ( item->isSelected() ) { + delSel.append(((KOListViewItem *)item)->data()); + ++icount; + } + + item = item->nextSibling(); + } + if ( icount ) { + emit beamIncidenceList( delSel ); + return; + QString fn ; + fn = QDir::homeDirPath()+"/kopitempbeamfile.vcs"; + QString mes; + bool createbup = true; + if ( createbup ) { + QString description = "\n"; + CalendarLocal* cal = new CalendarLocal(); + cal->setTimeZoneId(KOPrefs::instance()->mTimeZoneId); + Incidence *incidence = delSel.first(); + while ( incidence ) { + Incidence *in = incidence->clone(); + description += in->summary() + "\n"; + cal->addIncidence( in ); + incidence = delSel.next(); + } + FileStorage storage( cal, fn, new VCalFormat ); + storage.save(); + delete cal; + mes = i18n("KO/Pi: Ready for beaming"); + topLevelWidget()->setCaption(mes); + +#ifndef DESKTOP_VERSION + Ir *ir = new Ir( this ); + connect( ir, SIGNAL( done( Ir * ) ), this, SLOT( beamDone( Ir * ) ) ); + ir->send( fn, description, "text/x-vCalendar" ); +#endif + } + } +} +void KOListView::beamDone( Ir *ir ) +{ +#ifndef DESKTOP_VERSION + delete ir; +#endif + topLevelWidget()->setCaption(i18n("KO/Pi:Beaming done")); +} + +void KOListView::saveDescriptionToFile() +{ + + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + i18n("This saves the text/details of selected\nJournals and Events/Todos\nto a text file."), + i18n("Continue"), i18n("Cancel"), 0, + 0, 1 ); + if ( result != 0 ) { + return; + } + int icount = 0; + QPtrList<Incidence> delSel ; + QListViewItem *item = mListView->firstChild (); + while ( item ) { + if ( item->isSelected() ) { + delSel.append(((KOListViewItem *)item)->data()); + ++icount; + } + + item = item->nextSibling(); + } + if ( icount ) { + QString fn = KOPrefs::instance()->mLastSaveFile; + fn = KFileDialog::getSaveFileName( fn, i18n("Save filename"), this ); + + if ( fn == "" ) + return; + QFileInfo info; + info.setFile( fn ); + QString mes; + bool createbup = true; + if ( info. exists() ) { + mes = i18n("File already exists!\nOld file from:\n%1\nOverwrite?\n").arg (KGlobal::locale()->formatDateTime(info.lastModified (), true, false ) ); + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),mes, + i18n("Overwrite!"), i18n("Cancel"), 0, + 0, 1 ); + if ( result != 0 ) { + createbup = false; + } + } + if ( createbup ) { + QString text = i18n("KO/Pi Description/Journal save file.\nSave date: ") + + KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(), false); + Incidence *incidence = delSel.first(); + icount = 0; + while ( incidence ) { + if ( incidence->type() == "Journal" ) { + text += "\n************************************\n"; + text += i18n("Journal from: ") +incidence->dtStartDateStr( false ); + text +="\n" + i18n("Last modified: ") +KGlobal::locale()->formatDateTime(incidence->lastModified(), false); + text +="\n" + i18n("Description: ") + "\n"+ incidence->description(); + ++icount; + + } else { + if ( !incidence->description().isEmpty() ) { + text += "\n************************************\n"; + if ( incidence->type() == "Todo" ) + text += i18n("To-Do: "); + text += incidence->summary(); + if ( incidence->hasStartDate() ) + text +="\n"+ i18n("Start Date: ") + incidence->dtStartStr( false ); + text +="\n"+ i18n("Last modified: ") +KGlobal::locale()->formatDateTime(incidence->lastModified(), false); + if ( !incidence->location().isEmpty() ) + text += "\n" +i18n("Location: ") + incidence->location(); + text += "\n" + i18n("Description: ") + "\n" + incidence->description(); + ++icount; + + } + } + incidence = delSel.next(); + } + QFile file( fn ); + if (!file.open( IO_WriteOnly ) ) { + topLevelWidget()->setCaption(i18n("File open error - nothing saved!") ); + return; + } + QTextStream ts( &file ); + ts << text; + file.close(); + //qDebug("%s ", text.latin1()); + mes = i18n("KO/Pi:Saved %1 descriptions/journals").arg(icount ); + KOPrefs::instance()->mLastSaveFile = fn; + topLevelWidget()->setCaption(mes); + } + } +} +void KOListView::saveToFile() +{ + + int icount = 0; + QPtrList<Incidence> delSel ; + QListViewItem *item = mListView->firstChild (); + while ( item ) { + if ( item->isSelected() ) { + delSel.append(((KOListViewItem *)item)->data()); + ++icount; + } + + item = item->nextSibling(); + } + if ( icount ) { + QString fn = KOPrefs::instance()->mLastSaveFile; + fn = KFileDialog::getSaveFileName( fn, i18n("Save filename"), this ); + + if ( fn == "" ) + return; + QFileInfo info; + info.setFile( fn ); + QString mes; + bool createbup = true; + if ( info. exists() ) { + mes = i18n("File already exists!\nOld file from:\n%1\nOverwrite?\n").arg (KGlobal::locale()->formatDateTime(info.lastModified (), true, false ) ); + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),mes, + i18n("Overwrite!"), i18n("Cancel"), 0, + 0, 1 ); + if ( result != 0 ) { + createbup = false; + } + } + if ( createbup ) { + CalendarLocal cal; + cal.setTimeZoneId(KOPrefs::instance()->mTimeZoneId); + Incidence *incidence = delSel.first(); + while ( incidence ) { + cal.addIncidence( incidence->clone() ); + incidence = delSel.next(); + } + ICalFormat format; + format.save( &cal, fn ); + mes = i18n("KO/Pi:Saved %1").arg(fn ); + KOPrefs::instance()->mLastSaveFile = fn; + topLevelWidget()->setCaption(mes); + } + } +} +void KOListView::deleteAll() +{ + int icount = 0; + QPtrList<Incidence> delSel ; + QListViewItem *item = mListView->firstChild (); + while ( item ) { + if ( item->isSelected() ) { + delSel.append(((KOListViewItem *)item)->data()); + ++icount; + } + + item = item->nextSibling(); + } + if ( icount ) { + Incidence *incidence = delSel.first(); + Incidence *toDelete; + KOPrefs *p = KOPrefs::instance(); + bool confirm = p->mConfirm; + QString mess; + mess = mess.sprintf( i18n("You have %d item(s) selected.\n"), icount ); + if ( KMessageBox::Continue == KMessageBox::warningContinueCancel(this, mess + i18n("All selected items will be\npermanently deleted.\n(Deleting items will take\nsome time on a PDA)\n"), i18n("KO/Pi Confirmation"),i18n("Delete")) ) { + p->mConfirm = false; + int delCounter = 0; + QDialog dia ( this, "p-dialog", true ); + QLabel lab (i18n("Close dialog to abort deletion!"), &dia ); + QVBoxLayout lay( &dia ); + lay.setMargin(7); + lay.setSpacing(7); + lay.addWidget( &lab); + QProgressBar bar( icount, &dia ); + lay.addWidget( &bar); + int w = 220; + int h = 50; + int dw = QApplication::desktop()->width(); + int dh = QApplication::desktop()->height(); + dia.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); + //dia.resize( 240,50 ); + dia.show(); + + while ( incidence ) { + bar.setProgress( delCounter ); + mess = mess.sprintf( i18n("Deleting item %d ..."), ++delCounter ); + dia.setCaption( mess ); + qApp->processEvents(); + toDelete = (incidence); + incidence = delSel.next(); + emit deleteIncidenceSignal(toDelete ); + if ( dia.result() != 0 ) + break; + + } + mess = mess.sprintf( i18n("%d items remaining in list."), count() ); + topLevelWidget ()->setCaption( mess ); + p->mConfirm = confirm; + } + } + + +} +int KOListView::maxDatesHint() +{ + return 0; +} + +int KOListView::currentDateCount() +{ + return 0; +} + +QPtrList<Incidence> KOListView::selectedIncidences() +{ + QPtrList<Incidence> eventList; + QListViewItem *item = mListView->firstChild (); + while ( item ) { + if ( item->isSelected() ) { + eventList.append(((KOListViewItem *)item)->data()); + } + + item = item->nextSibling(); + } + + // // QListViewItem *item = mListView->selectedItem(); + //if (item) eventList.append(((KOListViewItem *)item)->data()); + + return eventList; +} + +DateList KOListView::selectedDates() +{ + DateList eventList; + return eventList; +} + +void KOListView::showDates(bool show) +{ + // Shouldn't we set it to a value greater 0? When showDates is called with + // show == true at first, then the columnwidths are set to zero. + static int oldColWidth1 = 0; + static int oldColWidth3 = 0; + + if (!show) { + oldColWidth1 = mListView->columnWidth(1); + oldColWidth3 = mListView->columnWidth(3); + mListView->setColumnWidth(1, 0); + mListView->setColumnWidth(3, 0); + } else { + mListView->setColumnWidth(1, oldColWidth1); + mListView->setColumnWidth(3, oldColWidth3); + } + mListView->repaint(); +} + +void KOListView::printPreview(CalPrinter *calPrinter, const QDate &fd, + const QDate &td) +{ +#ifndef KORG_NOPRINTER + calPrinter->preview(CalPrinter::Day, fd, td); +#endif +} + +void KOListView::showDates() +{ + showDates(true); +} + +void KOListView::hideDates() +{ + showDates(false); +} + +void KOListView::updateView() +{ + mListView->setFocus(); + if ( mListView->firstChild () ) + mListView->setCurrentItem( mListView->firstChild () ); +} +void KOListView::updateConfig() +{ + + mListView->setFont ( KOPrefs::instance()->mListViewFont ); + updateView(); + +} +void KOListView::setStartDate(const QDate &start) +{ + mStartDate = start; +} + +void KOListView::showDates(const QDate &start, const QDate &end) +{ + clear(); + mStartDate = start; + QDate date = start; + while( date <= end ) { + addEvents(calendar()->events(date)); + addTodos(calendar()->todos(date)); + date = date.addDays( 1 ); + } + emit incidenceSelected( 0 ); + updateView(); + +} + +void KOListView::addEvents(QPtrList<Event> eventList) +{ + Event *ev; + for(ev = eventList.first(); ev; ev = eventList.next()) { + addIncidence(ev); + } + if ( !mListView->currentItem() ){ + updateView(); + } +} + +void KOListView::addTodos(QPtrList<Todo> eventList) +{ + Todo *ev; + for(ev = eventList.first(); ev; ev = eventList.next()) { + addIncidence(ev); + } + if ( !mListView->currentItem() ){ + updateView(); + } +} +void KOListView::addJournals(QPtrList<Journal> eventList) +{ + Journal *ev; + for(ev = eventList.first(); ev; ev = eventList.next()) { + addIncidence(ev); + } + if ( !mListView->currentItem() ){ + updateView(); + } +} + +void KOListView::addIncidence(Incidence *incidence) +{ + if ( mUidDict.find( incidence->uid() ) ) return; + + // mListView->setFont ( KOPrefs::instance()->mListViewFont ); + mUidDict.insert( incidence->uid(), incidence ); + + KOListViewItem *item = new KOListViewItem( incidence, mListView ); + ListItemVisitor v(item, mStartDate ); + if (incidence->accept(v)) return; + else delete item; + //qDebug("delete item "); +} + +void KOListView::showEvents(QPtrList<Event> eventList) +{ + clear(); + + addEvents(eventList); + + // After new creation of list view no events are selected. + emit incidenceSelected( 0 ); +} +int KOListView::count() +{ + return mListView->childCount(); +} + +void KOListView::changeEventDisplay(Event *event, int action) +{ + KOListViewItem *item; + + switch(action) { + case KOGlobals::EVENTADDED: + addIncidence( event ); + break; + case KOGlobals::EVENTEDITED: + item = getItemForEvent(event); + if (item) { + mUidDict.remove( event->uid() ); + delete item; + addIncidence( event ); + } + break; + case KOGlobals::EVENTDELETED: + item = getItemForEvent(event); + if (item) { + mUidDict.remove( event->uid() ); + delete item; + } + break; + default: + ; + } +} + +KOListViewItem *KOListView::getItemForEvent(Event *event) +{ + KOListViewItem *item = (KOListViewItem *)mListView->firstChild(); + while (item) { + if (item->data() == event) return item; + item = (KOListViewItem *)item->nextSibling(); + } + return 0; +} + +void KOListView::defaultItemAction(QListViewItem *i) +{ + KOListViewItem *item = static_cast<KOListViewItem *>( i ); + if ( item ) defaultAction( item->data() ); + +} + +void KOListView::popupMenu(QListViewItem *item,const QPoint &,int) +{ + mActiveItem = (KOListViewItem *)item; + if (mActiveItem) { + Incidence *incidence = mActiveItem->data(); + mPopupMenu->showIncidencePopup(incidence); + + /* + if ( incidence && incidence->type() == "Event" ) { + Event *event = static_cast<Event *>( incidence ); + mPopupMenu->showEventPopup(event); + } + */ + } +} + +void KOListView::readSettings(KConfig *config, QString setting) +{ + // qDebug("KOListView::readSettings "); + mListView->restoreLayout(config,setting); +} + +void KOListView::writeSettings(KConfig *config, QString setting) +{ + // qDebug("KOListView::writeSettings "); + mListView->saveLayout(config, setting); +} + +void KOListView::processSelectionChange(QListViewItem *) +{ + + KOListViewItem *item = + static_cast<KOListViewItem *>( mListView->currentItem() ); + + if ( !item ) { + emit incidenceSelected( 0 ); + } else { + emit incidenceSelected( item->data() ); + } +} + +void KOListView::clearSelection() +{ + mListView->selectAll( false ); +} +void KOListView::allSelection() +{ + mListView->selectAll( true ); +} + +void KOListView::clear() +{ + mListView->clear(); + mUidDict.clear(); +} + +Incidence* KOListView::currentItem() +{ + if ( mListView->currentItem() ) + return ((KOListViewItem*) mListView->currentItem())->data(); + return 0; +} +void KOListView::keyPressEvent ( QKeyEvent *e) +{ + + if ( e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace ) { + deleteAll(); + return; + } + + e->ignore(); +} +void KOListViewListView::keyPressEvent ( QKeyEvent *e) +{ + + switch ( e->key() ) { + case Qt::Key_Down: + if ( e->state() == ShiftButton ) { + QListViewItem* cn = currentItem(); + if ( !cn ) + cn = firstChild(); + if ( !cn ) + return; + while ( cn->nextSibling() ) + cn = cn->nextSibling(); + setCurrentItem ( cn ); + ensureItemVisible ( cn ); + + e->accept(); + return; + } + if ( e->state() == ControlButton ) { + int count = childCount (); + int jump = count / 5; + QListViewItem* cn; + cn = currentItem(); + if ( ! cn ) + return; + if ( jump == 0 ) + jump = 1; + while ( jump && cn->nextSibling() ) { + cn = cn->nextSibling(); + --jump; + } + setCurrentItem ( cn ); + ensureItemVisible ( cn ); + + } else + QListView::keyPressEvent ( e ) ; + e->accept(); + break; + + case Qt::Key_Up: + if ( e->state() == ShiftButton ) { + QListViewItem* cn = firstChild(); + if ( cn ) { + setCurrentItem ( cn ); + ensureItemVisible ( cn ); + } + e->accept(); + return; + } + if ( e->state() == ControlButton ) { + int count = childCount (); + int jump = count / 5; + QListViewItem* cn; + cn = currentItem(); + if ( ! cn ) + return; + if ( jump == 0 ) + jump = 1; + while ( jump && cn->itemAbove ()) { + cn = cn->itemAbove (); + --jump; + } + setCurrentItem ( cn ); + ensureItemVisible ( cn ); + } else + QListView::keyPressEvent ( e ) ; + e->accept(); + break; + case Qt::Key_I: { + QListViewItem* cn; + cn = currentItem(); + if ( cn ) { + KOListViewItem* ci = (KOListViewItem*)( cn ); + if ( ci ){ + emit showIncidence( ci->data()); + cn = cn->nextSibling(); + if ( cn ) { + setCurrentItem ( cn ); + ensureItemVisible ( cn ); + } + } + } + e->accept(); + } + break; + case Qt::Key_Return: + case Qt::Key_Enter: + { + QListViewItem* cn; + cn = currentItem(); + if ( cn ) { + KOListViewItem* ci = (KOListViewItem*)( cn ); + if ( ci ){ + if ( e->state() == ShiftButton ) + ci->setSelected( false ); + else + ci->setSelected( true ); + cn = cn->nextSibling(); + if ( cn ) { + setCurrentItem ( cn ); + ensureItemVisible ( cn ); + } + } + } + e->accept(); + } + break; + default: + e->ignore(); + } +} +KOListViewListView::KOListViewListView(KOListView * lv ) + : KListView( lv ) +{ +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation(viewport(), QPEApplication::RightOnHold ); +#endif + setSelectionMode( QListView::Multi ); + setMultiSelection( true); + mAllowPopupMenu = true; + mMouseDown = false; + +} +void KOListViewListView::contentsMouseDoubleClickEvent(QMouseEvent *e) +{ + if (!e) return; + QPoint vp = contentsToViewport(e->pos()); + QListViewItem *item = itemAt(vp); + if (!item) { + emit newEvent(); + return; + } + KListView::contentsMouseDoubleClickEvent(e); +} + + +void KOListViewListView::contentsMousePressEvent(QMouseEvent *e) +{ + //qDebug("contentsMousePressEvent++++ "); + if (! mMouseDown ) { + mAllowPopupMenu = true; + mYMousePos = mapToGlobal( (e->pos())).y(); + } + if ( e->button() == RightButton && mMouseDown ) + return; + if ( e->button() == LeftButton ) + mMouseDown = true; + KListView::contentsMousePressEvent( e ); +} +void KOListViewListView::contentsMouseReleaseEvent(QMouseEvent *e) +{ + //qDebug("contentsMouseReleaseEv---- "); + if ( ! mMouseDown ) { + if ( e->button() == RightButton && ! mAllowPopupMenu ) + return; + QListViewItem* ci = currentItem(); + if ( ci ) + ci->setSelected( true ); + KListView::contentsMouseReleaseEvent(e); + return; + } + if ( e->button() == LeftButton ) + mMouseDown = false; + if ( e->button() == RightButton && ! mAllowPopupMenu ) + return; + if ( e->button() == RightButton ) { + QListViewItem* ci = currentItem(); + if ( ci ) + ci->setSelected( true ); + } + KListView::contentsMouseReleaseEvent(e); +} +void KOListViewListView::contentsMouseMoveEvent(QMouseEvent *e) +{ + // qDebug("contentsMouseMoveEv....... "); + // qDebug("start: %d current %d ",mYMousePos , mapToGlobal( (e->pos())).y() ); + int diff = mYMousePos - mapToGlobal( (e->pos())).y(); + if ( diff < 0 ) diff = -diff; + if ( diff > 20 ) + mAllowPopupMenu = false; + KListView::contentsMouseMoveEvent(e); +} diff --git a/korganizer/kolistview.h b/korganizer/kolistview.h new file mode 100644 index 0000000..23afdb1 --- a/dev/null +++ b/korganizer/kolistview.h @@ -0,0 +1,167 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1999 Preston Brown + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOLISTVIEW_H +#define _KOLISTVIEW_H + +#include <qlistview.h> +#include <qmap.h> +#include <qdict.h> + +#include <klistview.h> + +#ifndef DESKTOP_VERSION +#include <qtopia/ir.h> +#else +#define Ir char +#endif +#include <libkcal/incidence.h> + +#include "koeventview.h" +#include "customlistviewitem.h" + +using namespace KCal; + +typedef CustomListViewItem<Incidence *> KOListViewItem; + +/** + This class provides the initialisation of a KOListViewItem for calendar + components using the Incidence::Visitor. +*/ +class ListItemVisitor : public Incidence::Visitor +{ + public: + ListItemVisitor(KOListViewItem *, QDate d); + ~ListItemVisitor(); + + bool visit(Event *); + bool visit(Todo *); + bool visit(Journal *); + + private: + KOListViewItem *mItem; + QDate mDate; +}; + +/** + This class provides a multi-column list view of events. It can + display events from one particular day or several days, it doesn't + matter. To use a view that only handles one day at a time, use + KODayListView. + + @short multi-column list view of various events. + @author Preston Brown <pbrown@kde.org> + @see KOBaseView, KODayListView +*/ +class KOListView; + +class KOListViewListView : public KListView +{ + Q_OBJECT + public: + KOListViewListView(KOListView * lv ); + signals: + void newEvent(); + void showIncidence( Incidence* ); + private: + void keyPressEvent ( QKeyEvent * ) ; + void contentsMouseDoubleClickEvent(QMouseEvent *e); + void contentsMousePressEvent(QMouseEvent *e); + void contentsMouseReleaseEvent(QMouseEvent *e); + void contentsMouseMoveEvent(QMouseEvent *e); + bool mAllowPopupMenu; + bool mMouseDown; + int mYMousePos; +}; + +class KOListView : public KOEventView +{ + Q_OBJECT + public: + KOListView(Calendar *calendar, QWidget *parent = 0, + const char *name = 0); + ~KOListView(); + + virtual int maxDatesHint(); + virtual int currentDateCount(); + virtual QPtrList<Incidence> selectedIncidences(); + virtual DateList selectedDates(); + + void showDates(bool show); + Incidence* currentItem(); + void addTodos(QPtrList<Todo> eventList); + void addJournals(QPtrList<Journal> eventList); + virtual void printPreview(CalPrinter *calPrinter, + const QDate &, const QDate &); + + void readSettings(KConfig *config, QString setting = "KOListView Layout"); + void writeSettings(KConfig *config, QString setting = "KOListView Layout"); + void updateList(); + void setStartDate(const QDate &start); + int count(); + signals: + void signalNewEvent(); + void beamIncidenceList(QPtrList<Incidence>); + + public slots: + virtual void updateView(); + virtual void showDates(const QDate &start, const QDate &end); + virtual void showEvents(QPtrList<Event> eventList); + void clearSelection(); + void allSelection(); + + void clear(); + void beamDone( Ir *ir ); + void showDates(); + void hideDates(); + void deleteAll(); + void saveToFile(); + void saveDescriptionToFile(); + void beamSelected(); + void updateConfig(); + void addCat(); + void setCat(); + void setCategories( bool removeOld ); + void changeEventDisplay(Event *, int); + + void defaultItemAction(QListViewItem *item); + void popupMenu(QListViewItem *item,const QPoint &,int); + + protected slots: + void processSelectionChange(QListViewItem *); + + protected: + void addEvents(QPtrList<Event> eventList); + void addIncidence(Incidence *); + KOListViewItem *getItemForEvent(Event *event); + + private: + KOListViewListView *mListView; + KOEventPopupMenu *mPopupMenu; + KOListViewItem *mActiveItem; + QDict<Incidence> mUidDict; + QDate mStartDate; + void keyPressEvent ( QKeyEvent * ) ; +}; + +#endif diff --git a/korganizer/kolistview.moc b/korganizer/kolistview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kolistview.moc diff --git a/korganizer/kolocationbox.cpp b/korganizer/kolocationbox.cpp new file mode 100644 index 0000000..f8fee2e --- a/dev/null +++ b/korganizer/kolocationbox.cpp @@ -0,0 +1,96 @@ +/* + Copyright (c) 2004 Dirk Loesche <dirk.loesche@bigfoot.de> + + This file is part of KOrganizer/PI + KOrganizer Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + KOrganizer/PI Copyright (c) 2004 Lutz Rogowski <lutz@pi-sync.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "kolocationbox.h" +#include <qstring.h> +#include <qlineedit.h> +#include <qapplication.h> + + +KOLocationBox::KOLocationBox( bool rw , QWidget *parent , int _maxItems) : + QComboBox( rw , parent ) +{ + maxItems = _maxItems; + maxItems = 50; // sorry - hack from me to set maxitems globally to 30 + setInsertionPolicy(AtTop); + setDuplicatesEnabled( FALSE ); + setMaxCount( maxItems ); + setAutoCompletion( TRUE ); + +} + +KOLocationBox::~KOLocationBox() +{ +} + +void KOLocationBox::load(int what) +{ + clear(); + // qDebug("load %d ",what ); + switch(what) { + case LOCATION: + insertStringList( KOPrefs::instance()->mLocationDefaults, 0 ); +// insertStringList( KOPrefs::instance()->mLocationUserDefaults, 0 ); + break; // don't disable + case SUMMARYEVENT: + insertStringList( KOPrefs::instance()->mEventSummaryUser, 0 ); + break; // don't disable + case SUMMARYTODO: + insertStringList( KOPrefs::instance()->mTodoSummaryUser, 0 ); + break; // don't disable + } +} + +void KOLocationBox::save(int what) +{ + strlist.clear(); + for( int l = 0; l < count() ; l++ ) { + strlist << text( l ); + } + // strlist.sort(); + QString currentLine = lineEdit()->text(); + if ( !strlist.contains( currentLine ) ) + strlist.prepend( currentLine ); + // qDebug("save %d ", what); + switch(what) { + case LOCATION: + KOPrefs::instance()->mLocationDefaults = strlist; +// KOPrefs::instance()->mLocationUserDefaults = strlist; + break; // don't disable + case SUMMARYEVENT: + KOPrefs::instance()->mEventSummaryUser = strlist; + break; // don't disable + case SUMMARYTODO: + KOPrefs::instance()->mTodoSummaryUser = strlist; + break; // don't disable + } +} + +void KOLocationBox::clearItems(int what) +{ + clear(); + save(what); +} diff --git a/korganizer/kolocationbox.h b/korganizer/kolocationbox.h new file mode 100644 index 0000000..be8ea86 --- a/dev/null +++ b/korganizer/kolocationbox.h @@ -0,0 +1,55 @@ +/* + File Copyright (c) 2004 Dirk Loesche <dirk.loesche@bigfoot.de> + + This file is part of KOrganizer/PI + KOrganizer Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + KOrganizer/PI Copyright (c) 2004 Lutz Rogowski <lutz@pi-sync.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KOLOCATIONBOX_H +#define KOLOCATIONBOX_H + +#include <qcombobox.h> +#include "koprefs.h" + +class KOLocationBox : public QComboBox +{ + public: + KOLocationBox( bool rw , QWidget *parent , int _maxItems ); + virtual ~KOLocationBox(); + + enum {LOCATION, SUMMARYEVENT, SUMMARYTODO}; + + public slots: + void load(int); + void save(int); + void clearItems(int); // clear listbox and config rc items + + protected: +// void focusOutEvent( QFocusEvent * ); +// void timerEvent( QTimerEvent * ); + + private: + int maxItems; // maximal listbox items + QStringList strlist; // temporary stringlist +}; + +#endif diff --git a/korganizer/komonthview.cpp b/korganizer/komonthview.cpp new file mode 100644 index 0000000..c4bc51b --- a/dev/null +++ b/korganizer/komonthview.cpp @@ -0,0 +1,1057 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <qpopupmenu.h> +#include <qfont.h> +#include <qfontmetrics.h> +#include <qkeycode.h> +#include <qhbox.h> +#include <qvbox.h> +#include <qpushbutton.h> +#include <qtooltip.h> +#include <qpainter.h> +#include <qwhatsthis.h> +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#else +#include <qapplication.h> +#endif + +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kiconloader.h> + +#include <kcalendarsystem.h> + +#ifndef KORG_NOPRINTER +#include "calprinter.h" +#endif +#include "koprefs.h" +#ifndef KORG_NOPLUGINS +#include "kocore.h" +#endif +#include "koglobals.h" +#include <libkdepim/kincidenceformatter.h> + +#include "komonthview.h" +#include "komonthview.moc" + +#define PIXMAP_SIZE 5 + +class KNOWhatsThis :public QWhatsThis +{ +public: + KNOWhatsThis( KNoScrollListBox* sbox ) : QWhatsThis( sbox ), _wid( sbox) { }; + +protected: + virtual QString text( const QPoint& p) + { + return _wid->getWhatsThisText(p) ; + }; +private: + KNoScrollListBox* _wid; + +}; + + +KNoScrollListBox::KNoScrollListBox(QWidget *parent,const char *name) + : QListBox(parent, name) +{ +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold ); +#endif + new KNOWhatsThis(this); +} + +QString KNoScrollListBox::getWhatsThisText(QPoint p) +{ + QListBoxItem* item = itemAt ( p ); + if ( ! item ) { + return i18n("Click in the cell or\non the date label\nto add an event!"); + } + return KIncidenceFormatter::instance()->getFormattedText(((MonthViewItem*) item)->incidence()); +} +void KNoScrollListBox::keyPressEvent(QKeyEvent *e) +{ + + switch(e->key()) { + case Key_Right: + // if ( e->state() == Qt::ControlButton ) + { + e->ignore(); + return; + } + scrollBy(4,0); + break; + case Key_Left: + // if ( e->state() == Qt::ControlButton ) + { + e->ignore(); + return; + } + scrollBy(-4,0); + break; + case Key_Up: + if(!count()) break; + setCurrentItem((currentItem()+count()-1)%count()); + if(!itemVisible(currentItem())) { + if((unsigned int) currentItem() == (count()-1)) { + setTopItem(currentItem()-numItemsVisible()+1); + } else { + setTopItem(topItem()-1); + } + } + break; + case Key_Down: + if(!count()) break; + setCurrentItem((currentItem()+1)%count()); + if(!itemVisible(currentItem())) { + if(currentItem() == 0) { + setTopItem(0); + } else { + setTopItem(topItem()+1); + } + } + break; + case Key_Shift: + emit shiftDown(); + break; + default: + e->ignore(); + break; + } +} + +void KNoScrollListBox::keyReleaseEvent(QKeyEvent *e) +{ + switch(e->key()) { + case Key_Shift: + emit shiftUp(); + break; + default: + break; + } +} + +void KNoScrollListBox::mousePressEvent(QMouseEvent *e) +{ + QListBox::mousePressEvent(e); + + if(e->button() == RightButton) { + emit rightClick(); + } +} + +MonthViewItem::MonthViewItem( Incidence *incidence, QDate qd, const QString & s) + : QListBoxItem() +{ + setText( s ); + + mIncidence = incidence; + mDate = qd; + // QWhatsThis::add(this,KIncidenceFormatter::instance()->getFormattedText( mIncidence )); + mRecur = false; + mAlarm = false; + mReply = false; + mInfo = false; +} + +void MonthViewItem::paint(QPainter *p) +{ +#if QT_VERSION >= 0x030000 + bool sel = isSelected(); +#else + bool sel = selected(); +#endif + + + if (KOPrefs::instance()->mMonthViewUsesCategoryColor) + { + p->setBackgroundColor( palette().color( QPalette::Normal, \ + sel ? QColorGroup::Highlight : QColorGroup::Background ) ); + p->eraseRect( 0, 0, listBox()->maxItemWidth(), height( listBox() ) ); + } + int x = 1; + int y = 3;//(height() - mRecurPixmap.height()) /2; + int size = PIXMAP_SIZE; + if ( QApplication::desktop()->width() < 300 ) + size = 3; + if ( KOPrefs::instance()->mMonthShowIcons ) { + if ( mInfo ) { + p->fillRect ( x, y,size,size, Qt::darkGreen ); + x += size + 1; + } + if ( mRecur ) { + p->fillRect ( x, y,size,size, Qt::blue ); + x += size + 1; + } + if ( mAlarm ) { + p->fillRect ( x, y,size,size, Qt::red ); + x += size + 1; + } + if ( mReply ) { + p->fillRect ( x, y,size,size, Qt::yellow ); + x += size + 1; + } + } + QFontMetrics fm = p->fontMetrics(); + int yPos; + int pmheight = size; + if( pmheight < fm.height() ) + yPos = fm.ascent() + fm.leading()/2; + else + yPos = pmheight/2 - fm.height()/2 + fm.ascent(); + p->setPen( palette().color( QPalette::Normal, sel ? \ + QColorGroup::HighlightedText : QColorGroup::Foreground ) ); + p->drawText( x, yPos, text() ); + if ( mIncidence->cancelled() ) { + int wid = fm.width( text() ); + p->drawLine( x, yPos- fm.height()/2+2,x+wid, yPos- fm.height()/2 +2); + } + +} + +int MonthViewItem::height(const QListBox *lb) const +{ + return lb->fontMetrics().lineSpacing()+1; +} + +int MonthViewItem::width(const QListBox *lb) const +{ + int size = PIXMAP_SIZE; + if ( QApplication::desktop()->width() < 300 ) + size = 3; + int x = 1; + if ( mInfo ) { + x += size + 1; + } + if( mRecur ) { + x += size+1; + } + if( mAlarm ) { + x += size+1; + } + if( mReply ) { + x += size+1; + } + + return( x + lb->fontMetrics().width( text() ) + 1 ); +} + + +MonthViewCell::MonthViewCell( KOMonthView *parent) + : QWidget( parent ), + mMonthView( parent ) +{ + + QVBoxLayout *topLayout = new QVBoxLayout( this ); + + // mLabel = new QLabel( this );QPushButton + mLabel = new QPushButton( this ); + //mLabel->setFrameStyle( QFrame::Panel | QFrame::Plain ); + //mLabel->setLineWidth( 1 ); + //mLabel->setAlignment( AlignCenter ); + mLabel->setFlat( true ); + mItemList = new KNoScrollListBox( this ); + mItemList->setMinimumSize( 10, 10 ); + mItemList->setFrameStyle( QFrame::Panel | QFrame::Plain ); + mItemList->setLineWidth( 1 ); + topLayout->addWidget( mItemList ); + mLabel->raise(); + // QColor( 0,0,255 ) QColor( 160,1600,255 ) + mStandardPalette = palette(); + mStandardPalette.setColor(QColorGroup::Base, mStandardPalette.color( QPalette::Normal, QColorGroup::Background ) ); + + enableScrollBars( false ); + updateConfig(); + connect( mLabel, SIGNAL( clicked( )), + SLOT( newEvent() )); + connect( mItemList, SIGNAL( doubleClicked( QListBoxItem *) ), + SLOT( defaultAction( QListBoxItem * ) ) ); + connect( mItemList, SIGNAL( rightButtonPressed( QListBoxItem *, + const QPoint &) ), + SLOT( contextMenu( QListBoxItem * ) ) ); + connect( mItemList, SIGNAL( highlighted( QListBoxItem *) ), + SLOT( selection( QListBoxItem * ) ) ); + connect( mItemList, SIGNAL( clicked( QListBoxItem * ) ), + SLOT( cellClicked( QListBoxItem * ) ) ); + connect( mItemList, SIGNAL( clicked( QListBoxItem * ) ), + SLOT( selection( QListBoxItem * ) ) ); +} + +void MonthViewCell::setDate( const QDate &date ) +{ +// kdDebug() << "MonthViewCell::setDate(): " << date.toString() << endl; + + mDate = date; + + QString text; + bool smallDisplay = QApplication::desktop()->width() < 320 && KOPrefs::instance()->mMonthViewSatSunTog; + if ( KOGlobals::self()->calendarSystem()->day( date ) == 1 || (date.dayOfWeek() == 7 && !smallDisplay ) || KOPrefs::instance()->mMonthShowShort) { + text = KOGlobals::self()->calendarSystem()->monthName( date, true ) + " "; + mLabel->resize( mLabelBigSize ); + text += QString::number( KOGlobals::self()->calendarSystem()->day(mDate) ); + } else { + mLabel->resize( mLabelSize ); + text += QString::number( KOGlobals::self()->calendarSystem()->day(mDate) ); + } + mLabel->setText( text ); + + //resizeEvent( 0 ); +} + +QDate MonthViewCell::date() const +{ + return mDate; +} + +void MonthViewCell::setPrimary( bool primary ) +{ + mPrimary = primary; + //setMyPalette(); +} +void MonthViewCell::setMyPalette() +{ + + if ( mHoliday) { + setPalette( mHolidayPalette ); + } else { + if ( mPrimary ) { + setPalette( mPrimaryPalette ); + } else { + setPalette( mNonPrimaryPalette ); + } + } + QPalette pal = palette(); + + mLabel->setPalette( QPalette ( pal.color( QPalette::Normal,QColorGroup::Base),pal.color(QPalette::Normal,QColorGroup::Base ) )); +} +QPalette MonthViewCell::getPalette () +{ + if ( !KOPrefs::instance()->mMonthViewUsesDayColors ) + return mStandardPalette; + if ( mHoliday) { + return mHolidayPalette ; + } else { + if ( mPrimary ) { + return mPrimaryPalette ; + } + } + return mNonPrimaryPalette; +} +bool MonthViewCell::isPrimary() const +{ + return mPrimary; +} + +void MonthViewCell::setHoliday( bool holiday ) +{ + mHoliday = holiday; + //setMyPalette(); +} + +void MonthViewCell::setHoliday( const QString &holiday ) +{ + mHolidayString = holiday; + + if ( !holiday.isEmpty() ) { + setHoliday( true ); + } +} +void MonthViewCell::keyPressEvent ( QKeyEvent * e ) +{ + + e->ignore(); + +} +void MonthViewCell::updateCell() +{ + + setPrimary( mDate.month()%2 ); + setHoliday( KOGlobals::self()->calendarSystem()->dayOfWeek(mDate) == KOGlobals::self()->calendarSystem()->weekDayOfPray() ); + if ( mDate == QDate::currentDate() ) { + mItemList->setLineWidth( 3 ); + } else { + mItemList->setLineWidth( 1 ); + } + mItemList->clear(); + //qApp->processEvents(); + if ( !mHolidayString.isEmpty() ) { + MonthViewItem *item = new MonthViewItem( 0, mDate, mHolidayString ); + item->setPalette( mHolidayPalette ); + mItemList->insertItem( item ); + } + //mLabel->setMaximumWidth( width() - mItemList->lineWidth()*2); + QPtrList<Event> events = mMonthView->calendar()->events( mDate, true ); + Event *event; + for( event = events.first(); event; event = events.next() ) { + if ( event->categories().contains("Holiday") || + event->categories().contains(i18n("Holiday"))) { + setHoliday( true ); + if ( mDate.dayOfWeek() == 7 ) + mItemList->setLineWidth( 3 ); + } + QString text; + if (event->isMultiDay()) { + QString prefix = "<->"; + if ( event->doesRecur() ) { + if ( event->recursOn( mDate) ) + prefix ="->" ; + else { + int days = event->dtStart().date().daysTo ( event->dtEnd().date() ); + if ( event->recursOn( mDate.addDays( -days)) ) + prefix ="<-" ; + } + + } else { + if (mDate == event->dtStart().date()) { + prefix ="->" ; + } else if (mDate == event->dtEnd().date()) { + prefix ="<-" ; + } + } + text = prefix + event->summary(); + } else { + if (event->doesFloat()) + text = event->summary(); + else { + text = KGlobal::locale()->formatTime(event->dtStart().time()); + text += " " + event->summary(); + } + } + + MonthViewItem *item = new MonthViewItem( event, mDate, text ); + QPalette pal; + if (KOPrefs::instance()->mMonthViewUsesCategoryColor) { + QStringList categories = event->categories(); + QString cat = categories.first(); + if ( KOPrefs::instance()->mMonthViewUsesForegroundColor ) { + pal = getPalette(); + if (cat.isEmpty()) { + pal.setColor(QColorGroup::Foreground,KOPrefs::instance()->mEventColor); + } else { + pal.setColor(QColorGroup::Foreground, *(KOPrefs::instance()->categoryColor(cat))); + } + + } else { + if (cat.isEmpty()) { + pal = QPalette(KOPrefs::instance()->mEventColor, KOPrefs::instance()->mEventColor); + } else { + pal = QPalette(*(KOPrefs::instance()->categoryColor(cat)), *(KOPrefs::instance()->categoryColor(cat))); + } + } + + } else { + pal = mStandardPalette ; + } + item->setPalette( pal ); + item->setRecur( event->recurrence()->doesRecur() ); + item->setAlarm( event->isAlarmEnabled() ); + item->setMoreInfo( event->description().length() > 0 ); + Attendee *me = event->attendeeByMails(KOPrefs::instance()->mAdditionalMails, + KOPrefs::instance()->email()); + if ( me != 0 ) { + if ( me->status() == Attendee::NeedsAction && me->RSVP()) + item->setReply(true); + else + item->setReply(false); + } else + item->setReply(false); + bool insert = true; + if ( !(event->doesRecur() == Recurrence::rNone) ) { + if ( !KOPrefs::instance()->mMonthDailyRecur && event->doesRecur() == Recurrence::rDaily ) + insert = false; + else + if ( !KOPrefs::instance()->mMonthWeeklyRecur && event->doesRecur() == Recurrence::rWeekly ) + insert = false; + + } + if ( insert ) + mItemList->insertItem( item ); + } + + // insert due todos + QPtrList<Todo> todos = mMonthView->calendar()->todos( mDate ); + Todo *todo; + for(todo = todos.first(); todo; todo = todos.next()) { + QString text; + if (todo->hasDueDate()) { + if (!todo->doesFloat()) { + text += KGlobal::locale()->formatTime(todo->dtDue().time()); + text += " "; + } + } + text += i18n("To-Do: %1").arg(todo->summary()); + + MonthViewItem *item = new MonthViewItem( todo, mDate, text ); + //item->setPalette( mStandardPalette ); + QPalette pal; + if (KOPrefs::instance()->mMonthViewUsesCategoryColor) { + QStringList categories = todo->categories(); + QString cat = categories.first(); + if ( KOPrefs::instance()->mMonthViewUsesForegroundColor ) { + pal = getPalette(); + if (cat.isEmpty()) { + pal.setColor(QColorGroup::Foreground,KOPrefs::instance()->mEventColor); + } else { + pal.setColor(QColorGroup::Foreground, *(KOPrefs::instance()->categoryColor(cat))); + } + + } else { + if (cat.isEmpty()) { + pal = QPalette(KOPrefs::instance()->mEventColor, KOPrefs::instance()->mEventColor); + } else { + pal = QPalette(*(KOPrefs::instance()->categoryColor(cat)), *(KOPrefs::instance()->categoryColor(cat))); + } + } + + } else { + pal = mStandardPalette ; + } + item->setPalette( pal ); + mItemList->insertItem( item ); + } + //setMyPalette(); + setMyPalette(); + resizeEvent( 0 ); + // if ( isVisible()) + // qApp->processEvents(); +} + +void MonthViewCell::updateConfig() +{ + + setFont( KOPrefs::instance()->mMonthViewFont ); + + QFontMetrics fm( font() ); + mLabelSize = fm.size( 0, "30" ) + QSize( 4, 2 ); + mLabelBigSize = fm.size( 0, "Mag 30" ) + QSize( 2, 2 ); + mHolidayPalette = mStandardPalette; + mPrimaryPalette = mStandardPalette; + mNonPrimaryPalette = mStandardPalette; + if ( KOPrefs::instance()->mMonthViewUsesDayColors ) { + mHolidayPalette.setColor(QColorGroup::Base, KOPrefs::instance()->mMonthViewHolidayColor ); + mHolidayPalette.setColor(QColorGroup::Background, KOPrefs::instance()->mMonthViewHolidayColor ); + mHolidayPalette.setColor(QColorGroup::Foreground, KOPrefs::instance()->mMonthViewHolidayColor.dark()); + mPrimaryPalette.setColor(QColorGroup::Foreground,KOPrefs::instance()->mMonthViewOddColor.dark()); + mPrimaryPalette.setColor(QColorGroup::Base,KOPrefs::instance()->mMonthViewOddColor); + mPrimaryPalette.setColor(QColorGroup::Background,KOPrefs::instance()->mMonthViewOddColor); + mNonPrimaryPalette.setColor(QColorGroup::Foreground,KOPrefs::instance()->mMonthViewEvenColor.dark()); + mNonPrimaryPalette.setColor(QColorGroup::Base,KOPrefs::instance()->mMonthViewEvenColor); + mNonPrimaryPalette.setColor(QColorGroup::Background,KOPrefs::instance()->mMonthViewEvenColor); + } + updateCell(); +} + +void MonthViewCell::enableScrollBars( bool enabled ) +{ + if ( enabled ) { + mItemList->setVScrollBarMode(QScrollView::Auto); + mItemList->setHScrollBarMode(QScrollView::Auto); + } else { + mItemList->setVScrollBarMode(QScrollView::AlwaysOff); + mItemList->setHScrollBarMode(QScrollView::AlwaysOff); + } +} + +Incidence *MonthViewCell::selectedIncidence() +{ + int index = mItemList->currentItem(); + if ( index < 0 ) return 0; + + MonthViewItem *item = + static_cast<MonthViewItem *>( mItemList->item( index ) ); + + if ( !item ) return 0; + + return item->incidence(); +} + +QDate MonthViewCell::selectedIncidenceDate() +{ + QDate qd; + int index = mItemList->currentItem(); + if ( index < 0 ) return qd; + + MonthViewItem *item = + static_cast<MonthViewItem *>( mItemList->item( index ) ); + + if ( !item ) return qd; + + return item->incidenceDate(); +} + +void MonthViewCell::deselect() +{ + mItemList->clearSelection(); + enableScrollBars( false ); + // updateCell(); +} +void MonthViewCell::select() +{ + ;// updateCell(); +} + +void MonthViewCell::resizeEvent ( QResizeEvent * ) +{ + int size = height() - mLabel->height(); + if ( size > 0 ) + mItemList->verticalScrollBar()->setMaximumHeight( size ); + size = width() - mLabel->width(); + if ( size > 0 ) + mItemList->horizontalScrollBar()->setMaximumWidth( size ); + mLabel->move( width()-mItemList->lineWidth() - mLabel->width(), height()-mItemList->lineWidth() - mLabel->height() ); + //mLabel->setMaximumWidth( width() - mItemList->lineWidth()*2); +} + +void MonthViewCell::defaultAction( QListBoxItem *item ) +{ + if ( !item ) return; + + MonthViewItem *eventItem = static_cast<MonthViewItem *>( item ); + Incidence *incidence = eventItem->incidence(); + if ( incidence ) mMonthView->defaultAction( incidence ); +} +void MonthViewCell::newEvent() +{ + QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) ); + emit newEventSignal( dt ); +} +void MonthViewCell::cellClicked( QListBoxItem *item ) +{ + static QListBoxItem * lastClicked = 0; + if ( item == 0 ) { + QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) ); + emit newEventSignal( dt ); + return; + } + /* + if ( lastClicked ) + if ( ! item ) { + if ( lastClicked->listBox() != item->listBox() ) + lastClicked->listBox()->clearSelection(); + } + */ + + mMonthView->setSelectedCell( this ); + if( KOPrefs::instance()->mEnableMonthScroll ) enableScrollBars( true ); + select(); +} + +void MonthViewCell::contextMenu( QListBoxItem *item ) +{ + if ( !item ) return; + + MonthViewItem *eventItem = static_cast<MonthViewItem *>( item ); + Incidence *incidence = eventItem->incidence(); + if ( incidence ) mMonthView->showContextMenu( incidence ); +} + +void MonthViewCell::selection( QListBoxItem *item ) +{ + if ( !item ) return; + + mMonthView->setSelectedCell( this ); +} + + +// ******************************************************************************* +// ******************************************************************************* +// ******************************************************************************* + + +KOMonthView::KOMonthView(Calendar *calendar, QWidget *parent, const char *name) + : KOEventView( calendar, parent, name ), + mDaysPerWeek( 7 ), mNumWeeks( 6 ), mNumCells( mDaysPerWeek * mNumWeeks ), + mShortDayLabels( false ), mWidthLongDayLabel( 0 ), mSelectedCell( 0 ) +{ + mCells.setAutoDelete( true ); + mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ; + // mDayLayout = new QGridLayout( this ); + // create the day of the week labels (Sun, Mon, etc) and add them to + // the layout. + mDayLabels.resize( mDaysPerWeek ); + QFont bfont = font(); + if ( QApplication::desktop()->width() < 650 ) { + bfont.setPointSize( bfont.pointSize() - 2 ); + } + bfont.setBold( true ); + int i; + + for( i = 0; i < mDaysPerWeek; i++ ) { + QLabel *label = new QLabel( this ); + label->setFont(bfont); + label->setFrameStyle(QFrame::Panel|QFrame::Raised); + label->setLineWidth(1); + label->setAlignment(AlignCenter); + mDayLabels.insert( i, label ); + } + + bfont.setBold( false ); + mWeekLabels.resize( mNumWeeks+1 ); + for( i = 0; i < mNumWeeks+1; i++ ) { + KOWeekButton *label = new KOWeekButton( this ); + label->setFont(bfont); + connect( label, SIGNAL( selectWeekNum ( int )),this, SIGNAL( selectWeekNum ( int )) ); + label->setFlat(true); + QWhatsThis::add(label,i18n("Click on the week number to\nshow week in agenda view")); + //label->setFrameStyle(QFrame::Panel|QFrame::Raised); + //label->setLineWidth(1); + //label->setAlignment(AlignCenter); + mWeekLabels.insert( i, label ); + } + mWeekLabels[mNumWeeks]->setText( i18n("W")); + int row, col; + mCells.resize( mNumCells ); + for( row = 0; row < mNumWeeks; ++row ) { + for( col = 0; col < mDaysPerWeek; ++col ) { + MonthViewCell *cell = new MonthViewCell( this ); + mCells.insert( row * mDaysPerWeek + col, cell ); + + connect( cell, SIGNAL( defaultAction( Incidence * ) ), + SLOT( defaultAction( Incidence * ) ) ); + connect( cell, SIGNAL( newEventSignal( QDateTime ) ), + SIGNAL( newEventSignal( QDateTime ) ) ); + } + } + + mContextMenu = eventPopup(); + // updateConfig(); //useless here + + emit incidenceSelected( 0 ); +} + +KOMonthView::~KOMonthView() +{ + delete mContextMenu; +} + +int KOMonthView::maxDatesHint() +{ + return mNumCells; +} + +int KOMonthView::currentDateCount() +{ + return mNumCells; +} + +QPtrList<Incidence> KOMonthView::selectedIncidences() +{ + QPtrList<Incidence> selected; + + if ( mSelectedCell ) { + Incidence *incidence = mSelectedCell->selectedIncidence(); + if ( incidence ) selected.append( incidence ); + } + + return selected; +} + +DateList KOMonthView::selectedDates() +{ + DateList selected; + + if ( mSelectedCell ) { + QDate qd = mSelectedCell->selectedIncidenceDate(); + if ( qd.isValid() ) selected.append( qd ); + } + + return selected; +} + +void KOMonthView::printPreview(CalPrinter *calPrinter, const QDate &fd, + const QDate &td) +{ +#ifndef KORG_NOPRINTER + calPrinter->preview(CalPrinter::Month, fd, td); +#endif +} + +void KOMonthView::updateConfig() +{ + + mWeekStartsMonday = KGlobal::locale()->weekStartsMonday(); + + QFontMetrics fontmetric(mDayLabels[0]->font()); + mWidthLongDayLabel = 0; + + for (int i = 0; i < 7; i++) { + int width = fontmetric.width(KOGlobals::self()->calendarSystem()->weekDayName(i+1)); + if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width; + } + bool temp = mShowSatSunComp ; + mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ; + if ( temp != KOPrefs::instance()->mMonthViewSatSunTog ) + computeLayout(); + updateDayLabels(); + //qDebug("KOMonthView::updateConfig() %d %d %d ",height(), mDayLabels[0]->sizeHint().height() ,mNumWeeks); + int cellHeight = (height() - mDayLabels[0]->sizeHint().height()) /mNumWeeks; + //resizeEvent( 0 ); + for (uint i = 0; i < mCells.count(); ++i) { + mCells[i]->updateConfig(); + } +} + +void KOMonthView::updateDayLabels() +{ + + for (int i = 0; i < 7; i++) { + if (mWeekStartsMonday) { + bool show = mShortDayLabels; + if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > mDayLabels[i]->width() ) + show = true; + mDayLabels[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show)); + } else { + if (i==0) mDayLabels[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(7,mShortDayLabels)); + else mDayLabels[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i,mShortDayLabels)); + + } + } +} + +void KOMonthView::showDates(const QDate &start, const QDate &) +{ +// kdDebug() << "KOMonthView::showDates(): " << start.toString() << endl; + + + mStartDate = start; + + int startWeekDay = mWeekStartsMonday ? 1 : 7; + + while( KOGlobals::self()->calendarSystem()->dayOfWeek(mStartDate) != startWeekDay ) { + mStartDate = mStartDate.addDays( -1 ); + } + + bool primary = false; + uint i; + for( i = 0; i < mCells.size(); ++i ) { + QDate date = mStartDate.addDays( i ); + mCells[i]->setDate( date ); + +#ifndef KORG_NOPLUGINS + // add holiday, if present + QString hstring(KOCore::self()->holiday(date)); + mCells[i]->setHoliday( hstring ); +#endif + + } + QDate date = mStartDate.addDays( mWeekStartsMonday ? 3 : 4 ); + for( i = 0; i < 6; ++i ) { + int wno; + // remember, according to ISO 8601, the first week of the year is the + // first week that contains a thursday. Thus we must subtract off 4, + // not just 1. + int dayOfYear = date.dayOfYear(); + if (dayOfYear % 7 != 0) + wno = dayOfYear / 7 + 1; + else + wno =dayOfYear / 7; + mWeekLabels[i]->setWeekNum( wno ); + date = date.addDays( 7 ); + } + updateView(); +} + +void KOMonthView::showEvents(QPtrList<Event>) +{ + qDebug("KOMonthView::selectEvents is not implemented yet. "); +} + +void KOMonthView::changeEventDisplay(Event *, int) +{ + // this should be re-written to be much more efficient, but this + // quick-and-dirty-hack gets the job done for right now. + updateView(); +} + +void KOMonthView::updateView() +{ + + uint i; + for( i = 0; i < mCells.count(); ++i ) { + mCells[i]->updateCell(); + } + //qDebug("KOMonthView::updateView() "); + processSelectionChange(); +} + +void KOMonthView::resizeEvent(QResizeEvent * e) +{ + computeLayout(); +} +void KOMonthView::computeLayout() +{ + // select the appropriate heading string size. E.g. "Wednesday" or "Wed". + // note this only changes the text if the requested size crosses the + // threshold between big enough to support the full name and not big + // enough. + + int daysToShow = 7; + bool combinedSatSun = false; + if (mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ) { + daysToShow = 6; + combinedSatSun = true; + } + int tWid = topLevelWidget()->size().width(); + int tHei = topLevelWidget()->size().height(); + + int wid = size().width();//e + int hei = size().height()-1; + + if ( ((wid *3)/2) < tWid && (( hei *3) /2) < tHei ) + return; + + QFontMetrics fm ( mWeekLabels[0]->font() ); + int weeklabelwid = fm.width( "888" ); + wid -= weeklabelwid; + + int colWid = wid / daysToShow; + int lastCol = wid - ( colWid*6 ); + int dayLabelHei = mDayLabels[0]->sizeHint().height(); + int cellHei = (hei - dayLabelHei) /6; + int colModulo = wid % daysToShow; + int rowModulo = (hei- dayLabelHei) % 6; + //qDebug("rowmod %d ", rowModulo); + int i; + int x,y,w,h; + x= 0; + y= 0; + w = colWid; + h = dayLabelHei ; + for ( i = 0; i < 7; i++) { + if ( i == daysToShow-colModulo ) + ++w; + if ( combinedSatSun ) { + if ( i >= daysToShow-1 ) { + mDayLabels[i]->setGeometry( x+weeklabelwid,y,w/2,h); + x -= w/2 ; + } + else + mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h); + } else + mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h); + x += w; + } + x= 0; + y= dayLabelHei; + w = colWid; + h = cellHei ; + for ( i = 0; i < mCells.count(); ++i) { + + w = colWid; + if ( ((i) % 7) >= 7-colModulo ) { + ++w; + } + if ( i == (6-rowModulo)*7) + ++h; + if ( combinedSatSun ) { + if ( (i)%7 >= daysToShow-1 ) { + if ( (i)%7 == daysToShow-1 ) { + mCells[i]->setGeometry ( x+weeklabelwid,y,w,h/2 ); + x -= w ;y += h/2; + } else { + mCells[i]->setGeometry ( x+weeklabelwid,y,w,h-h/2 ); + y -= h/2; + } + } else + mCells[i]->setGeometry ( x+weeklabelwid,y,w,h ); + + } + else + mCells[i]->setGeometry ( x+weeklabelwid,y,w,h ); + x += w; + if ( x + w/2 > wid ) { + x = 0; + y += h; + } + } + y= dayLabelHei; + h = cellHei ; + for ( i = 0; i < 6; i++) { + if ( i == (6-rowModulo)) + ++h; + mWeekLabels[i]->setGeometry( 0,y,weeklabelwid,h); + y += h; + } + mWeekLabels[6]->setGeometry( 0,0,weeklabelwid,dayLabelHei); + // qDebug("RRRRRRRRRRRRR %d %d old %d %d", e->size().width(),e->size().height() , e->oldSize().width(),e->oldSize().height()); + //qDebug("parent %d %d ", topLevelWidget()->size().width(), topLevelWidget()->size().height()); + mShortDayLabels = mDayLabels[0]->width() < mWidthLongDayLabel ; + updateDayLabels(); +} + +void KOMonthView::showContextMenu( Incidence *incidence ) +{ + mContextMenu->showIncidencePopup(incidence); + /* + if( incidence && incidence->type() == "Event" ) { + Event *event = static_cast<Event *>(incidence); + mContextMenu->showEventPopup(event); + } else { + kdDebug() << "MonthView::showContextMenu(): cast failed." << endl; + } + */ +} +MonthViewCell * KOMonthView::selectedCell( ) +{ + return mSelectedCell; +} +void KOMonthView::setSelectedCell( MonthViewCell *cell ) +{ + // qDebug("KOMonthView::setSelectedCell "); + if ( mSelectedCell && mSelectedCell != cell ) { + MonthViewCell * mvc = mSelectedCell; + mSelectedCell = cell; + mvc->deselect(); + } else + mSelectedCell = cell; + // if ( mSelectedCell ) +// mSelectedCell->select(); + if ( !mSelectedCell ) + emit incidenceSelected( 0 ); + else + emit incidenceSelected( mSelectedCell->selectedIncidence() ); +} + +void KOMonthView::processSelectionChange() +{ + QPtrList<Incidence> incidences = selectedIncidences(); + if (incidences.count() > 0) { + emit incidenceSelected( incidences.first() ); + } else { + emit incidenceSelected( 0 ); + } +} + +void KOMonthView::clearSelection() +{ + if ( mSelectedCell ) { + mSelectedCell->deselect(); + mSelectedCell = 0; + } +} +void KOMonthView::keyPressEvent ( QKeyEvent * e ) +{ + + e->ignore(); + +} diff --git a/korganizer/komonthview.h b/korganizer/komonthview.h new file mode 100644 index 0000000..d976246 --- a/dev/null +++ b/korganizer/komonthview.h @@ -0,0 +1,252 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _KOMONTHVIEW_H +#define _KOMONTHVIEW_H + +#include <qlabel.h> +#include <qframe.h> +#include <qdatetime.h> +#include <qlistbox.h> +#include <qpoint.h> +#include <qlayout.h> +#include <qintdict.h> +#include <qpushbutton.h> +#include <qvaluelist.h> +#include <qptrvector.h> + +#include <libkcal/calendar.h> +#include <libkcal/event.h> + +#include "koeventview.h" + +class KOWeekButton : public QPushButton +{ + Q_OBJECT + public: + KOWeekButton( QWidget *parent=0, const char *name=0 ) : + QPushButton( parent, name) + { + connect( this, SIGNAL( clicked() ), + SLOT( bottonClicked() )); + mNumber = -1; + } + void setWeekNum ( int num ) {mNumber = num; setText( QString::number ( num ));} + signals: + void selectWeekNum ( int ); +private: + int mNumber; +private slots : + void bottonClicked() { if ( mNumber > 0 ) emit selectWeekNum ( mNumber ); } +}; + +class KNoScrollListBox: public QListBox +{ + Q_OBJECT + public: + KNoScrollListBox(QWidget *parent=0, const char *name=0); + ~KNoScrollListBox() {} + QString getWhatsThisText(QPoint p) ; + + signals: + void shiftDown(); + void shiftUp(); + void rightClick(); + + protected slots: + void keyPressEvent(QKeyEvent *); + void keyReleaseEvent(QKeyEvent *); + void mousePressEvent(QMouseEvent *); +}; + + +class MonthViewItem: public QListBoxItem +{ + public: + MonthViewItem( Incidence *, QDate qd, const QString & title ); + + void setRecur(bool on) { mRecur = on; } + void setAlarm(bool on) { mAlarm = on; } + void setReply(bool on) { mReply = on; } + void setMoreInfo(bool on) { mInfo = on; } + + + void setPalette(const QPalette &p) { mPalette = p; } + QPalette palette() const { return mPalette; } + + Incidence *incidence() const { return mIncidence; } + QDate incidenceDate() { return mDate; } + + protected: + virtual void paint(QPainter *); + virtual int height(const QListBox *) const; + virtual int width(const QListBox *) const; + + private: + bool mRecur; + bool mAlarm; + bool mReply; + bool mInfo; + + QPalette mPalette; + QDate mDate; + + Incidence *mIncidence; +}; + + +class KOMonthView; + +class MonthViewCell : public QWidget +{ + Q_OBJECT + public: + MonthViewCell( KOMonthView * ); + + void setDate( const QDate & ); + QDate date() const; + + void setPrimary( bool ); + bool isPrimary() const; + + void setHoliday( bool ); + void setHoliday( const QString & ); + + void updateCell(); + + void updateConfig(); + + void enableScrollBars( bool ); + + Incidence *selectedIncidence(); + QDate selectedIncidenceDate(); + + void deselect(); + void select(); + + signals: + void defaultAction( Incidence * ); + void newEventSignal( QDateTime ); + + protected: + void resizeEvent( QResizeEvent * ); + + protected slots: + void defaultAction( QListBoxItem * ); + void contextMenu( QListBoxItem * ); + void selection( QListBoxItem * ); + void cellClicked( QListBoxItem * ); + void newEvent(); + + private: + KOMonthView *mMonthView; + + QDate mDate; + bool mPrimary; + bool mHoliday; + QString mHolidayString; + + //QLabel *mLabel; + QPushButton *mLabel; + QListBox *mItemList; + + QSize mLabelSize; + QSize mLabelBigSize; + QPalette mHolidayPalette; + QPalette mStandardPalette; + QPalette mPrimaryPalette; + QPalette mNonPrimaryPalette; + void setMyPalette(); + QPalette getPalette (); + void keyPressEvent ( QKeyEvent * ) ; + +}; + + +class KOMonthView: public KOEventView +{ + Q_OBJECT + public: + KOMonthView(Calendar *cal, QWidget *parent = 0, const char *name = 0 ); + ~KOMonthView(); + + /** Returns maximum number of days supported by the komonthview */ + virtual int maxDatesHint(); + + /** Returns number of currently shown dates. */ + virtual int currentDateCount(); + + /** returns the currently selected events */ + virtual QPtrList<Incidence> selectedIncidences(); + + /** returns dates of the currently selected events */ + virtual DateList selectedDates(); + + virtual void printPreview(CalPrinter *calPrinter, + const QDate &, const QDate &); + + MonthViewCell * selectedCell(); + public slots: + virtual void updateView(); + virtual void updateConfig(); + virtual void showDates(const QDate &start, const QDate &end); + virtual void showEvents(QPtrList<Event> eventList); + + void changeEventDisplay(Event *, int); + + void clearSelection(); + + void showContextMenu( Incidence * ); + + void setSelectedCell( MonthViewCell * ); + + protected slots: + void processSelectionChange(); + signals: + void selectWeekNum ( int ); + protected: + void resizeEvent(QResizeEvent *); + void viewChanged(); + void updateDayLabels(); + + private: + int mDaysPerWeek; + int mNumWeeks; + int mNumCells; + bool mWeekStartsMonday; + bool mShowSatSunComp; + void computeLayout(); + + QPtrVector<MonthViewCell> mCells; + QPtrVector<QLabel> mDayLabels; + QPtrVector<KOWeekButton> mWeekLabels; + + bool mShortDayLabels; + int mWidthLongDayLabel; + + QDate mStartDate; + + MonthViewCell *mSelectedCell; + + KOEventPopupMenu *mContextMenu; + void keyPressEvent ( QKeyEvent * ) ; + +}; + +#endif diff --git a/korganizer/komonthview.moc b/korganizer/komonthview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/komonthview.moc diff --git a/korganizer/koprefs.cpp b/korganizer/koprefs.cpp new file mode 100644 index 0000000..2900a40 --- a/dev/null +++ b/korganizer/koprefs.cpp @@ -0,0 +1,555 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <time.h> +#ifndef _WIN32_ +#include <unistd.h> +#endif +#include <qdir.h> +#include <qtextstream.h> +#include <qtextcodec.h> +#include <qstring.h> +#include <qfont.h> +#include <qcolor.h> +#include <qstringlist.h> +#include <stdlib.h> + +#include <kglobal.h> +#include <kconfig.h> +#include <klocale.h> +#include <kdebug.h> +#include <kemailsettings.h> +#include <kstaticdeleter.h> + +#include "koprefs.h" +#include "mainwindow.h" + +const char *germanwords[][2] = { +#include "wordsgerman.h" + "", "" +}; + +KOPrefs *KOPrefs::mInstance = 0; +static KStaticDeleter<KOPrefs> insd; + +KOPrefs::KOPrefs() : + KPimPrefs("korganizerrc") +{ + mCategoryColors.setAutoDelete(true); + mLocaleDict = 0; + fillMailDefaults(); + mDefaultCategoryColor = QColor(175,210,255);//196,196,196); + QColor defaultHolidayColor = QColor(255,0,0); + QColor defaultHighlightColor = QColor(129,112,255);//64,64,255); + QColor defaultAgendaBgColor = QColor(239,241,169);//128,128,128); + QColor defaultWorkingHoursColor = QColor(170,223,150);//160,160,160); + QColor defaultTodoDueTodayColor = QColor(255,220,100); + QColor defaultTodoOverdueColor = QColor(255,153,125); + + mTimeBarFont = QFont("helvetica",10);//,QFont::Bold); + mDefaultViewFont = QFont("helvetica",10); + mDefaultMonthViewFont = QFont("helvetica",8); + mMarcusBainsFont= QFont("helvetica",10); + mDateNavigatorFont= QFont("helvetica",10, QFont::Bold); + mEditBoxFont = QFont("helvetica",12); + mJornalViewFont = QFont("helvetica",12); + + KPrefs::setCurrentGroup("General"); + addItemBool("Enable Group Scheduling",&mEnableGroupScheduling,false); + + addItemBool("ShowIconNewTodo",&mShowIconNewTodo,true); + addItemBool("ShowIconNewEvent",&mShowIconNewEvent,true); + addItemBool("ShowIconSearch",&mShowIconSearch,true); + addItemBool("ShowIconList",&mShowIconList,true); + addItemBool("ShowIconDay1",&mShowIconDay1,true); + addItemBool("ShowIconDay5",&mShowIconDay5,true); + addItemBool("ShowIconDay7",&mShowIconDay7,true); + addItemBool("ShowIconMonth",&mShowIconMonth,true); + addItemBool("ShowIconTodoview",&mShowIconTodoview,true); + addItemBool("ShowIconBackFast",&mShowIconBackFast,true); + addItemBool("ShowIconBack",&mShowIconBack,true); + addItemBool("ShowIconToday",&mShowIconToday,true); + addItemBool("ShowIconForward",&mShowIconForward,true); + addItemBool("ShowIconForwardFast",&mShowIconForwardFast,true); + addItemBool("ShowIconWhatsThis",&mShowIconWhatsThis,false); + addItemBool("ShowIconNextDays",&mShowIconNextDays,true); + addItemBool("ShowIconNext",&mShowIconNext,true); + addItemBool("ShowIconJournal",&mShowIconJournal,true); + addItemBool("ShowIconStretch",&mShowIconStretch,true); + addItemBool("LanguageChanged",&mLanguageChanged,false); + + addItemBool("AskForQuit",&mAskForQuit,false); + +#ifndef DESKTOP_VERSION + addItemBool("ShowFullMenu",&mShowFullMenu,false); +#else + addItemBool("ShowFullMenu",&mShowFullMenu,true); +#endif + addItemBool("ToolBarHor",&mToolBarHor, true ); + addItemBool("ToolBarUp",&mToolBarUp, false ); + addItemBool("ToolBarMiniIcons",&mToolBarMiniIcons, false ); + addItemInt("Whats Next Days",&mWhatsNextDays,3); + addItemInt("Whats Next Prios",&mWhatsNextPrios,1); + + addItemBool("ShowTodoInAgenda",&mShowTodoInAgenda,true); + addItemBool("ShowCompletedTodo",&mShowCompletedTodo,true); + addItemInt("AllDay Size",&mAllDaySize,28); + QString defAlarm = KGlobal::iconLoader()->iconPath()+"koalarm.wav"; + addItemString("DefaultAlarmFile",&mDefaultAlarmFile,defAlarm ); + + addItemStringList("LocationDefaults",&mLocationDefaults ); + addItemStringList("EventSummary User",&mEventSummaryUser); + addItemStringList("TodoSummary User",&mTodoSummaryUser); + + addItemBool("Enable Group Scheduling",&mEnableGroupScheduling,false); + addItemBool("Enable Project View",&mEnableProjectView,false); + addItemBool("Auto Save",&mAutoSave,false); + addItemInt("Auto Save Interval",&mAutoSaveInterval,3); + addItemBool("Confirm Deletes",&mConfirm,true); + addItemString("Archive File",&mArchiveFile); + addItemString("Html Export File",&mHtmlExportFile, + QDir::homeDirPath() + "/" + i18n("Default export file", "calendar.html")); + addItemBool("Html With Save",&mHtmlWithSave,false); + + KPrefs::setCurrentGroup("Personal Settings"); + + addItemInt("Mail Client",&mMailClient,MailClientKMail); + addItemBool("Use Control Center Email",&mEmailControlCenter,false); + addItemBool("Bcc",&mBcc,false); + + KPrefs::setCurrentGroup("Time & Date"); + + // addItemString("Time Zone",&mTimeZone,"+0100"); + addItemString("TimeZoneName",&mTimeZoneId,i18n ("+01:00 Europe/Oslo(CET)") ); + // addItemInt("TimeZoneOffset",&mTimeZoneOffset,60); + addItemBool("UseDaylightsaving",&mUseDaylightsaving,true); + addItemInt("DaylightsavingStart",&mDaylightsavingStart,90); + addItemInt("DaylightsavingEnd",&mDaylightsavingEnd,304); + + + addItemInt("Default Start Time",&mStartTime,10); + addItemInt("Default Duration",&mDefaultDuration,2); + addItemInt("Default Alarm Time",&mAlarmTime,3); + addItemInt("Daylight Savings",&mDaylightSavings,0); + KPrefs::setCurrentGroup("AlarmSettings"); + addItemInt("AlarmPlayBeeps",&mAlarmPlayBeeps,20); + addItemInt("AlarmSuspendTime",&mAlarmSuspendTime,7); + addItemInt("AlarmSuspendCount",&mAlarmSuspendCount,5); + addItemInt("AlarmBeepInterval",&mAlarmBeepInterval,3); + + + KPrefs::setCurrentGroup("Calendar"); + + addItemInt("Default Calendar Format",&mDefaultFormat,FormatICalendar); + + KPrefs::setCurrentGroup("Fonts"); + // qDebug(" KPrefs::setCurrentGroup(Fonts); "); + addItemFont("TimeBar Font",&mTimeBarFont); + addItemFont("MonthView Font",&mMonthViewFont); + addItemFont("AgendaView Font",&mAgendaViewFont); + addItemFont("MarcusBains Font",&mMarcusBainsFont); + addItemFont("TimeLabels Font",&mTimeLabelsFont); + addItemFont("TodoView Font",&mTodoViewFont); + addItemFont("ListView Font",&mListViewFont); + addItemFont("DateNavigator Font",&mDateNavigatorFont); + addItemFont("EditBox Font",&mEditBoxFont); + addItemFont("JournalView Font",&mJornalViewFont); + addItemFont("WhatsNextView Font",&mWhatsNextFont); + addItemFont("EventView Font",&mEventViewFont); + + KPrefs::setCurrentGroup("SyncProfiles"); + addItemString("LocalMachineName",&mLocalMachineName, "undefined"); + addItemStringList("SyncProfileNames",&mSyncProfileNames); + + KPrefs::setCurrentGroup("RemoteSyncing"); + addItemBool("UsePasswd",&mUsePassWd,false); + addItemBool("WriteBackFile",&mWriteBackFile,true); + addItemBool("WriteBackExistingOnly",&mWriteBackExistingOnly,false); + addItemBool("AskForPreferences",&mAskForPreferences,true); + addItemBool("ShowSyncSummary",&mShowSyncSummary,true); + addItemBool("ShowSyncEvents",&mShowSyncEvents,false); + addItemInt("LastSyncTime",&mLastSyncTime,0); + addItemInt("SyncAlgoPrefs",&mSyncAlgoPrefs,3); + addItemInt("RingSyncAlgoPrefs",&mRingSyncAlgoPrefs,3); + +#ifdef _WIN32_ + QString hdp= locateLocal("data","korganizer")+"\\\\"; +#else + QString hdp= locateLocal("data","korganizer")+"/"; +#endif + addItemString("RemoteIP",&mRemoteIP, "192.168.0.65"); + addItemString("RemoteUser",&mRemoteUser, "zaurus"); + addItemString("RemotePassWd",&mRemotePassWd, ""); + addItemString("RemoteFile", &mRemoteFile, hdp+"mycalendar.ics"); + addItemString("LocalTempFile",&mLocalTempFile, "/tmp/tempsyncfile.ics" ); + + + KPrefs::setCurrentGroup("LoadSaveFileNames"); + + addItemString("LastImportFile", &mLastImportFile ,hdp +"import.ics" ); + addItemString("LastVcalFile", &mLastVcalFile ,hdp +"export.vcs" ); + addItemString("LastSaveFile", &mLastSaveFile ,hdp +"mybackup.ics" ); + addItemString("LastLoadFile", &mLastLoadFile ,hdp +"mybackup.ics" ); + addItemString("LastSyncedLocalFile", &mLastSyncedLocalFile ,hdp +"lastsync.ics" ); + + + KPrefs::setCurrentGroup("Locale"); + addItemInt("PreferredLanguage",&mPreferredLanguage,0); + addItemInt("PreferredTime",&mPreferredTime,0); + addItemInt("PreferredDate",&mPreferredDate,0); + addItemBool("WeekStartsOnSunday",&mWeekStartsOnSunday,false); + addItemBool("QuickSavingWOUnicode",&mUseQuicksave,false); + addItemBool("ShortDateInViewer",&mShortDateInViewer,false); + addItemString("UserDateFormatLong", &mUserDateFormatLong, "%A %d %b %y"); + addItemString("UserDateFormatShort", &mUserDateFormatShort, "%aK %d.%m.%y"); + + + KPrefs::setCurrentGroup("Colors"); + addItemColor("Holiday Color",&mHolidayColor,defaultHolidayColor); + addItemColor("Highlight Color",&mHighlightColor,defaultHighlightColor); + addItemColor("Event Color",&mEventColor,mDefaultCategoryColor); + addItemColor("Agenda Background Color",&mAgendaBgColor,defaultAgendaBgColor); + addItemColor("WorkingHours Color",&mWorkingHoursColor,defaultWorkingHoursColor); + addItemColor("Todo due today Color",&mTodoDueTodayColor,defaultTodoDueTodayColor); + addItemColor("Todo overdue Color",&mTodoOverdueColor,defaultTodoOverdueColor); + addItemColor("MonthViewEvenColor",&mMonthViewEvenColor,QColor( 160,160,255 )); + addItemColor("MonthViewOddColor",&mMonthViewOddColor,QColor( 160,255,160 )); + addItemColor("MonthViewHolidayColor",&mMonthViewHolidayColor,QColor( 255,160,160 )); + addItemBool("MonthViewUsesDayColors",&mMonthViewUsesDayColors,true); + addItemBool("MonthViewSatSunTog",&mMonthViewSatSunTog,true); + addItemBool("HightlightDateTimeEdit",&mHightlightDateTimeEdit,false); + addItemColor("AppColor1",&mAppColor1,QColor( 130,170,255 )); + addItemColor("AppColor2",&mAppColor2,QColor( 174,216,255 )); + addItemBool("UseAppColors",&mUseAppColors,false); + + + + KPrefs::setCurrentGroup("Views"); + addItemInt("Hour Size",&mHourSize,8); + addItemBool("Show Daily Recurrences",&mDailyRecur,true); + addItemBool("Show Weekly Recurrences",&mWeeklyRecur,true); + addItemBool("Show Month Daily Recurrences",&mMonthDailyRecur,true); + addItemBool("Show Month Weekly Recurrences",&mMonthWeeklyRecur,true); + addItemBool("ShowShortMonthName",&mMonthShowShort,false); + addItemBool("ShowIconsInMonthCell",&mMonthShowIcons,true); + addItemBool("Enable ToolTips",&mEnableToolTips,false); + addItemBool("Enable MonthView ScrollBars",&mEnableMonthScroll,false); + addItemBool("Marcus Bains shows seconds",&mMarcusBainsShowSeconds,false); + addItemBool("Show Marcus Bains",&mMarcusBainsEnabled,true); + addItemBool("EditOnDoubleClick",&mEditOnDoubleClick,true); + addItemBool("ViewChangeHoldFullscreen",&mViewChangeHoldFullscreen,false); + addItemBool("ViewChangeHoldNonFullscreen",&mViewChangeHoldNonFullscreen,false); + addItemBool("CenterOnCurrentTime",&mCenterOnCurrentTime,false); + addItemBool("SetTimeToDayStartAt",&mSetTimeToDayStartAt,true); + addItemBool("HighlightCurrentDay",&mHighlightCurrentDay,true); + addItemBool("WNViewShowsParents",&mWNViewShowsParents,true); + addItemBool("WNViewShowLocation",&mWNViewShowLocation,false); + addItemBool("UseHighlightLightColor",&mUseHighlightLightColor,false); + addItemBool("ListViewMonthTimespan",&mListViewMonthTimespan,true); + addItemBool("TodoViewUsesCatColors",&mTodoViewUsesCatColors,false); + addItemBool("TodoViewShowsPercentage",&mTodoViewShowsPercentage,false); + addItemBool("TodoViewUsesSmallFont",&mTodoViewUsesSmallFont,false); + addItemBool("TodoViewUsesForegroundColor",&mTodoViewUsesForegroundColor,false); + addItemBool("MonthViewUsesForegroundColor",&mMonthViewUsesForegroundColor,false); + addItemBool("UseInternalAlarmNotification",&mUseInternalAlarmNotification,false); + addItemInt("Day Begins",&mDayBegins,7); + addItemInt("Working Hours Start",&mWorkingHoursStart,8); + addItemInt("Working Hours End",&mWorkingHoursEnd,17); + addItemBool("Exclude Holidays",&mExcludeHolidays,true); + addItemBool("Exclude Saturdays",&mExcludeSaturdays,true); + + addItemBool("Month View Uses Category Color",&mMonthViewUsesCategoryColor,false); + addItemBool("Full View Month",&mFullViewMonth,true); + addItemBool("Full View Todo",&mFullViewTodo,true); + addItemBool("Quick Todo",&mEnableQuickTodo,false); + + addItemInt("Next X Days",&mNextXDays,3); + + KPrefs::setCurrentGroup("Printer"); + + KPrefs::setCurrentGroup("Layout"); + + addItemBool("CompactDialogs",&mCompactDialogs,false); + addItemBool("VerticalScreen",&mVerticalScreen,true); + + KPrefs::setCurrentGroup("KOrganizer Plugins"); + + addItemStringList("SelectedPlugins",&mSelectedPlugins,"holidays"); + + KPrefs::setCurrentGroup("Group Scheduling"); + + addItemInt("IMIPScheduler",&mIMIPScheduler,IMIPKMail); + addItemInt("IMIPSend",&mIMIPSend,IMIPdirectsend); + addItemStringList("AdditionalMails",&mAdditionalMails,""); + addItemInt("IMIP auto refresh",&mIMIPAutoRefresh,neverAuto); + addItemInt("IMIP auto insert request",&mIMIPAutoInsertRequest,neverAuto); + addItemInt("IMIP auto insert reply",&mIMIPAutoInsertReply,neverAuto); + addItemInt("IMIP auto FreeBusy",&mIMIPAutoFreeBusy,neverAuto); + addItemInt("IMIP auto save FreeBusy",&mIMIPAutoFreeBusyReply,neverAuto); + + KPrefs::setCurrentGroup( "Editors" ); + + addItemStringList( "EventTemplates", &mEventTemplates ); + addItemStringList( "TodoTemplates", &mTodoTemplates ); + + addItemInt("DestinationPolicy",&mDestination,standardDestination); + + + +} + + +KOPrefs::~KOPrefs() +{ + if (mInstance == this) + mInstance = insd.setObject(0); + setLocaleDict( 0 ); + if ( mLocaleDict ) + delete mLocaleDict; + //qDebug("KOPrefs::~KOPrefs() "); +} + + +KOPrefs *KOPrefs::instance() +{ + if (!mInstance) { + mInstance = insd.setObject(new KOPrefs()); + mInstance->readConfig(); + } + + return mInstance; +} + +void KOPrefs::usrSetDefaults() +{ + +} + +void KOPrefs::fillMailDefaults() +{ + if (mName.isEmpty()) mName = i18n("Anonymous"); + if (mEmail.isEmpty()) mEmail = i18n("nobody@nowhere"); +} + +void KOPrefs::setTimeZoneIdDefault() +{ + mTimeZoneId = i18n("+01:00 Europe/Oslo(CET)"); +} + +void KOPrefs::setCategoryDefaults() +{ + mCustomCategories.clear(); + mCustomCategories = getDefaultList(); + + QStringList::Iterator it; + for (it = mCustomCategories.begin();it != mCustomCategories.end();++it ) { + setCategoryColor(*it,mDefaultCategoryColor); + } +} + +QStringList KOPrefs::getDefaultList() +{ + QStringList retval ; + retval << i18n("Anniversary") << i18n("Appointment") << i18n("Birthday") << i18n("Business") << i18n("Business Travel") << i18n("Cinema") << i18n("Customer") + << i18n("Break")<< i18n("Breakfast")<< i18n("Competition")<< i18n("Dinner") + << i18n("Education")<< i18n("Family") << i18n("Favorites") << i18n("Festival")<< i18n("Fishing")<< i18n("Flight") << i18n("Gifts") + << i18n("Holiday") << i18n("Holiday Cards")<< i18n("Hot Contacts") << i18n("Hiking") << i18n("Hunting") << i18n("Key Customer") << i18n("Kids") + << i18n("Lunch") << i18n("Meeting") << i18n("Miscellaneous") << i18n("Partner")<< i18n("Party") << i18n("Personal") << i18n("Personal Travel") + << i18n("PHB") << i18n("Phone Calls") << i18n("Projects") << i18n("Recurring") << i18n("School") << i18n("Shopping") + << i18n("Speach") << i18n("Special Occasion") << i18n("Sports") << i18n("Talk") << i18n("Travel") << i18n("TV")<< i18n("University") + << i18n("Vacation") << i18n("VIP") << i18n("SyncEvent") ; + retval.sort(); + return retval; +} + +void KOPrefs::usrReadConfig() +{ + mLocaleDict = 0; + // pending LR fix translation + // qDebug("KOPrefs::usrReadConfig() fix translation "); + if ( mPreferredLanguage == 1 ) { + mLocaleDict = new QDict<QString>; + int i = 0; + QString fw ( germanwords[i] [0]); + while ( !fw.isEmpty() ) { + mLocaleDict->insert( fw, new QString (germanwords[i] [1] )); + ++i; + fw = germanwords[i] [0]; + } + + setLocaleDict( mLocaleDict ); + } + if ( mPreferredLanguage == 3 ) { + QString fileName = MainWindow::resourcePath()+"usertranslation.txt"; + QFile file( fileName ); + if (file.open( IO_ReadOnly ) ) { + QTextStream ts( &file ); + ts.setCodec( QTextCodec::codecForLocale() ); + QString text = ts.read(); + file.close(); + + QString line; + QString we; + QString wt; + int br = 0; + int nbr; + nbr = text.find ( "},", br ); + line = text.mid( br, nbr - br ); + br = nbr+1; + int se, ee, st, et; + mLocaleDict = new QDict<QString>; + QString end = "{ \"\",\"\" }"; + while ( (line != end) && (br > 1) ) { + //qDebug("%d *%s* ", br, line.latin1()); + se = line.find("\"")+1; + et = line.findRev("\"",-1); + ee = line.find("\",\""); + st = ee+3; + we = line.mid( se, ee-se ); + wt = line.mid( st, et-st ); + //qDebug("*%s* *%s* ", we.latin1(), wt.latin1()); + mLocaleDict->insert( we, new QString (wt) ); + nbr = text.find ( "}", br ); + line = text.mid( br, nbr - br ); + br = nbr+1; + } + //qDebug("end *%s* ", end.latin1()); + + setLocaleDict( mLocaleDict ); + } else { + qDebug("KO: Cannot find translation file usertranslation.txt"); + } + } + config()->setGroup("General"); + + mCustomCategories = config()->readListEntry("Custom Categories"); + if ( KOPrefs::instance()->mLanguageChanged ) { + mLocationDefaults.clear(); + mEventSummaryUser.clear(); + mTodoSummaryUser.clear(); + } + if (mLocationDefaults.isEmpty()) { + mLocationDefaults << i18n("Home") << i18n("Office") << i18n("Libary") << i18n("School") << i18n("Doctor") << i18n("Beach") + << i18n("University") << i18n("Restaurant") << i18n("Bar") << i18n("Conference room") << i18n("Cinema") << i18n("Lake") << i18n("Kindergarden") + << i18n("Germany") << i18n("Sweden") << i18n("Forest") << i18n("Desert") << i18n("Kitchen") ; + // << i18n("") << i18n("") << i18n("") << i18n("") << i18n("") << i18n("") << i18n("") << i18n("") + mLocationDefaults.sort(); + } + + if (mEventSummaryUser.isEmpty()) { + mEventSummaryUser = getDefaultList() ; + } + if (mTodoSummaryUser.isEmpty()) { + mTodoSummaryUser = getDefaultList() ; + } + + if (mCustomCategories.isEmpty()) setCategoryDefaults(); + + config()->setGroup("Personal Settings"); + mName = config()->readEntry("user_name",""); + mEmail = config()->readEntry("user_email",""); + fillMailDefaults(); + + config()->setGroup("Category Colors"); + QStringList::Iterator it; + for (it = mCustomCategories.begin();it != mCustomCategories.end();++it ) { + setCategoryColor(*it,config()->readColorEntry(*it,&mDefaultCategoryColor)); + + } + + if (mTimeZoneId.isEmpty()) { + setTimeZoneIdDefault(); + } + KPimPrefs::usrReadConfig(); +} + + +void KOPrefs::usrWriteConfig() +{ + config()->setGroup("General"); + config()->writeEntry("Custom Categories",mCustomCategories); + + config()->setGroup("Personal Settings"); + config()->writeEntry("user_name",mName); + config()->writeEntry("user_email",mEmail); + + config()->setGroup("Category Colors"); + QDictIterator<QColor> it(mCategoryColors); + while (it.current()) { + config()->writeEntry(it.currentKey(),*(it.current())); + ++it; + } + + + KPimPrefs::usrWriteConfig(); +} + +void KOPrefs::setCategoryColor(QString cat,const QColor & color) +{ + mCategoryColors.replace(cat,new QColor(color)); +} + +QColor *KOPrefs::categoryColor(QString cat) +{ + QColor *color = 0; + + if (!cat.isEmpty()) color = mCategoryColors[cat]; + + if (color) return color; + else return &mDefaultCategoryColor; +} + +void KOPrefs::setFullName(const QString &name) +{ + mName = name; +} + +void KOPrefs::setEmail(const QString &email) +{ + //qDebug(" KOPrefs::setEmai*********** %s",email.latin1() ); + mEmail = email; +} + +QString KOPrefs::fullName() +{ + if (mEmailControlCenter) { + KEMailSettings settings; + return settings.getSetting(KEMailSettings::RealName); + } else { + return mName; + } +} + +QString KOPrefs::email() +{ + if (mEmailControlCenter) { + KEMailSettings settings; + return settings.getSetting(KEMailSettings::EmailAddress); + } else { + return mEmail; + } +} +KConfig* KOPrefs::getConfig() +{ + return config(); +} diff --git a/korganizer/koprefs.h b/korganizer/koprefs.h new file mode 100644 index 0000000..fe044e6 --- a/dev/null +++ b/korganizer/koprefs.h @@ -0,0 +1,299 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KOPREFS_H +#define KOPREFS_H + +#include <qdict.h> + +#include <libkdepim/kpimprefs.h> + +class KConfig; +class QFont; +class QColor; +class QStringList; + +class KOPrefs : public KPimPrefs +{ + public: + enum { FormatVCalendar, FormatICalendar }; + enum { MailClientKMail, MailClientSendmail }; + enum { IMIPDummy, IMIPKMail }; + enum { IMIPOutbox, IMIPdirectsend }; + enum { neverAuto, addressbookAuto, selectedAuto }; + enum { standardDestination, askDestination }; + + virtual ~KOPrefs(); + + /** Get instance of KOPrefs. It is made sure that there is only one + instance. */ + static KOPrefs *instance(); + + /** Set preferences to default values */ + void usrSetDefaults(); + + /** Read preferences from config file */ + void usrReadConfig(); + + /** Write preferences to config file */ + void usrWriteConfig(); + void setCategoryDefaults(); + + protected: + void setTimeZoneIdDefault(); + + /** Fill empty mail fields with default values. */ + void fillMailDefaults(); + + private: + /** Constructor disabled for public. Use instance() to create a KOPrefs + object. */ + KOPrefs(); + + static KOPrefs *mInstance; + QDict<QString> *mLocaleDict; + QStringList getDefaultList(); + public: + // preferences data + KConfig* getConfig(); + void setFullName(const QString &); + QString fullName(); + void setEmail(const QString &); + QString email(); + + QString mAdditional; + + bool mEmailControlCenter; + + bool mBcc; + bool mAutoSave; + int mAutoSaveInterval; + bool mConfirm; + + bool mEnableGroupScheduling; + bool mEnableProjectView; + + int mDefaultFormat; + int mMailClient; + + QString mTimeZone; + QString mTimeZoneId; + //QString mTimeZoneName; // e.g. +00:04:00 Indian/Mauritius + //int mTimeZoneOffset; // e.g. -240 min + bool mUseDaylightsaving; + int mDaylightsavingStart; + int mDaylightsavingEnd; + int mStartTime; + int mDefaultDuration; + int mAlarmTime; + int mDaylightSavings; + + int mWorkingHoursStart; + int mWorkingHoursEnd; + bool mExcludeHolidays; + bool mExcludeSaturdays; + bool mMarcusBainsShowSeconds; + + QFont mTimeBarFont; + QFont mMonthViewFont; + QFont mAgendaViewFont; + QFont mMarcusBainsFont; + QFont mTimeLabelsFont; + QFont mTodoViewFont; + QFont mListViewFont; + QFont mDateNavigatorFont; + QFont mEditBoxFont; + QFont mJornalViewFont; + QFont mWhatsNextFont; + QFont mEventViewFont; + + + + + QColor mHolidayColor; + QColor mHighlightColor; + QColor mEventColor; + QColor mAgendaBgColor; + QColor mWorkingHoursColor; + QColor mTodoDueTodayColor; + QColor mTodoOverdueColor; + QColor mMonthViewEvenColor; + QColor mMonthViewOddColor; + QColor mMonthViewHolidayColor; + bool mMonthViewUsesDayColors; + bool mMonthViewSatSunTog; + QColor mAppColor1; + QColor mAppColor2; + bool mUseAppColors; + + int mDayBegins; + int mHourSize; + int mAllDaySize; + bool mShowFullMenu; + bool mDailyRecur; + bool mWeeklyRecur; + bool mMonthDailyRecur; + bool mMonthWeeklyRecur; + bool mMonthShowIcons; + bool mMonthShowShort; + bool mEnableToolTips; + bool mEnableMonthScroll; + bool mFullViewMonth; + bool mMonthViewUsesCategoryColor; + bool mFullViewTodo; + bool mShowCompletedTodo; + bool mMarcusBainsEnabled; + int mNextXDays; + int mWhatsNextDays; + int mWhatsNextPrios; + bool mEnableQuickTodo; + bool mLanguageChanged; + + bool mCompactDialogs; + bool mVerticalScreen; + + bool mShowIconNewTodo; + bool mShowIconNewEvent; + bool mShowIconSearch; + bool mShowIconList; + bool mShowIconDay1; + bool mShowIconDay5; + bool mShowIconDay7; + bool mShowIconMonth; + bool mShowIconTodoview; + bool mShowIconBackFast; + bool mShowIconBack; + bool mShowIconToday; + bool mShowIconForward; + bool mShowIconForwardFast; + bool mShowIconWhatsThis; + bool mShowIconNextDays; + bool mShowIconNext; + bool mShowIconJournal; + + bool mShowIconStretch; + + bool mToolBarHor; + bool mToolBarUp; + bool mToolBarMiniIcons; + + bool mAskForQuit; + bool mUsePassWd; + bool mWriteBackFile; + bool mAskForPreferences; + bool mShowSyncSummary; + bool mShowSyncEvents; + bool mShowTodoInAgenda; + bool mWriteBackExistingOnly; + + QString mRemoteIP; + QString mRemoteUser; + QString mRemotePassWd; + QString mRemoteFile; + QString mLocalTempFile; + + int mLastSyncTime; + int mSyncAlgoPrefs; + int mRingSyncAlgoPrefs; + QStringList mSyncProfileNames; + QString mLocalMachineName; + void setCategoryColor(QString cat,const QColor & color); + QColor *categoryColor(QString cat); + + QString mArchiveFile; + QString mHtmlExportFile; + bool mHtmlWithSave; + + QStringList mSelectedPlugins; + + QString mLastImportFile; + QString mLastVcalFile; + QString mLastSaveFile; + QString mLastLoadFile; + QString mLastSyncedLocalFile; + + + QString mDefaultAlarmFile; + int mIMIPScheduler; + int mIMIPSend; + QStringList mAdditionalMails; + int mIMIPAutoRefresh; + int mIMIPAutoInsertReply; + int mIMIPAutoInsertRequest; + int mIMIPAutoFreeBusy; + int mIMIPAutoFreeBusyReply; + + QStringList mTodoTemplates; + QStringList mEventTemplates; + + int mDestination; + + + bool mEditOnDoubleClick; + bool mViewChangeHoldFullscreen; + bool mViewChangeHoldNonFullscreen; + bool mCenterOnCurrentTime; + bool mSetTimeToDayStartAt; + bool mHighlightCurrentDay; + bool mUseHighlightLightColor; + bool mListViewMonthTimespan; + bool mWNViewShowsParents; + bool mWNViewShowLocation; + bool mTodoViewShowsPercentage; + bool mTodoViewUsesCatColors; + bool mTodoViewUsesSmallFont; + bool mTodoViewUsesForegroundColor; + bool mMonthViewUsesForegroundColor; + + bool mHightlightDateTimeEdit; + int mPreferredLanguage; + bool mUseQuicksave; + int mPreferredTime; + int mPreferredDate; + bool mWeekStartsOnSunday; + bool mShortDateInViewer; + QString mUserDateFormatLong; + QString mUserDateFormatShort; + + QStringList mLocationDefaults; + QStringList mEventSummaryUser; + QStringList mTodoSummaryUser; + + bool mUseInternalAlarmNotification; + int mAlarmPlayBeeps; + int mAlarmSuspendTime; + int mAlarmSuspendCount; + int mAlarmBeepInterval; + + private: + QDict<QColor> mCategoryColors; + QColor mDefaultCategoryColor; + + QFont mDefaultTimeBarFont; + QFont mDefaultViewFont; + QFont mDefaultMonthViewFont; + + QString mName; + QString mEmail; +}; + +#endif diff --git a/korganizer/koprefsdialog.cpp b/korganizer/koprefsdialog.cpp new file mode 100644 index 0000000..04fffe2 --- a/dev/null +++ b/korganizer/koprefsdialog.cpp @@ -0,0 +1,1610 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> +#include <qlabel.h> +#include <qgroupbox.h> +#include <qbuttongroup.h> +#include <qlineedit.h> +#include <qfont.h> +#include <qslider.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qcombobox.h> +#include <qvbox.h> +#include <qhbox.h> +#include <qregexp.h> +#include <qspinbox.h> +#include <qdatetime.h> +#include <qcheckbox.h> +#include <qradiobutton.h> +#include <qpushbutton.h> +#include <qstrlist.h> +#include <qapplication.h> + +#include <kcolorbutton.h> +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> +#include <kfontdialog.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <kcolordialog.h> +#include <kiconloader.h> +#include <kemailsettings.h> +#include <kstandarddirs.h> + +#include <kurlrequester.h> +#include <klineedit.h> + +#if defined(USE_SOLARIS) +#include <sys/param.h> + +#define ZONEINFODIR "/usr/share/lib/zoneinfo" +#define INITFILE "/etc/default/init" +#endif + +#include "koprefs.h" + +#include "koprefsdialog.h" +#include "koprefsdialog.moc" + + +KOPrefsDialog::KOPrefsDialog(QWidget *parent, char *name, bool modal) : + KPrefsDialog(KOPrefs::instance(),parent,name,true) +{ + + setCaption( i18n("Preferences - some settings need a restart (nr)")); + mCategoryDict.setAutoDelete(true); + + KGlobal::locale()->insertCatalogue("timezones"); + + setupMainTab(); + setupLocaleTab(); + setupTimeZoneTab(); + setupTimeTab(); + setupLocaleDateTab(); + setupFontsTab(); + setupColorsTab(); + setupViewsTab(); + //setupSyncTab(); + //setupSyncAlgTab(); + //setupPrinterTab(); + //setupGroupSchedulingTab(); + //setupGroupAutomationTab(); +} + + +KOPrefsDialog::~KOPrefsDialog() +{ +} + +void KOPrefsDialog::setupLocaleDateTab() +{ +QFrame *topFrame = addPage(i18n("Date Format"),0,0); + QGridLayout *topLayout = new QGridLayout(topFrame,3,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + int iii = 0; + + + KPrefsWidRadios *syncPrefsGroup = + addWidRadios(i18n("Date Format:"),&(KOPrefs::instance()->mPreferredDate),topFrame); + QString format; + if ( QApplication::desktop()->width() < 480 ) + format = "(%d.%m.%Y)"; + else + format = "(%d.%m.%Y|%A %d %B %Y)"; + syncPrefsGroup->addRadio(i18n("24.03.2004 "+format)); + if ( QApplication::desktop()->width() < 480 ) + format = "(%m.%d.%Y)"; + else + format = "(%m.%d.%Y|%A %B %d %Y)"; + syncPrefsGroup->addRadio(i18n("03.24.2004 "+format)); + if ( QApplication::desktop()->width() < 480 ) + format = "(%Y-%m-%d)"; + else + format = "(%Y-%m-%d|%A %Y %B %d)"; + syncPrefsGroup->addRadio(i18n("2004-03-24 "+format)); + syncPrefsGroup->addRadio(i18n("User defined")); + topLayout->addMultiCellWidget( syncPrefsGroup->groupBox(),iii,iii,0,1); + ++iii; + ++iii; + QLabel * lab; + mUserDateFormatLong = new QLineEdit(topFrame); + lab = new QLabel(mUserDateFormatLong, i18n("User long date:"), topFrame); + topLayout->addWidget(lab ,iii,0); + topLayout->addWidget(mUserDateFormatLong,iii,1); + ++iii; + mUserDateFormatShort = new QLineEdit(topFrame); + lab = new QLabel(mUserDateFormatShort, i18n("User short date:"), topFrame); + topLayout->addWidget(lab ,iii,0); + topLayout->addWidget(mUserDateFormatShort,iii,1); + ++iii; + lab = new QLabel( i18n("Monday 19 April 2004: %A %d %B %Y"), topFrame); + topLayout->addMultiCellWidget(lab ,iii,iii,0,1); + ++iii; + lab = new QLabel( i18n("Mon 19.04.04: %a %d.%m.%y"), topFrame); + topLayout->addMultiCellWidget(lab ,iii,iii,0,1); + ++iii; + lab = new QLabel( i18n("Mon, 19.Apr.04: %a, %d.%b.%y"), topFrame); + topLayout->addMultiCellWidget(lab ,iii,iii,0,1); + ++iii; + +} + +void KOPrefsDialog::setupLocaleTab() +{ + QFrame *topFrame = addPage(i18n("Locale"),0,0); + QGridLayout *topLayout = new QGridLayout(topFrame,4,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + int iii = 0; + KPrefsWidRadios *syncPrefsGroup = + addWidRadios(i18n("Language:(needs restart)"),&(KOPrefs::instance()->mPreferredLanguage),topFrame); + syncPrefsGroup->addRadio(i18n("English")); + syncPrefsGroup->addRadio(i18n("German")); + syncPrefsGroup->addRadio(i18n("French(nyi)")); + syncPrefsGroup->addRadio(i18n("User defined (usertranslation.txt)")); + if ( QApplication::desktop()->width() < 300 ) + ;// syncPrefsGroup->groupBox()-> setOrientation (Qt::Vertical); + topLayout->addMultiCellWidget( syncPrefsGroup->groupBox(),iii,iii,0,1); + ++iii; + + syncPrefsGroup = + addWidRadios(i18n("Time Format(nr):"),&(KOPrefs::instance()->mPreferredTime),topFrame); + if ( QApplication::desktop()->width() > 300 ) + syncPrefsGroup->groupBox()-> setOrientation (Qt::Vertical); + syncPrefsGroup->addRadio(i18n("24:00")); + syncPrefsGroup->addRadio(i18n("12:00am")); + syncPrefsGroup->groupBox()-> setOrientation (Qt::Vertical); + topLayout->addMultiCellWidget( syncPrefsGroup->groupBox(),iii,iii,0,1); + ++iii; + KPrefsWidBool *sb; + if ( QApplication::desktop()->width() < 300 ) { + sb = + addWidBool(i18n("Week starts on Sunday"), + &(KOPrefs::instance()->mWeekStartsOnSunday),topFrame); + topLayout->addMultiCellWidget(sb->checkBox(), iii,iii,0,1); + ++iii; + sb = + addWidBool(i18n("Use short date in (WN/E) view"), + &(KOPrefs::instance()->mShortDateInViewer),topFrame); + topLayout->addMultiCellWidget(sb->checkBox(), iii,iii,0,1); + } + else { + QWidget * hb = new QWidget( topFrame ); + QHBoxLayout *hbLayout = new QHBoxLayout(hb); + sb = + addWidBool(i18n("Week starts on Sunday"), + &(KOPrefs::instance()->mWeekStartsOnSunday),hb); + hbLayout->addWidget(sb->checkBox() ); + sb = + addWidBool(i18n("Use short date in (WN/E) view"), + &(KOPrefs::instance()->mShortDateInViewer),hb); + hbLayout->addWidget(sb->checkBox() ); + topLayout->addMultiCellWidget(hb, iii,iii,0,1); + + } + //#ifndef DESKTOP_VERSION +#if 0 + ++iii; + sb = + addWidBool(i18n("Quick load/save (w/o Unicode)"), + &(KOPrefs::instance()->mUseQuicksave),topFrame); + topLayout->addMultiCellWidget(sb->checkBox(), iii,iii,0,1); +#endif +} +void KOPrefsDialog::showSyncPage() +{ + showPage ( 2 ) ; + +} +void KOPrefsDialog::setupSyncAlgTab() +{ +#if 0 + QLabel * lab; + QFrame *topFrame = addPage(i18n("Sync Prefs"),0,0); + mSetupSyncAlgTab = topFrame; + QGridLayout *topLayout = new QGridLayout(topFrame,6,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + int iii = 0; + + KPrefsWidBool *sb = + addWidBool(i18n("Ask for preferences before syncing"), + &(KOPrefs::instance()->mAskForPreferences),topFrame); + topLayout->addMultiCellWidget(sb->checkBox(), iii,iii,0,1); + + ++iii; + + KPrefsWidRadios *syncPrefsGroup = + addWidRadios(i18n("Sync preferences:"),&(KOPrefs::instance()->mSyncAlgoPrefs), + topFrame); + syncPrefsGroup->addRadio(i18n("Take local entry on conflict")); + syncPrefsGroup->addRadio(i18n("Take remote entry on conflict")); + syncPrefsGroup->addRadio(i18n("Take newest entry on conflict")); + syncPrefsGroup->addRadio(i18n("Ask for every entry on conflict")); + syncPrefsGroup->addRadio(i18n("Force take local entry always")); + syncPrefsGroup->addRadio(i18n("Force take remote entry always")); + topLayout->addMultiCellWidget( syncPrefsGroup->groupBox(),iii,iii,0,1); + ++iii; + sb = + addWidBool(i18n("Show summary after syncing"), + &(KOPrefs::instance()->mShowSyncSummary),topFrame); + topLayout->addMultiCellWidget(sb->checkBox(), iii,iii,0,1); + + ++iii; +#endif + + + +} + + +void KOPrefsDialog::setupSyncTab() +{ +#if 0 + QLabel * lab; + QFrame *topFrame = addPage(i18n("Sync Network"),0,0); + QGridLayout *topLayout = new QGridLayout(topFrame,6,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + lab = new QLabel(i18n("Remote syncing (via ssh/scp)\nnetwork settings "), topFrame); + int iii = 0; + topLayout->addMultiCellWidget(lab , iii,iii,0,1); + ++iii; + + mRemoteIPEdit = new QLineEdit(topFrame); + lab = new QLabel(mRemoteIPEdit, i18n("Remote IP:"), topFrame); + topLayout->addWidget(lab ,iii,0); + topLayout->addWidget(mRemoteIPEdit,iii,1); + ++iii; + mRemoteUser = new QLineEdit(topFrame); + lab = new QLabel(mRemoteUser, i18n("Remote user:"), topFrame); + topLayout->addWidget(lab ,iii,0); + topLayout->addWidget(mRemoteUser, iii,1); + ++iii; + + mRemoteFile = new QLineEdit(topFrame); + lab = new QLabel(mRemoteFile, i18n("Remote file:"), topFrame); + topLayout->addWidget(lab ,iii,0); + topLayout->addWidget(mRemoteFile,iii,1); + ++iii; + + mLocalTempFile = new QLineEdit(topFrame); + lab = new QLabel(mLocalTempFile, i18n("Local temp file:"), topFrame); + topLayout->addWidget(lab ,iii,0); + topLayout->addWidget(mLocalTempFile,iii,1); + ++iii; + + KPrefsWidBool *wb = + addWidBool(i18n("Write back synced file"), + &(KOPrefs::instance()->mWriteBackFile),topFrame); + topLayout->addMultiCellWidget(wb->checkBox(), iii,iii,0,1); + ++iii; + wb = + addWidBool(i18n("Write back existing entries only"), + &(KOPrefs::instance()->mWriteBackExistingOnly),topFrame); + topLayout->addMultiCellWidget(wb->checkBox(), iii,iii,0,1); + ++iii; + +#endif +} + +void KOPrefsDialog::setupMainTab() +{ + QFrame *topFrame = addPage(i18n("General"),0,0); + // DesktopIcon("identity",KIcon::SizeMedium)); + + QGridLayout *topLayout = new QGridLayout(topFrame,6,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + + // KPrefsWidBool *emailControlCenter = +// addWidBool(i18n("&Use email settings from Control Center"), +// &(KOPrefs::instance()->mEmailControlCenter),topFrame); +// topLayout->addMultiCellWidget(emailControlCenter->checkBox(),0,0,0,1); + // connect(emailControlCenter->checkBox(),SIGNAL(toggled(bool)), + // SLOT(toggleEmailSettings(bool))); + + mNameEdit = new QLineEdit(topFrame); + mNameLabel = new QLabel(mNameEdit, i18n("Full &name:"), topFrame); + topLayout->addWidget(mNameLabel,0,0); + topLayout->addWidget(mNameEdit,0,1); + + mEmailEdit = new QLineEdit(topFrame); + mEmailLabel = new QLabel(mEmailEdit, i18n("E&mail address:"),topFrame); + topLayout->addWidget(mEmailLabel,1,0); + topLayout->addWidget(mEmailEdit,1,1); + KPrefsWidBool *wb; + QHBox *dummy; + if ( QApplication::desktop()->width() > 480 ) { + dummy = new QHBox(topFrame); + } else { + dummy = new QVBox(topFrame); + } + + topLayout->addMultiCellWidget(dummy, 2,2,0,1); + addWidBool(i18n("Full menu bar(nr)"), + &(KOPrefs::instance()->mShowFullMenu),dummy); + + + addWidBool(i18n("Mini icons in toolbar(nr)"), + &(KOPrefs::instance()->mToolBarMiniIcons),dummy); + + + dummy = new QHBox(topFrame); + new QLabel(i18n("Days in What's Next:"),dummy); + mWhatsNextSpin = new QSpinBox(1,14,1,dummy); + + topLayout->addMultiCellWidget(dummy,3,3,0,1); + + + + dummy = new QHBox(topFrame); + new QLabel(i18n("Days in Next-X-Days:"),dummy); + mNextXDaysSpin = new QSpinBox(2,14,1,dummy); + + topLayout->addMultiCellWidget(dummy,4,4,0,1); + + QHBox *prioBox = new QHBox(topFrame); + // intervalBox->setSpacing(spacingHint()); + topLayout->addMultiCellWidget(prioBox,5,5,0,1); + QString messa = i18n("Show topmost todo prios in What's Next:"); + + if ( QApplication::desktop()->width() < 300 ) + messa = i18n("Show topmost todo prios in What's N.:"); + QLabel *prioLabel = new QLabel(messa, prioBox); + mPrioSpin = new QSpinBox(0,5,1,prioBox); + if ( QApplication::desktop()->width() < 300 ) + mPrioSpin->setFixedWidth( 40 ); + + // KPrefsWidBool *bcc = +// addWidBool(i18n("Send copy to owner when mailing events"), +// &(KOPrefs::instance()->mBcc),topFrame); +// topLayout->addMultiCellWidget(bcc->checkBox(),4,4,0,1); + + + // QGroupBox *autoSaveGroup = new QGroupBox(1,Horizontal,i18n("Auto-Save"), topFrame); + //topLayout->addMultiCellWidget(autoSaveGroup,6,6,0,1); + + // addWidBool(i18n("Enable automatic saving of calendar"), + // &(KOPrefs::instance()->mAutoSave),autoSaveGroup); + + QHBox *intervalBox = new QHBox(topFrame); + // intervalBox->setSpacing(spacingHint()); + topLayout->addMultiCellWidget(intervalBox,6,6,0,1); + QLabel *autoSaveIntervalLabel = new QLabel(i18n("Auto save delay in minutes:"),intervalBox); + mAutoSaveIntervalSpin = new QSpinBox(0,500,1,intervalBox); + autoSaveIntervalLabel->setBuddy(mAutoSaveIntervalSpin); + /* + QHBox * agendasize = new QHBox ( topFrame ); + + new QLabel (i18n("AllDayAgenda Height:"), agendasize ); + + + mHourSizeSlider = new QSlider(24,47,1,24,Horizontal,agendasize); + topLayout->addMultiCellWidget(agendasize,7,7,0,1); + */ + KPrefsWidBool *verticalScreen = + addWidBool(i18n("Show vertical screen (Needs restart)"), + &(KOPrefs::instance()->mVerticalScreen),topFrame); + //topLayout->addWidget(verticalScreen->checkBox(),ii++,0); + topLayout->addMultiCellWidget(verticalScreen->checkBox(),7,7,0,1); + + KPrefsWidBool *ask = + addWidBool(i18n("Ask for quit when closing KO/Pi"), + &(KOPrefs::instance()->mAskForQuit),topFrame); + topLayout->addMultiCellWidget(ask->checkBox(),8,8,0,1); + + + /* + KPrefsWidBool *confirmCheck = + addWidBool(i18n("Confirm &deletes"),&(KOPrefs::instance()->mConfirm), + topFrame); + topLayout->addMultiCellWidget(confirmCheck->checkBox(),7,7,0,1); + + + mEnableGroupScheduling = + addWidBool(i18n("Enable group scheduling"), + &(KOPrefs::instance()->mEnableGroupScheduling),topFrame); + topLayout->addWidget(mEnableGroupScheduling->checkBox(),8,0); + connect(mEnableGroupScheduling->checkBox(),SIGNAL(clicked()), + SLOT(warningGroupScheduling())); + + mEnableProjectView = + addWidBool(i18n("Enable project view"), + &(KOPrefs::instance()->mEnableProjectView),topFrame); + topLayout->addWidget(mEnableProjectView->checkBox(),9,0); + connect(mEnableProjectView->checkBox(),SIGNAL(clicked()), + SLOT(warningProjectView())); + + // Can't be disabled anymore + mEnableGroupScheduling->checkBox()->hide(); + + // Disable setting, because this feature now becomes stable + mEnableProjectView->checkBox()->hide(); + + KPrefsWidRadios *defaultFormatGroup = + addWidRadios(i18n("Default Calendar Format"), + &(KOPrefs::instance()->mDefaultFormat),topFrame); + defaultFormatGroup->addRadio(i18n("vCalendar")); + defaultFormatGroup->addRadio(i18n("iCalendar")); + + topLayout->addMultiCellWidget(defaultFormatGroup->groupBox(),10,10,0,1); + + // Default format unconditionally is iCalendar + defaultFormatGroup->groupBox()->hide(); + + KPrefsWidRadios *mailClientGroup = + addWidRadios(i18n("Mail Client"),&(KOPrefs::instance()->mMailClient), + topFrame); + mailClientGroup->addRadio(i18n("KMail")); + mailClientGroup->addRadio(i18n("Sendmail")); + topLayout->addMultiCellWidget(mailClientGroup->groupBox(),11,11,0,1); + + KPrefsWidBool *htmlsave = + addWidBool(i18n("Export to HTML with every save"),&(KOPrefs::instance()->mHtmlWithSave), + topFrame); + topLayout->addMultiCellWidget(htmlsave->checkBox(),12,12,0,1); + + KPrefsWidRadios *destinationGroup = + addWidRadios(i18n("New Events/Todos should"),&(KOPrefs::instance()->mDestination), + topFrame); + destinationGroup->addRadio(i18n("be added to the standard resource")); + destinationGroup->addRadio(i18n("be asked which resource to use")); + topLayout->addMultiCellWidget(destinationGroup->groupBox(),13,13,0,1); + + topLayout->setRowStretch(14,1); + */ +} + + +void KOPrefsDialog::setupTimeTab() +{ + QFrame *topFrame = addPage(i18n("Time"),0,0); + // DesktopIcon("clock",KIcon::SizeMedium)); + + QGridLayout *topLayout = new QGridLayout(topFrame,4,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + + QHBox *dummy = new QHBox(topFrame); + KPrefsWidTime *dayBegins = + addWidTime(i18n("Day begins at:"),&(KOPrefs::instance()->mDayBegins), + dummy); + //topLayout->addWidget(dayBegins->label(),2,0); + + //topLayout->addWidget(dayBegins->spinBox(),2,1); + topLayout->addMultiCellWidget(dummy,0,0,0,1); + + topLayout->addWidget(new QLabel(i18n("Default appointment time:"), + topFrame),1,0); + mStartTimeSpin = new QSpinBox(0,23,1,topFrame); + mStartTimeSpin->setSuffix(":00"); + topLayout->addWidget(mStartTimeSpin,1,1); + + topLayout->addWidget(new QLabel(i18n("Def. duration of new app.:"), + topFrame),2,0); + mDefaultDurationSpin = new QSpinBox(0,23,1,topFrame); + mDefaultDurationSpin->setSuffix(":00"); + topLayout->addWidget(mDefaultDurationSpin,2,1); + + QStringList alarmList; + alarmList << i18n("1 minute") << i18n("5 minutes") << i18n("10 minutes") + << i18n("15 minutes") << i18n("30 minutes")<< i18n("1 hour")<< i18n("3 hours") << i18n("24 hours") ; + topLayout->addWidget(new QLabel(i18n("Default alarm time:"),topFrame), + 3,0); + mAlarmTimeCombo = new QComboBox(topFrame); + mAlarmTimeCombo->insertStringList(alarmList); + topLayout->addWidget(mAlarmTimeCombo,3,1); + + + QGroupBox *workingHoursGroup = new QGroupBox(1,Horizontal, + i18n("Working Hours"), + topFrame); + topLayout->addMultiCellWidget(workingHoursGroup,4,4,0,1); + workingHoursGroup->layout()->setSpacing( 0 ); + workingHoursGroup->layout()->setMargin( 4 ); + QHBox *workStartBox = new QHBox(workingHoursGroup); + // workStartBox->setMargin( 0 ); + addWidTime(i18n("Daily starting hour:"), + &(KOPrefs::instance()->mWorkingHoursStart),workStartBox); + + QHBox *workEndBox = new QHBox(workingHoursGroup); + //workEndBox->setMargin( 0 ); + addWidTime(i18n("Daily ending hour:"), + &(KOPrefs::instance()->mWorkingHoursEnd),workEndBox); + QVBox *excludeBox = new QVBox(workingHoursGroup); + //excludeBox->setMargin( 0 ); + addWidBool(i18n("Exclude holidays"), + &(KOPrefs::instance()->mExcludeHolidays),excludeBox); + + addWidBool(i18n("Exclude Saturdays"), + &(KOPrefs::instance()->mExcludeSaturdays),excludeBox); + +// KPrefsWidBool *marcusBainsShowSeconds = addWidBool(i18n("Show seconds on Marcus Bains line"), +// &(KOPrefs::instance()->mMarcusBainsShowSeconds), +// topFrame); +// topLayout->addWidget(marcusBainsShowSeconds->checkBox(),5,0); + + // topLayout->setRowStretch(6,1); +} + + +void KOPrefsDialog::setupViewsTab() +{ + + QFrame *topFrame = addPage(i18n("Views"),0,0); + // DesktopIcon("viewmag",KIcon::SizeMedium)); + + QGridLayout *topLayout = new QGridLayout(topFrame,6,1); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + +// QBoxLayout *dayBeginsLayout = new QHBoxLayout; +// topLayout->addLayout(dayBeginsLayout,0,0); + +// KPrefsWidTime *dayBegins = +// addWidTime(i18n("Day begins at:"),&(KOPrefs::instance()->mDayBegins), +// topFrame); +// dayBeginsLayout->addWidget(dayBegins->label()); +// dayBeginsLayout->addStretch(1); +// dayBeginsLayout->addWidget(dayBegins->spinBox()); + +// QBoxLayout *nextDaysLayout = new QHBoxLayout; +// topLayout->addLayout(nextDaysLayout,1,0); +// nextDaysLayout->addWidget(new QLabel(i18n("Days to show in Next-X-Days view:"),topFrame)); +// mNextXDaysSpin = new QSpinBox(2,14,1,topFrame); +// nextDaysLayout->addStretch(1); +// nextDaysLayout->addWidget(mNextXDaysSpin); + + + int ii = 0; + KPrefsWidBool *dummy = + addWidBool(i18n("Edit item on doubleclick (if not, show)"), + &(KOPrefs::instance()->mEditOnDoubleClick),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + dummy = + addWidBool(i18n("Highlight current day in agenda"), + &(KOPrefs::instance()->mHighlightCurrentDay),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + dummy = + addWidBool(i18n("Use light color for highlight current day"), + &(KOPrefs::instance()->mUseHighlightLightColor),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + KPrefsWidBool *dailyRecur = + addWidBool(i18n("Show events that recur daily in date nav."), + &(KOPrefs::instance()->mDailyRecur),topFrame); + topLayout->addWidget(dailyRecur->checkBox(),ii++,0); + + KPrefsWidBool *weeklyRecur = + addWidBool(i18n("Show ev. that recur weekly in date nav."), + &(KOPrefs::instance()->mWeeklyRecur),topFrame); + topLayout->addWidget(weeklyRecur->checkBox(),ii++,0); + if ( QApplication::desktop()->width() > 640 ) { + + KPrefsWidBool *enableToolTips = + addWidBool(i18n("Enable tooltips displaying summary of ev."), + &(KOPrefs::instance()->mEnableToolTips),topFrame); + topLayout->addWidget(enableToolTips->checkBox(),ii++,0); + + } + KPrefsWidBool *passwdk = + addWidBool(i18n("Show parent To-Do's in What's Next view"), + &(KOPrefs::instance()->mWNViewShowsParents),topFrame); + topLayout->addWidget(passwdk->checkBox(), ii++,0); + + passwdk = + addWidBool(i18n("Show location in What's Next view"), + &(KOPrefs::instance()->mWNViewShowLocation),topFrame); + topLayout->addWidget(passwdk->checkBox(), ii++,0); + + passwdk = + addWidBool(i18n("Show Sync Events in WN/Agenda view"), + &(KOPrefs::instance()->mShowSyncEvents),topFrame); + topLayout->addWidget(passwdk->checkBox(), ii++,0); + + + KPrefsWidBool *marcusBainsEnabled = + addWidBool(i18n("Show Marcus Bains line"), + &(KOPrefs::instance()->mMarcusBainsEnabled),topFrame); + topLayout->addWidget(marcusBainsEnabled->checkBox(),ii++,0); + + + // topLayout->addWidget(hourSizeGroup,ii++,0); + // topLayout->addMultiCellWidget(hourSizeGroup,ii,ii,0,0); + //topLayout->setRowStretch(11,1); + + + + + + + topFrame = addPage(i18n("ViewChange"),0,0); + // DesktopIcon("viewmag",KIcon::SizeMedium)); + + topLayout = new QGridLayout(topFrame,6,1); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + ii = 0; + + + dummy = + addWidBool(i18n("Hold fullscreen on view change"), + &(KOPrefs::instance()->mViewChangeHoldFullscreen),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + dummy = + addWidBool(i18n("Hold non-fullscreen on view change"), + &(KOPrefs::instance()->mViewChangeHoldNonFullscreen),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + + KPrefsWidBool *fullViewTodo = + addWidBool(i18n("Event list view uses full window"), + &(KOPrefs::instance()->mFullViewTodo),topFrame); + topLayout->addWidget(fullViewTodo->checkBox(),ii++,0); + + KPrefsWidBool *fullViewMonth = + addWidBool(i18n("Next days view uses full window"), + &(KOPrefs::instance()->mFullViewMonth),topFrame); + topLayout->addWidget(fullViewMonth->checkBox(),ii++,0); + + dummy = + addWidBool(i18n("Set agenda to DayBeginsAt on change"), + &(KOPrefs::instance()->mSetTimeToDayStartAt),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + dummy = + addWidBool(i18n("Set agenda to current time on change"), + &(KOPrefs::instance()->mCenterOnCurrentTime),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + dummy = + addWidBool(i18n("Listview uses monthly timespan"), + &(KOPrefs::instance()->mListViewMonthTimespan),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + dummy = + addWidBool(i18n("Highlight selection in Time Edit"), + &(KOPrefs::instance()->mHightlightDateTimeEdit),topFrame); + topLayout->addWidget( dummy->checkBox(), ii++,0); + + + + + + topFrame = addPage(i18n("Month View"),0,0); + // DesktopIcon("viewmag",KIcon::SizeMedium)); + + topLayout = new QGridLayout(topFrame,5,1); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + ii = 0; + QLabel *lab; + QHBox *habo = new QHBox( topFrame ); + if ( QApplication::desktop()->width() < 320 ) { + lab = new QLabel ( i18n("Show events that recur "), topFrame ); + topLayout->addMultiCellWidget(lab,ii, ii,0,1); + ii++; + + } else { + new QLabel ( i18n("Show events that recur "), habo ); + + } + dailyRecur = + addWidBool(i18n("daily"), + &(KOPrefs::instance()->mMonthDailyRecur),habo); + // topLayout->addWidget(dailyRecur->checkBox(),ii++,0); + + weeklyRecur = + addWidBool(i18n("weekly"), + &(KOPrefs::instance()->mMonthWeeklyRecur),habo); + topLayout->addMultiCellWidget(habo,ii, ii,0,1); + ii++; + + + habo = new QHBox( topFrame ); + if ( QApplication::desktop()->width() < 320 ) { + lab = new QLabel (i18n("Show in every cell ") , topFrame ); + topLayout->addMultiCellWidget(lab,ii, ii,0,1); + ii++; + + } else { + new QLabel ( i18n("Show in every cell "), habo ); + } + weeklyRecur = + addWidBool(i18n("short month"), + &(KOPrefs::instance()->mMonthShowShort),habo); + weeklyRecur = + addWidBool(i18n("icons"), + &(KOPrefs::instance()->mMonthShowIcons),habo); + + topLayout->addMultiCellWidget(habo,ii, ii,0,1); + ii++; +#ifdef DESKTOP_VERSION + KPrefsWidBool *enableMonthScroll = + addWidBool(i18n("Enable scrollbars in month view cells"), + &(KOPrefs::instance()->mEnableMonthScroll),topFrame); + topLayout->addWidget(enableMonthScroll->checkBox(),ii++,0); +#endif + + dummy = + addWidBool(i18n("Show Sat/Sun together"), + &(KOPrefs::instance()->mMonthViewSatSunTog),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + KPrefsWidBool *coloredCategoriesInMonthView = + addWidBool(i18n("Month view uses category colors"), + &(KOPrefs::instance()->mMonthViewUsesCategoryColor),topFrame); + topLayout->addWidget(coloredCategoriesInMonthView->checkBox(),ii++,0); + + dummy = + addWidBool(i18n("Categorie colors are applied to text"), + &(KOPrefs::instance()->mMonthViewUsesForegroundColor),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + coloredCategoriesInMonthView = + addWidBool(i18n("Month view uses day colors"), + &(KOPrefs::instance()->mMonthViewUsesDayColors),topFrame); + topLayout->addWidget(coloredCategoriesInMonthView->checkBox(),ii++,0); + + KPrefsWidColor *holidayColor = + addWidColor(i18n("Day color odd months"), + &(KOPrefs::instance()->mMonthViewOddColor),topFrame); + topLayout->addWidget(holidayColor->label(),ii,0); + topLayout->addWidget(holidayColor->button(),ii++,1); + + holidayColor = + addWidColor(i18n("Day color even months"), + &(KOPrefs::instance()->mMonthViewEvenColor),topFrame); + topLayout->addWidget(holidayColor->label(),ii,0); + topLayout->addWidget(holidayColor->button(),ii++,1); + + + holidayColor = + addWidColor(i18n("Color for Sundays + category \"Holiday\""), + &(KOPrefs::instance()->mMonthViewHolidayColor),topFrame); + topLayout->addWidget(holidayColor->label(),ii,0); + topLayout->addWidget(holidayColor->button(),ii++,1); + + // *********************** Todo View + + topFrame = addPage(i18n("Todo View"),0,0); + // DesktopIcon("viewmag",KIcon::SizeMedium)); + + topLayout = new QGridLayout(topFrame,4,1); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + ii = 0; + + KPrefsWidBool *showCompletedTodo = + addWidBool(i18n("To-do view shows completed Todos"), + &(KOPrefs::instance()->mShowCompletedTodo),topFrame); + topLayout->addWidget(showCompletedTodo->checkBox(),ii++,0); + dummy = + addWidBool(i18n("To-do view shows complete as 'xx %'"), + &(KOPrefs::instance()->mTodoViewShowsPercentage),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + dummy = + addWidBool(i18n("Small To-do view uses smaller font"), + &(KOPrefs::instance()->mTodoViewUsesSmallFont),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + + + dummy = + addWidBool(i18n("Todo view uses category colors"), + &(KOPrefs::instance()->mTodoViewUsesCatColors),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + + QWidget* wid = new QWidget( topFrame ); + // Todo due today color + KPrefsWidColor *todoDueTodayColor = + addWidColor(i18n("Todo due today color:"), + &(KOPrefs::instance()->mTodoDueTodayColor),wid); + QHBoxLayout *widLayout = new QHBoxLayout(wid); + widLayout->addWidget( todoDueTodayColor->label() ); + widLayout->addWidget( todoDueTodayColor->button() ); + topLayout->addWidget(wid,ii++,0); + //topLayout->addWidget(todoDueTodayColor->button(),ii++,1); + + // Todo overdue color + wid = new QWidget( topFrame ); + widLayout = new QHBoxLayout(wid); + KPrefsWidColor *todoOverdueColor = + addWidColor(i18n("Todo overdue color:"), + &(KOPrefs::instance()->mTodoOverdueColor),wid); + widLayout->addWidget(todoOverdueColor->label()); + widLayout->addWidget(todoOverdueColor->button()); + topLayout->addWidget(wid,ii++,0); + + dummy = + addWidBool(i18n("Colors are applied to text"), + &(KOPrefs::instance()->mTodoViewUsesForegroundColor),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + dummy = + addWidBool(i18n("Allday Agenda view shows todos"), + &(KOPrefs::instance()->mShowTodoInAgenda),topFrame); + topLayout->addWidget(dummy->checkBox(),ii++,0); + + + + + topFrame = addPage(i18n("Alarm"),0,0); + // DesktopIcon("viewmag",KIcon::SizeMedium)); + + topLayout = new QGridLayout(topFrame,2,1); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + int iii = 0; + + dummy = + addWidBool(i18n("Use internal alarm notification"), + &(KOPrefs::instance()->mUseInternalAlarmNotification),topFrame); + topLayout->addWidget(dummy->checkBox(),iii++,0); + lab = new QLabel( i18n("Note: KO/Pi must be running to notify you about an alarm. Recommended for use on Zaurus: Disable this option and install KO/Pi alarm applet.\n"), topFrame); + + topLayout->addWidget(lab ,iii++,0); +#ifndef DESKTOP_VERSION + lab->setAlignment( AlignLeft|WordBreak|AlignTop); +#else + lab->setAlignment( AlignLeft|BreakAnywhere|WordBreak|AlignTop); + lab->setSizePolicy( QSizePolicy( QSizePolicy::Ignored , QSizePolicy::Ignored,true) ); +#endif + + QHBox* dummyBox = new QHBox(topFrame); + new QLabel(i18n("Play beeps count:"),dummyBox); + mAlarmPlayBeeps = new QSpinBox(0,500,1,dummyBox); + topLayout->addWidget(dummyBox,iii++,0); + + dummyBox = new QHBox(topFrame); + new QLabel(i18n("Beeps interval in sec:"),dummyBox); + mAlarmBeepInterval = new QSpinBox(1,600,1,dummyBox); + topLayout->addWidget(dummyBox,iii++,0); + + dummyBox = new QHBox(topFrame); + new QLabel(i18n("Default suspend time in min:"),dummyBox); + mAlarmSuspendTime = new QSpinBox(1,600,1,dummyBox); + topLayout->addWidget(dummyBox,iii++,0); + + dummyBox = new QHBox(topFrame); + new QLabel(i18n("Auto suspend count:"),dummyBox); + mAlarmSuspendCount = new QSpinBox(0,60,1,dummyBox); + topLayout->addWidget(dummyBox,iii++,0); + + + + + + + + QHBox* hbo = new QHBox ( topFrame ); + mDefaultAlarmFile = new QLineEdit(hbo); + QPushButton * loadTemplate = new QPushButton(hbo); + QPixmap icon; + if ( QApplication::desktop()->width() < 321 ) + icon = SmallIcon("fileimport16"); + else + icon = SmallIcon("fileimport"); + loadTemplate->setIconSet (icon ) ; + connect( loadTemplate, SIGNAL( clicked() ), this , SLOT( selectSoundFile() ) ); + int size = loadTemplate->sizeHint().height(); + loadTemplate->setFixedSize( size, size ); + //lab = new QLabel( i18n("This setting is useless for 5500 user!"), topFrame); + // topLayout->addWidget(lab ,iii++,0); + lab = new QLabel( i18n("Alarm *.wav file for newly created alarm:"), topFrame); + topLayout->addWidget(lab ,iii++,0); + topLayout->addWidget(hbo,iii++,0); + // lab = new QLabel( i18n("Note: This does not mean, that for every alarm this file is replayed. This file here is associated with a newly created alarm."), topFrame); + +// topLayout->addWidget(lab ,iii++,0); +// #ifndef DESKTOP_VERSION +// lab->setAlignment( AlignLeft|WordBreak|AlignTop); +// #else +// lab->setAlignment( AlignLeft|BreakAnywhere|WordBreak|AlignTop); +// lab->setSizePolicy( QSizePolicy( QSizePolicy::Ignored , QSizePolicy::Ignored,true) ); +// #endif + + +} + +void KOPrefsDialog::selectSoundFile() +{ + QString fileName = mDefaultAlarmFile->text(); + fileName = KFileDialog::getSaveFileName( mDefaultAlarmFile->text() , "Choose default alarm file", this ); + if ( fileName.length() > 0 ) + mDefaultAlarmFile->setText( fileName ); +} +void KOPrefsDialog::setupFontsTab() +{ + + QFrame *topFrame = addPage(i18n("Fonts"),0,0); + // DesktopIcon("fonts",KIcon::SizeMedium)); + + QGridLayout *topLayout = new QGridLayout(topFrame,7,3); + topLayout->setSpacing(1); + topLayout->setMargin(3); + KPrefsWidFont * tVFont; + int i = 0; + KPrefsWidFont *timeLabelsFont = + addWidFont(i18n("23"),i18n("DateNavigator:(nr)"), + &(KOPrefs::instance()->mDateNavigatorFont),topFrame); + topLayout->addWidget(timeLabelsFont->label(),i,0); + topLayout->addWidget(timeLabelsFont->preview(),i,1); + topLayout->addWidget(timeLabelsFont->button(),i,2); + ++i; + + + timeLabelsFont = + addWidFont(i18n("Mon 15"),i18n("Date Labels:"), + &(KOPrefs::instance()->mTimeLabelsFont),topFrame); + topLayout->addWidget(timeLabelsFont->label(),i,0); + topLayout->addWidget(timeLabelsFont->preview(),i,1); + topLayout->addWidget(timeLabelsFont->button(),i,2); + ++i; + + KPrefsWidFont *timeBarFont = + addWidFont(KGlobal::locale()->formatTime(QTime(12,34)),i18n("Time bar:"), + &(KOPrefs::instance()->mTimeBarFont),topFrame); + topLayout->addWidget(timeBarFont->label(),i,0); + topLayout->addWidget(timeBarFont->preview(),i,1); + topLayout->addWidget(timeBarFont->button(),i,2); + ++i; + + + KPrefsWidFont *marcusBainsFont = + addWidFont(KGlobal::locale()->formatTime(QTime(12,34,23)),i18n("M. Bains line:"), + &(KOPrefs::instance()->mMarcusBainsFont),topFrame); + topLayout->addWidget(marcusBainsFont->label(),i,0); + topLayout->addWidget(marcusBainsFont->preview(),i,1); + topLayout->addWidget(marcusBainsFont->button(),i,2); + ++i; + + tVFont = + addWidFont(i18n("Summary"),i18n("Event Viewer:"), + &(KOPrefs::instance()->mEventViewFont),topFrame); + topLayout->addWidget(tVFont->label(),i,0); + topLayout->addWidget(tVFont->preview(),i,1); + topLayout->addWidget(tVFont->button(),i,2); + ++i; + + + + tVFont = + addWidFont(i18n("Details"),i18n("EditorBox:"), + &(KOPrefs::instance()->mEditBoxFont),topFrame); + topLayout->addWidget(tVFont->label(),i,0); + topLayout->addWidget(tVFont->preview(),i,1); + topLayout->addWidget(tVFont->button(),i,2); + ++i; + + + + topLayout->setColStretch(1,1); + topLayout->setRowStretch(4,1); + + + i = 0; + topFrame = addPage(i18n("View Fonts"),0, + DesktopIcon("fonts",KIcon::SizeMedium)); + + topLayout = new QGridLayout(topFrame,7,3); + topLayout->setSpacing(1); + topLayout->setMargin(3); + + tVFont = + addWidFont(i18n("Configure KO"),i18n("What's Next View:"), + &(KOPrefs::instance()->mWhatsNextFont),topFrame); + topLayout->addWidget(tVFont->label(),i,0); + topLayout->addWidget(tVFont->preview(),i,1); + topLayout->addWidget(tVFont->button(),i,2); + ++i; + KPrefsWidFont *agendaViewFont = + addWidFont(i18n("Event text"),i18n("Agenda view:"), + &(KOPrefs::instance()->mAgendaViewFont),topFrame); + topLayout->addWidget(agendaViewFont->label(),i,0); + topLayout->addWidget(agendaViewFont->preview(),i,1); + topLayout->addWidget(agendaViewFont->button(),i,2); + ++i; + + + KPrefsWidFont *monthViewFont = + addWidFont(KGlobal::locale()->formatTime(QTime(12,34)) + " " + i18n("Event"), + i18n("Month view:"),&(KOPrefs::instance()->mMonthViewFont),topFrame); + topLayout->addWidget(monthViewFont->label(),i,0); + topLayout->addWidget(monthViewFont->preview(),i,1); + topLayout->addWidget(monthViewFont->button(),i,2); + ++i; + + + KPrefsWidFont *lVFont = + addWidFont(i18n("Event"),i18n("List View:"), + &(KOPrefs::instance()->mListViewFont),topFrame); + topLayout->addWidget(lVFont->label(),i,0); + topLayout->addWidget(lVFont->preview(),i,1); + topLayout->addWidget(lVFont->button(),i,2); + ++i; + + + tVFont = + addWidFont(i18n("ToDo"),i18n("ToDoView:"), + &(KOPrefs::instance()->mTodoViewFont),topFrame); + topLayout->addWidget(tVFont->label(),i,0); + topLayout->addWidget(tVFont->preview(),i,1); + topLayout->addWidget(tVFont->button(),i,2); + ++i; + + + tVFont = + addWidFont(i18n("Today"),i18n("JournalView:"), + &(KOPrefs::instance()->mJornalViewFont),topFrame); + topLayout->addWidget(tVFont->label(),i,0); + topLayout->addWidget(tVFont->preview(),i,1); + topLayout->addWidget(tVFont->button(),i,2); + ++i; + + + + + topLayout->setColStretch(1,1); + topLayout->setRowStretch(4,1); + + + + +} + +void KOPrefsDialog::setupColorsTab() +{ + QFrame *topFrame = addPage(i18n("Colors"),0,0); + // DesktopIcon("colorize",KIcon::SizeMedium)); + + QGridLayout *topLayout = new QGridLayout(topFrame,5,2); + // topLayout->setSpacing(spacingHint()); + // topLayout->setMargin(marginHint()); + + topLayout->setSpacing(2); + topLayout->setMargin(3); + + int ii = 1; + QGroupBox *categoryGroup ; + + categoryGroup = new QGroupBox(1,Vertical,i18n("Categories"), + topFrame); + topLayout->addMultiCellWidget(categoryGroup,0,0,0,1); + + mCategoryCombo = new QComboBox(categoryGroup); + mCategoryCombo->insertStringList(KOPrefs::instance()->mCustomCategories); + connect(mCategoryCombo,SIGNAL(activated(int)),SLOT(updateCategoryColor())); + + mCategoryButton = new KColorButton(categoryGroup); + connect(mCategoryButton,SIGNAL(changed(const QColor &)),SLOT(setCategoryColor())); + updateCategoryColor(); + + + // Holiday Color + + KPrefsWidColor *holidayColor = + addWidColor(i18n("Holiday color:"), + &(KOPrefs::instance()->mHolidayColor),topFrame); + topLayout->addWidget(holidayColor->label(),ii,0); + topLayout->addWidget(holidayColor->button(),ii++,1); + + // Highlight Color + KPrefsWidColor *highlightColor = + addWidColor(i18n("Highlight color:"), + &(KOPrefs::instance()->mHighlightColor),topFrame); + topLayout->addWidget(highlightColor->label(),ii,0); + topLayout->addWidget(highlightColor->button(),ii++,1); + + // Event color + KPrefsWidColor *eventColor = + addWidColor(i18n("Default event color:"), + &(KOPrefs::instance()->mEventColor),topFrame); + topLayout->addWidget(eventColor->label(),ii,0); + topLayout->addWidget(eventColor->button(),ii++,1); + + // agenda view background color + KPrefsWidColor *agendaBgColor = + addWidColor(i18n("Agenda view background color:"), + &(KOPrefs::instance()->mAgendaBgColor),topFrame); + topLayout->addWidget(agendaBgColor->label(),ii,0); + topLayout->addWidget(agendaBgColor->button(),ii++,1); + + // working hours color + KPrefsWidColor *workingHoursColor = + addWidColor(i18n("Working hours color:"), + &(KOPrefs::instance()->mWorkingHoursColor),topFrame); + topLayout->addWidget(workingHoursColor->label(),ii,0); + topLayout->addWidget(workingHoursColor->button(),ii++,1); + + KPrefsWidBool *sb = + addWidBool(i18n("Use colors for application:"), + &(KOPrefs::instance()->mUseAppColors),topFrame); + topLayout->addMultiCellWidget(sb->checkBox(), ii, ii, 0,1 ); + + ii++; + KPrefsWidColor * workingHoursColor1 = + addWidColor(i18n("Buttons, menus, etc.:"), + &(KOPrefs::instance()->mAppColor1),topFrame); + topLayout->addWidget(workingHoursColor1->label(),ii,0); + topLayout->addWidget(workingHoursColor1->button(),ii++,1); + + KPrefsWidColor * workingHoursColor2 = + addWidColor(i18n("Frames, labels, etc.:"), + &(KOPrefs::instance()->mAppColor2),topFrame); + topLayout->addWidget(workingHoursColor2->label(),ii,0); + topLayout->addWidget(workingHoursColor2->button(),ii++,1); + + + +} + +void KOPrefsDialog::setCategoryColor() +{ + mCategoryDict.replace(mCategoryCombo->currentText(), new QColor(mCategoryButton->color())); +} + +void KOPrefsDialog::updateCategoryColor() +{ + QString cat = mCategoryCombo->currentText(); + QColor *color = mCategoryDict.find(cat); + if (!color) { + color = KOPrefs::instance()->categoryColor(cat); + } + if (color) { + mCategoryButton->setColor(*color); + } +} + +void KOPrefsDialog::setupPrinterTab() +{ + mPrinterTab = addPage(i18n("Printing"),0, + DesktopIcon("fileprint",KIcon::SizeMedium)); + + QGridLayout *topLayout = new QGridLayout(mPrinterTab,5,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + + topLayout->setRowStretch(4,1); +} + +void KOPrefsDialog::setupGroupSchedulingTab() +{ +#if 0 + QFrame *topFrame = addPage(i18n("Group Scheduling"),0, + DesktopIcon("personal",KIcon::SizeMedium)); + + QGridLayout *topLayout = new QGridLayout(topFrame,6,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + +#if 0 + KPrefsWidRadios *schedulerGroup = + addWidRadios(i18n("Scheduler Mail Client"),&(KOPrefs::instance()->mIMIPScheduler), + topFrame); + schedulerGroup->addRadio("Dummy"); // Only for debugging + schedulerGroup->addRadio(i18n("Mail client")); + + topLayout->addMultiCellWidget(schedulerGroup->groupBox(),0,0,0,1); +#endif + + KPrefsWidRadios *sendGroup = + addWidRadios(i18n("Scheduler Mails Should Be"),&(KOPrefs::instance()->mIMIPSend), + topFrame); + sendGroup->addRadio(i18n("Send to outbox")); + sendGroup->addRadio(i18n("Send directly")); + + topLayout->addMultiCellWidget(sendGroup->groupBox(),1,1,0,1); + + topLayout->addMultiCellWidget(new QLabel(i18n("Additional email addresses:"),topFrame),2,2,0,1); + mAMails = new QListView(topFrame); + mAMails->addColumn(i18n("Email"),300); + topLayout->addMultiCellWidget(mAMails,3,3,0,1); + + topLayout->addWidget(new QLabel(i18n("Additional email address:"),topFrame),4,0); + aEmailsEdit = new QLineEdit(topFrame); + aEmailsEdit->setEnabled(false); + topLayout->addWidget(aEmailsEdit,4,1); + + QPushButton *add = new QPushButton(i18n("New"),topFrame,"new"); + topLayout->addWidget(add,5,0); + QPushButton *del = new QPushButton(i18n("Remove"),topFrame,"remove"); + topLayout->addWidget(del,5,1); + + //topLayout->setRowStretch(2,1); + connect(add, SIGNAL( clicked() ), this, SLOT(addItem()) ); + connect(del, SIGNAL( clicked() ), this, SLOT(removeItem()) ); + connect(aEmailsEdit,SIGNAL( textChanged(const QString&) ), this,SLOT(updateItem())); + connect(mAMails,SIGNAL(selectionChanged(QListViewItem *)),SLOT(updateInput())); +#endif +} + +void KOPrefsDialog::setupGroupAutomationTab() +{ + return; + QFrame *topFrame = addPage(i18n("Group Automation"),0, + DesktopIcon("personal",KIcon::SizeMedium)); + + QGridLayout *topLayout = new QGridLayout(topFrame,5,1); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + + KPrefsWidRadios *autoRefreshGroup = + addWidRadios(i18n("Auto Send Refresh"), + &(KOPrefs::instance()->mIMIPAutoRefresh),topFrame); + autoRefreshGroup->addRadio(i18n("Never")); + autoRefreshGroup->addRadio(i18n("If attendee is in addressbook")); + //autoRefreshGroup->addRadio(i18n("selected emails")); + topLayout->addMultiCellWidget(autoRefreshGroup->groupBox(),0,0,0,0); + + KPrefsWidRadios *autoInsertGroup = + addWidRadios(i18n("Auto Insert IMIP Replies"), + &(KOPrefs::instance()->mIMIPAutoInsertReply),topFrame); + autoInsertGroup->addRadio(i18n("Never")); + autoInsertGroup->addRadio(i18n("If attendee is in addressbook")); + //autoInsertGroup->addRadio(i18n("selected emails")); + topLayout->addMultiCellWidget(autoInsertGroup->groupBox(),1,1,0,0); + + KPrefsWidRadios *autoRequestGroup = + addWidRadios(i18n("Auto Insert IMIP Requests"), + &(KOPrefs::instance()->mIMIPAutoInsertRequest),topFrame); + autoRequestGroup->addRadio(i18n("Never")); + autoRequestGroup->addRadio(i18n("If organizer is in addressbook")); + //autoInsertGroup->addRadio(i18n("selected emails")); + topLayout->addMultiCellWidget(autoRequestGroup->groupBox(),2,2,0,0); + + KPrefsWidRadios *autoFreeBusyGroup = + addWidRadios(i18n("Auto Send FreeBusy Information"), + &(KOPrefs::instance()->mIMIPAutoFreeBusy),topFrame); + autoFreeBusyGroup->addRadio(i18n("Never")); + autoFreeBusyGroup->addRadio(i18n("If requested from an email in addressbook")); + //autoFreeBusyGroup->addRadio(i18n("selected emails")); + topLayout->addMultiCellWidget(autoFreeBusyGroup->groupBox(),3,3,0,0); + + KPrefsWidRadios *autoFreeBusyReplyGroup = + addWidRadios(i18n("Auto Save FreeBusy Replies"), + &(KOPrefs::instance()->mIMIPAutoFreeBusyReply),topFrame); + autoFreeBusyReplyGroup->addRadio(i18n("Never")); + autoFreeBusyReplyGroup->addRadio(i18n("If attendee is in addressbook")); + //autoFreeBusyGroup->addRadio(i18n("selected emails")); + topLayout->addMultiCellWidget(autoFreeBusyReplyGroup->groupBox(),4,4,0,0); +} + +void KOPrefsDialog::showPrinterTab() +{ + showPage(pageIndex(mPrinterTab)); +} + + +void KOPrefsDialog::setCombo(QComboBox *combo, const QString & text, + const QStringList *tags) +{ + if (tags) { + int i = tags->findIndex(text); + if (i > 0) combo->setCurrentItem(i); + } else { + for(int i=0;i<combo->count();++i) { + if (combo->text(i) == text) { + combo->setCurrentItem(i); + break; + } + } + } +} + +void KOPrefsDialog::usrReadConfig() +{ + mNameEdit->setText(KOPrefs::instance()->fullName()); + mEmailEdit->setText(KOPrefs::instance()->email()); + + mAutoSaveIntervalSpin->setValue(KOPrefs::instance()->mAutoSaveInterval); + QDate current ( 2001, 1,1); + mStartDateSavingEdit->setDate(current.addDays(KOPrefs::instance()->mDaylightsavingStart-1)); + mEndDateSavingEdit->setDate(current.addDays(KOPrefs::instance()->mDaylightsavingEnd-1)); + setCombo(mTimeZoneCombo,i18n(KOPrefs::instance()->mTimeZoneId)); + //mTimezoneOffsetSpin->setValue( KOPrefs::instance()->mTimeZoneOffset); + mStartTimeSpin->setValue(KOPrefs::instance()->mStartTime); + mDefaultDurationSpin->setValue(KOPrefs::instance()->mDefaultDuration); + mAlarmTimeCombo->setCurrentItem(KOPrefs::instance()->mAlarmTime); + // if (KOPrefs::instance()->mAllDaySize > 47 ) + // KOPrefs::instance()->mAllDaySize = KOPrefs::instance()->mAllDaySize/2; + //mHourSizeSlider->setValue(KOPrefs::instance()->mAllDaySize); + + mNextXDaysSpin->setValue(KOPrefs::instance()->mNextXDays); + mWhatsNextSpin->setValue(KOPrefs::instance()->mWhatsNextDays); + mPrioSpin->setValue(KOPrefs::instance()->mWhatsNextPrios); + // mAMails->clear(); + // for ( QStringList::Iterator it = KOPrefs::instance()->mAdditionalMails.begin(); +// it != KOPrefs::instance()->mAdditionalMails.end(); ++it ) { +// QListViewItem *item = new QListViewItem(mAMails); +// item->setText(0,*it); +// mAMails->insertItem(item); +// } + + // mRemoteIPEdit->setText(KOPrefs::instance()->mRemoteIP); + //mRemoteUser->setText(KOPrefs::instance()->mRemoteUser); + //mRemotePassWd->setText(KOPrefs::instance()->mRemotePassWd); + //mRemoteFile->setText(KOPrefs::instance()->mRemoteFile); + + //that soundmLocalTempFile->setText(KOPrefs::instance()->mLocalTempFile); + mDefaultAlarmFile->setText(KOPrefs::instance()->mDefaultAlarmFile); + QString dummy = KOPrefs::instance()->mUserDateFormatLong; + mUserDateFormatLong->setText(dummy.replace( QRegExp("K"), QString(",") )); + dummy = KOPrefs::instance()->mUserDateFormatShort; + mUserDateFormatShort->setText(dummy.replace( QRegExp("K"), QString(",") )); + updateCategories(); + mAlarmPlayBeeps->setValue(KOPrefs::instance()->mAlarmPlayBeeps ); + mAlarmSuspendTime->setValue(KOPrefs::instance()->mAlarmSuspendTime ); + mAlarmSuspendCount->setValue(KOPrefs::instance()->mAlarmSuspendCount ); + mAlarmBeepInterval->setValue(KOPrefs::instance()->mAlarmBeepInterval ); +} + + +void KOPrefsDialog::usrWriteConfig() +{ + + // KOPrefs::instance()->mRemoteIP = mRemoteIPEdit->text(); + //KOPrefs::instance()->mRemoteUser = mRemoteUser->text(); + //KOPrefs::instance()->mRemotePassWd = mRemotePassWd->text(); + //KOPrefs::instance()->mRemoteFile= mRemoteFile->text(); + //KOPrefs::instance()->mLocalTempFile =mLocalTempFile->text(); + KOPrefs::instance()->mDefaultAlarmFile =mDefaultAlarmFile->text(); + + KOPrefs::instance()->mUserDateFormatShort = mUserDateFormatShort->text().replace( QRegExp(","), QString("K") ); + KOPrefs::instance()->mUserDateFormatLong = mUserDateFormatLong->text().replace( QRegExp(","), QString("K") ); + KOPrefs::instance()->setFullName(mNameEdit->text()); + KOPrefs::instance()->setEmail(mEmailEdit->text()); + + KOPrefs::instance()->mAutoSaveInterval = mAutoSaveIntervalSpin->value(); + + KOPrefs::instance()->mTimeZoneId = mTimeZoneCombo->currentText(); + QDate date; + date = mStartDateSavingEdit->date(); + int sub = 0; + if ( QDate::leapYear( date.year() ) && date.dayOfYear() > 59 ) + sub = 1; + KOPrefs::instance()->mDaylightsavingStart = date.dayOfYear()-sub; + date = mEndDateSavingEdit->date(); + if ( QDate::leapYear( date.year() ) && date.dayOfYear() > 59 ) + sub = 1; + else + sub = 0; + KOPrefs::instance()->mDaylightsavingEnd = date.dayOfYear()-sub; + // KOPrefs::instance()->mTimeZoneOffset = mTimezoneOffsetSpin->value(); + + KOPrefs::instance()->mStartTime = mStartTimeSpin->value(); + KOPrefs::instance()->mDefaultDuration = mDefaultDurationSpin->value(); + KOPrefs::instance()->mAlarmTime = mAlarmTimeCombo->currentItem(); + + //KOPrefs::instance()->mAllDaySize = mHourSizeSlider->value(); + + QDictIterator<QColor> it(mCategoryDict); + while (it.current()) { + KOPrefs::instance()->setCategoryColor(it.currentKey(),*it.current()); + ++it; + } + + KOPrefs::instance()->mNextXDays = mNextXDaysSpin->value(); + KOPrefs::instance()->mWhatsNextDays = mWhatsNextSpin->value(); + KOPrefs::instance()->mWhatsNextPrios = mPrioSpin->value(); + + KOPrefs::instance()->mAdditionalMails.clear(); + // QListViewItem *item; + // item = mAMails->firstChild(); + // while (item) + // { + // KOPrefs::instance()->mAdditionalMails.append( item->text(0) ); + // item = item->nextSibling(); + // } + KOPrefs::instance()->mAlarmPlayBeeps = mAlarmPlayBeeps->value(); + KOPrefs::instance()->mAlarmSuspendTime = mAlarmSuspendTime->value() ; + KOPrefs::instance()->mAlarmSuspendCount= mAlarmSuspendCount->value() ; + KOPrefs::instance()->mAlarmBeepInterval= mAlarmBeepInterval->value() ; + +} + +void KOPrefsDialog::updateCategories() +{ + mCategoryCombo->clear(); + mCategoryDict.clear(); + mCategoryCombo->insertStringList(KOPrefs::instance()->mCustomCategories); + updateCategoryColor(); +} + +void KOPrefsDialog::warningGroupScheduling() +{ + warningExperimental(mEnableGroupScheduling->checkBox()->isChecked()); +} + +void KOPrefsDialog::warningProjectView() +{ + warningExperimental(mEnableProjectView->checkBox()->isChecked()); +} + +void KOPrefsDialog::warningExperimental(bool on) +{ + if (on) { + KMessageBox::information(this,i18n("This is an experimental feature. " + "It may not work, it may do nothing useful and it may cause data loss. " + "Use with care.\n" + "You have to restart KOrganizer for this setting to take effect.")); + } else { + KMessageBox::information(this, + i18n("You have to restart KOrganizer for this setting to take effect.")); + } +} + +void KOPrefsDialog::toggleEmailSettings(bool on) +{ + if (on) { + mEmailEdit->setEnabled(false); + mNameEdit->setEnabled(false); + mEmailLabel->setEnabled(false); + mNameLabel->setEnabled(false); + + KEMailSettings settings; + mNameEdit->setText(settings.getSetting(KEMailSettings::RealName)); + mEmailEdit->setText(settings.getSetting(KEMailSettings::EmailAddress)); + } else { + mEmailEdit->setEnabled(true); + mNameEdit->setEnabled(true); + mEmailLabel->setEnabled(true); + mNameLabel->setEnabled(true); + } +} + +void KOPrefsDialog::addItem() +{ + // aEmailsEdit->setEnabled(true); +// QListViewItem *item = new QListViewItem(mAMails); +// mAMails->insertItem(item); +// mAMails->setSelected(item,true); +// aEmailsEdit->setText(i18n("(EmptyEmail)")); +} + +void KOPrefsDialog::removeItem() +{ +// QListViewItem *item; +// item = mAMails->selectedItem(); +// if (!item) return; +// mAMails->takeItem(item); +// item = mAMails->selectedItem(); +// if (!item) { +// aEmailsEdit->setText(""); +// aEmailsEdit->setEnabled(false); +// } +// if (mAMails->childCount() == 0) { +// aEmailsEdit->setEnabled(false); +// } +} + +void KOPrefsDialog::updateItem() +{ + // QListViewItem *item; +// item = mAMails->selectedItem(); +// if (!item) return; +// item->setText(0,aEmailsEdit->text()); +} + +void KOPrefsDialog::updateInput() +{ +// QListViewItem *item; +// item = mAMails->selectedItem(); +// if (!item) return; +// aEmailsEdit->setEnabled(true); +// aEmailsEdit->setText(item->text(0)); +} +void KOPrefsDialog::updateTimezoneOffset( int index ) +{ + /* + qDebug("updateTimezoneOffset %d ", index); + if ( index < 24 ) { + mTimezoneOffsetSpin->setEnabled ( false ); + mTimezoneOffsetSpin->setValue( ( index-11 ) * 60 ); + + + } else { + if ( index == 24 ) { + mTimezoneOffsetSpin->setEnabled ( true ); + mTimezoneOffsetSpin->setValue( KOPrefs::instance()->mTimeZoneOffset); + + } else { + mTimezoneOffsetSpin->setEnabled ( false ); + mTimezoneOffsetSpin->setValue( 0 ); + } + } + */ +} + +void KOPrefsDialog::setupTimeZoneTab() +{ + QFrame *topFrame = addPage(i18n("Time Zone"),0,0); + // DesktopIcon("clock",KIcon::SizeMedium)); + + QGridLayout *topLayout = new QGridLayout(topFrame,5,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + + QHBox *timeZoneBox = new QHBox( topFrame ); + topLayout->addMultiCellWidget( timeZoneBox, 0, 0, 0, 1 ); + + new QLabel( i18n("Timezone:"), timeZoneBox ); + mTimeZoneCombo = new QComboBox( timeZoneBox ); + if ( QApplication::desktop()->width() < 300 ) { + mTimeZoneCombo->setMaximumWidth(150); + } + + QStringList list; + list = KGlobal::locale()->timeZoneList(); + mTimeZoneCombo->insertStringList(list); + + // find the currently set time zone and select it + QString sCurrentlySet = KOPrefs::instance()->mTimeZoneId; + int nCurrentlySet = 11; + for (int i = 0; i < mTimeZoneCombo->count(); i++) + { + if (mTimeZoneCombo->text(i) == sCurrentlySet) + { + nCurrentlySet = i; + break; + } + } + mTimeZoneCombo->setCurrentItem(nCurrentlySet); + int iii = 1; + KPrefsWidBool *sb = + addWidBool(i18n("Timezone has daylight saving"), + &(KOPrefs::instance()->mUseDaylightsaving),topFrame); + topLayout->addMultiCellWidget(sb->checkBox(), iii,iii,0,1); + ++iii; + QLabel* lab = new QLabel( i18n("Actual start/end is the\nsunday before this date."), topFrame ); + topLayout->addMultiCellWidget(lab, iii,iii,0,1); + ++iii; + lab = new QLabel( i18n("The year in the date is ignored."), topFrame ); + topLayout->addMultiCellWidget(lab, iii,iii,0,1); + ++iii; + lab = new QLabel( i18n("Daylight start:"), topFrame ); + topLayout->addWidget(lab, iii,0); + mStartDateSavingEdit = new KDateEdit(topFrame); + topLayout->addWidget(mStartDateSavingEdit, iii,1); + ++iii; + + lab = new QLabel( i18n("Daylight end:"), topFrame ); + topLayout->addWidget(lab, iii,0); + mEndDateSavingEdit = new KDateEdit(topFrame); + topLayout->addWidget(mEndDateSavingEdit, iii,1); + ++iii; + QDate current ( 2001, 1,1); + mStartDateSavingEdit->setDate(current.addDays(KOPrefs::instance()->mDaylightsavingStart-1)); + mEndDateSavingEdit->setDate(current.addDays(KOPrefs::instance()->mDaylightsavingEnd-1)); + + +} + diff --git a/korganizer/koprefsdialog.h b/korganizer/koprefsdialog.h new file mode 100644 index 0000000..fd651d0 --- a/dev/null +++ b/korganizer/koprefsdialog.h @@ -0,0 +1,161 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOPREFSDIALOG_H +#define _KOPREFSDIALOG_H + +#include <qframe.h> +#include <qdict.h> +#include <qcolor.h> +#include <qlistview.h> + +#include <kdialogbase.h> + +#include <libkdepim/kprefsdialog.h> +#include <libkdepim/kdateedit.h> + +class KColorButton; +class QSpinBox; +class QSlider; +class KURLRequester; +class QComboBox; +class QLineEdit; +class QStringList; + +/** Dialog to change the korganizer configuration. + */ +class KOPrefsDialog : public KPrefsDialog +{ + Q_OBJECT + public: + /** Initialize dialog and pages */ + KOPrefsDialog(QWidget *parent=0,char *name=0,bool modal=false); + ~KOPrefsDialog(); + + public slots: + void showPrinterTab(); + + /** Update controls for categories */ + void updateCategories(); + void showSyncPage(); + protected slots: + void selectSoundFile(); + void setCategoryColor(); + void updateCategoryColor(); + void updateTimezoneOffset( int ); + + + void warningExperimental(bool on); + void warningGroupScheduling(); + void warningProjectView(); + + void toggleEmailSettings(bool); + + //additional emails + void addItem(); + void removeItem(); + void updateItem(); + void updateInput(); + + protected: + void usrReadConfig(); + void usrWriteConfig(); + + void setupMainTab(); + void setupTimeTab(); + void setupTimeZoneTab(); + void setupLocaleTab(); + void setupLocaleDateTab(); + void setupFontsTab(); + void setupColorsTab(); + void setupViewsTab(); + void setupDisplayTab(); + void setupPrinterTab(); + void setupGroupSchedulingTab(); + void setupGroupAutomationTab(); + void setupSyncTab(); + void setupSyncAlgTab(); + + void setCombo(QComboBox *combo,const QString & text, const QStringList *tags = 0); + + + private: + KPrefsWidBool *mEnableGroupScheduling; + KPrefsWidBool *mEnableProjectView; + + QFrame *mPrinterTab; + + QLineEdit *nameEdit; + QLineEdit *emailEdit; + + QComboBox *timeCombo; + QComboBox *tzCombo; + + // widgets holding preferences data + QLineEdit *mNameEdit; + QLineEdit *mEmailEdit; + QLabel *mNameLabel; + QLabel *mEmailLabel; + QLineEdit *mAdditionalEdit; + QSpinBox *mAutoSaveIntervalSpin; + QSpinBox *mPrioSpin; + // QListView *mAMails; + QLineEdit *aEmailsEdit; + + QComboBox *mTimeZoneCombo; + QStringList tzonenames; + QSpinBox *mStartTimeSpin; + QSpinBox *mDefaultDurationSpin; + QComboBox *mAlarmTimeCombo; + + QComboBox *mCategoryCombo; + KColorButton *mCategoryButton; + QDict<QColor> mCategoryDict; + + QSlider *mHourSizeSlider; + + QSpinBox *mNextXDaysSpin; + QSpinBox *mWhatsNextSpin; + + QLineEdit * mRemoteIPEdit; + QLineEdit * mRemoteUser; + QLineEdit * mRemotePassWd; + QLineEdit * mRemoteFile; + QLineEdit * mLocalTempFile; + QWidget* mSetupSyncAlgTab; + QLineEdit * mUserDateFormatLong; + QLineEdit * mUserDateFormatShort; + + QSpinBox *mTimezoneOffsetSpin; + QSpinBox *mDaylightsavingStart; + QSpinBox *mDaylightsavingEnd; + KDateEdit* mStartDateSavingEdit; + KDateEdit* mEndDateSavingEdit; + QSpinBox * mAlarmPlayBeeps; + QSpinBox * mAlarmSuspendTime; + QSpinBox * mAlarmSuspendCount; + QSpinBox * mAlarmBeepInterval; + + QLineEdit * mDefaultAlarmFile; +}; + +#endif diff --git a/korganizer/koprefsdialog.moc b/korganizer/koprefsdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koprefsdialog.moc diff --git a/korganizer/korganizer.desktop b/korganizer/korganizer.desktop new file mode 100644 index 0000000..23672b2 --- a/dev/null +++ b/korganizer/korganizer.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment = KO/PI +Display = 640x480/144dpi,480x640/144dpi +Exec = kopi +Icon = kdepim/korganizer/korganizer +Name = KO/Pi +Type = Application +CanFastload = 1 diff --git a/korganizer/korganizer.pro b/korganizer/korganizer.pro new file mode 100644 index 0000000..fe2250e --- a/dev/null +++ b/korganizer/korganizer.pro @@ -0,0 +1,172 @@ +TEMPLATE = app +CONFIG = qt warn_on +TARGET = kopi +OBJECTS_DIR = _obj/ +MOC_DIR = _moc +DESTDIR= ../bin + +include( ../variables.pri ) + +INCLUDEPATH += ../microkde ../ interfaces ../microkde/kdecore ../microkde/kdeui ../microkde/kio/kfile +#../qtcompat +DEFINES += KORG_NODND KORG_NOPLUGINS KORG_NOARCHIVE KORG_NOMAIL +DEFINES += KORG_NODCOP KORG_NOKALARMD KORG_NORESOURCEVIEW KORG_NOSPLITTER +#KORG_NOPRINTER KORG_NOKABC +DEFINES += KORG_NOLVALTERNATION +DEFINES += DESKTOP_VERSION +unix : { +LIBS += ../bin/libmicrokdepim.so +LIBS += ../bin/libmicrokcal.so +LIBS += ../bin/libmicrokde.so +LIBS += ../bin/libmicrokabc.so +LIBS += -lldap +OBJECTS_DIR = obj/unix +MOC_DIR = moc/unix +} +win32: { +DEFINES += _WIN32_ +LIBS += ../bin/microkdepim.lib +LIBS += ../bin/microkcal.lib +LIBS += ../bin/microkde.lib +LIBS += ../bin/microkabc.lib +LIBS += ../libical/lib/ical.lib +LIBS += ../libical/lib/icalss.lib +QMAKE_LINK += /NODEFAULTLIB:LIBC +OBJECTS_DIR = obj/win +MOC_DIR = moc/win +} + + +INTERFACES = kofilterview_base.ui +# filteredit_base.ui + +# kdateedit.h \ + +HEADERS = \ + filteredit_base.h \ + alarmclient.h \ + calendarview.h \ + customlistviewitem.h \ + datenavigator.h \ + docprefs.h \ + filtereditdialog.h \ + incomingdialog.h \ + incomingdialog_base.h \ + interfaces/korganizer/baseview.h \ + interfaces/korganizer/calendarviewbase.h \ + journalentry.h \ + kdatenavigator.h \ + koagenda.h \ + koagendaitem.h \ + koagendaview.h \ + kocounterdialog.h \ + kodaymatrix.h \ + kodialogmanager.h \ + koeditordetails.h \ + koeditorgeneral.h \ + koeditorgeneralevent.h \ + koeditorgeneraltodo.h \ + koeditorrecurrence.h \ + koeventeditor.h \ + koeventpopupmenu.h \ + koeventview.h \ + koeventviewer.h \ + koeventviewerdialog.h \ + kofilterview.h \ + koglobals.h \ + koincidenceeditor.h \ + kojournalview.h \ + kolistview.h \ + kolocationbox.h \ + komonthview.h \ + koprefs.h \ + koprefsdialog.h \ + kosyncprefsdialog.h \ + kotimespanview.h \ + kotodoeditor.h \ + kotodoview.h \ + kotodoviewitem.h \ + koviewmanager.h \ + kowhatsnextview.h \ + ktimeedit.h \ + lineview.h \ + mainwindow.h \ + navigatorbar.h \ + outgoingdialog.h \ + outgoingdialog_base.h \ + publishdialog.h \ + publishdialog_base.h \ + savetemplatedialog.h \ + searchdialog.h \ + simplealarmclient.h \ + statusdialog.h \ + timeline.h \ + timespanview.h \ + version.h \ + ../kalarmd/alarmdialog.h + +SOURCES = \ +filteredit_base.cpp \ + calendarview.cpp \ + datenavigator.cpp \ + docprefs.cpp \ + filtereditdialog.cpp \ + incomingdialog.cpp \ + incomingdialog_base.cpp \ + journalentry.cpp \ + kdatenavigator.cpp \ + koagenda.cpp \ + koagendaitem.cpp \ + koagendaview.cpp \ + kocounterdialog.cpp \ + kodaymatrix.cpp \ + kodialogmanager.cpp \ + koeditordetails.cpp \ + koeditorgeneral.cpp \ + koeditorgeneralevent.cpp \ + koeditorgeneraltodo.cpp \ + koeditorrecurrence.cpp \ + koeventeditor.cpp \ + koeventpopupmenu.cpp \ + koeventview.cpp \ + koeventviewer.cpp \ + koeventviewerdialog.cpp \ + kofilterview.cpp \ + koglobals.cpp \ + koincidenceeditor.cpp \ + kojournalview.cpp \ + kolistview.cpp \ + kolocationbox.cpp \ + komonthview.cpp \ + koprefs.cpp \ + koprefsdialog.cpp \ + kosyncprefsdialog.cpp \ + kotimespanview.cpp \ + kotodoeditor.cpp \ + kotodoview.cpp \ + kotodoviewitem.cpp \ + koviewmanager.cpp \ + kowhatsnextview.cpp \ + ktimeedit.cpp \ + lineview.cpp \ + main.cpp \ + mainwindow.cpp \ + navigatorbar.cpp \ + outgoingdialog.cpp \ + outgoingdialog_base.cpp \ + publishdialog.cpp \ + publishdialog_base.cpp \ + savetemplatedialog.cpp \ + searchdialog.cpp \ + simplealarmclient.cpp \ + statusdialog.cpp \ + timeline.cpp \ + timespanview.cpp \ + ../kalarmd/alarmdialog.cpp + +HEADERS += calprintbase.h calprinter.h calprintplugins.h cellitem.h +INTERFACES += calprintdayconfig_base.ui \ + calprintmonthconfig_base.ui \ + calprinttodoconfig_base.ui \ + calprintweekconfig_base.ui +SOURCES += calprintbase.cpp calprinter.cpp calprintplugins.cpp cellitem.cpp diff --git a/korganizer/korganizer.pro.back b/korganizer/korganizer.pro.back new file mode 100644 index 0000000..8d23d66 --- a/dev/null +++ b/korganizer/korganizer.pro.back @@ -0,0 +1,133 @@ +TEMPLATE = app +CONFIG = qt warn_on release +TARGET = korganizer +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc +DESTDIR=$(QPEDIR)/bin +INCLUDEPATH += ../microkde ../qtcompat ../ interfaces +DEFINES += KORG_NODND KORG_NOPLUGINS KORG_NOKABC KORG_NOARCHIVE KORG_NOMAIL +DEFINES += KORG_NOPRINTER KORG_NOSPLITTER KORG_NODCOP KORG_NOKALARMD +DEFINES += KORG_NOLVALTERNATION +LIBS += -lkdepim +LIBS += -lkcal +LIBS += -lmicrokde +LIBS += -lqtcompat +LIBS += -lqpe +INTERFACES = \ + filteredit_base.ui \ + kofilterview_base.ui \ + +HEADERS = \ + alarmclient.h \ + calendarview.h \ + customlistviewitem.h \ + datenavigator.h \ + docprefs.h \ + filtereditdialog.h \ + incomingdialog.h \ + incomingdialog_base.h \ + interfaces/korganizer/baseview.h \ + journalentry.h \ + kdateedit.h \ + kdatenavigator.h \ + koagenda.h \ + koagendaitem.h \ + koagendaview.h \ + kocounterdialog.h \ + kodaymatrix.h \ + kodialogmanager.h \ + koeditordetails.h \ + koeditorgeneral.h \ + koeditorgeneralevent.h \ + koeditorgeneraltodo.h \ + koeditorrecurrence.h \ + koeventeditor.h \ + koeventpopupmenu.h \ + koeventview.h \ + koeventviewer.h \ + koeventviewerdialog.h \ + kofilterview.h \ + koglobals.h \ + koincidenceeditor.h \ + kojournalview.h \ + kolistview.h \ + komonthview.h \ + koprefs.h \ + koprefsdialog.h \ + kotimespanview.h \ + kotodoeditor.h \ + kotodoview.h \ + kotodoviewitem.h \ + koviewmanager.h \ + kowhatsnextview.h \ + ktimeedit.h \ + lineview.h \ + mainwindow.h \ + navigatorbar.h \ + outgoingdialog.h \ + outgoingdialog_base.h \ + publishdialog.h \ + publishdialog_base.h \ + savetemplatedialog.h \ + searchdialog.h \ + simplealarmclient.h \ + statusdialog.h \ + timeline.h \ + timespanview.h \ + version.h \ + +SOURCES = \ + calendarview.cpp \ + datenavigator.cpp \ + docprefs.cpp \ + filtereditdialog.cpp \ + incomingdialog.cpp \ + incomingdialog_base.cpp \ + journalentry.cpp \ + kdatenavigator.cpp \ + koagenda.cpp \ + koagendaitem.cpp \ + koagendaview.cpp \ + kocounterdialog.cpp \ + kodaymatrix.cpp \ + kodialogmanager.cpp \ + koeditordetails.cpp \ + koeditorgeneral.cpp \ + koeditorgeneralevent.cpp \ + koeditorgeneraltodo.cpp \ + koeditorrecurrence.cpp \ + koeventeditor.cpp \ + koeventpopupmenu.cpp \ + koeventview.cpp \ + koeventviewer.cpp \ + koeventviewerdialog.cpp \ + kofilterview.cpp \ + koglobals.cpp \ + koincidenceeditor.cpp \ + kojournalview.cpp \ + kolistview.cpp \ + komonthview.cpp \ + koprefs.cpp \ + koprefsdialog.cpp \ + kotimespanview.cpp \ + kotodoeditor.cpp \ + kotodoview.cpp \ + kotodoviewitem.cpp \ + koviewmanager.cpp \ + kowhatsnextview.cpp \ + ktimeedit.cpp \ + lineview.cpp \ + main.cpp \ + mainwindow.cpp \ + navigatorbar.cpp \ + outgoingdialog.cpp \ + outgoingdialog_base.cpp \ + publishdialog.cpp \ + publishdialog_base.cpp \ + savetemplatedialog.cpp \ + searchdialog.cpp \ + simplealarmclient.cpp \ + statusdialog.cpp \ + timeline.cpp \ + timespanview.cpp \ + diff --git a/korganizer/korganizerE.pro b/korganizer/korganizerE.pro new file mode 100644 index 0000000..c379fac --- a/dev/null +++ b/korganizer/korganizerE.pro @@ -0,0 +1,151 @@ +TEMPLATE = app +CONFIG += qt warn_on +TARGET = kopi +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR=$(QPEDIR)/bin + +INCLUDEPATH += ../microkde ../microkde/kdecore ../microkde/kio/kfile ../microkde/kdeui ../qtcompat ../ interfaces ../kabc $(QPEDIR)/include +#../libkabcwrap +DEFINES += KORG_NODND KORG_NOPLUGINS KORG_NOARCHIVE KORG_NOMAIL +DEFINES += KORG_NOPRINTER KORG_NODCOP KORG_NOKALARMD KORG_NORESOURCEVIEW KORG_NOSPLITTER +DEFINES += KORG_NOLVALTERNATION +#KORG_NOKABC +LIBS += -lmicrokdepim +LIBS += -lmicrokcal +LIBS += -lmicrokde +LIBS += -lmicroqtcompat +LIBS += -lmicrokabc +#LIBS += -lmicrokabcwrap +LIBS += -lqpe +LIBS += -ljpeg +LIBS += $(QTOPIALIB) + + +INTERFACES = kofilterview_base.ui +#filteredit_base.ui + +HEADERS = \ + wordsgerman.h \ + filteredit_base.h \ + alarmclient.h \ + calendarview.h \ + customlistviewitem.h \ + datenavigator.h \ + docprefs.h \ + filtereditdialog.h \ + incomingdialog.h \ + incomingdialog_base.h \ + interfaces/korganizer/baseview.h \ + interfaces/korganizer/calendarviewbase.h \ + journalentry.h \ + kdateedit.h \ + kdatenavigator.h \ + koagenda.h \ + koagendaitem.h \ + koagendaview.h \ + kocounterdialog.h \ + kodaymatrix.h \ + kodialogmanager.h \ + koeditordetails.h \ + koeditorgeneral.h \ + koeditorgeneralevent.h \ + koeditorgeneraltodo.h \ + koeditorrecurrence.h \ + koeventeditor.h \ + koeventpopupmenu.h \ + koeventview.h \ + koeventviewer.h \ + koeventviewerdialog.h \ + kofilterview.h \ + koglobals.h \ + koincidenceeditor.h \ + kojournalview.h \ + kolistview.h \ + kolocationbox.h \ + komonthview.h \ + koprefs.h \ + koprefsdialog.h \ + kosyncprefsdialog.h \ + kotimespanview.h \ + kotodoeditor.h \ + kotodoview.h \ + kotodoviewitem.h \ + koviewmanager.h \ + kowhatsnextview.h \ + ktimeedit.h \ + lineview.h \ + mainwindow.h \ + navigatorbar.h \ + outgoingdialog.h \ + outgoingdialog_base.h \ + publishdialog.h \ + publishdialog_base.h \ + savetemplatedialog.h \ + searchdialog.h \ + simplealarmclient.h \ + statusdialog.h \ + timeline.h \ + timespanview.h \ + version.h \ + ../kalarmd/alarmdialog.h + +SOURCES = \ + filteredit_base.cpp \ + calendarview.cpp \ + datenavigator.cpp \ + docprefs.cpp \ + filtereditdialog.cpp \ + incomingdialog.cpp \ + incomingdialog_base.cpp \ + journalentry.cpp \ + kdatenavigator.cpp \ + koagenda.cpp \ + koagendaitem.cpp \ + koagendaview.cpp \ + kocounterdialog.cpp \ + kodaymatrix.cpp \ + kodialogmanager.cpp \ + koeditordetails.cpp \ + koeditorgeneral.cpp \ + koeditorgeneralevent.cpp \ + koeditorgeneraltodo.cpp \ + koeditorrecurrence.cpp \ + koeventeditor.cpp \ + koeventpopupmenu.cpp \ + koeventview.cpp \ + koeventviewer.cpp \ + koeventviewerdialog.cpp \ + kofilterview.cpp \ + koglobals.cpp \ + koincidenceeditor.cpp \ + kojournalview.cpp \ + kolistview.cpp \ + kolocationbox.cpp \ + komonthview.cpp \ + koprefs.cpp \ + koprefsdialog.cpp \ + kosyncprefsdialog.cpp \ + kotimespanview.cpp \ + kotodoeditor.cpp \ + kotodoview.cpp \ + kotodoviewitem.cpp \ + koviewmanager.cpp \ + kowhatsnextview.cpp \ + ktimeedit.cpp \ + lineview.cpp \ + main.cpp \ + mainwindow.cpp \ + navigatorbar.cpp \ + outgoingdialog.cpp \ + outgoingdialog_base.cpp \ + publishdialog.cpp \ + publishdialog_base.cpp \ + savetemplatedialog.cpp \ + searchdialog.cpp \ + simplealarmclient.cpp \ + statusdialog.cpp \ + timeline.cpp \ + timespanview.cpp \ + ../kalarmd/alarmdialog.cpp + diff --git a/korganizer/kosyncprefsdialog.cpp b/korganizer/kosyncprefsdialog.cpp new file mode 100644 index 0000000..2e051f2 --- a/dev/null +++ b/korganizer/kosyncprefsdialog.cpp @@ -0,0 +1,453 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2004 Lutz Rogowski <rogowski@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> +#include <qlabel.h> +#include <qgroupbox.h> +#include <qbuttongroup.h> +#include <qlineedit.h> +#include <qfont.h> +#include <qslider.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qcombobox.h> +#include <qvbox.h> +#include <qhbox.h> +#include <qspinbox.h> +#include <qdatetime.h> +#include <qcheckbox.h> +#include <qradiobutton.h> +#include <qpushbutton.h> +#include <qstrlist.h> +#include <qapplication.h> + +#include <kcolorbutton.h> +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> +#include <kfontdialog.h> +#include <kmessagebox.h> +#include <kcolordialog.h> +#include <kiconloader.h> +#include <kemailsettings.h> +#include <kstandarddirs.h> +#include <kfiledialog.h> +#include <kmessagebox.h> + +#include <kurlrequester.h> +#include <klineedit.h> +#include <libkdepim/ksyncprofile.h> + + +#include "koprefs.h" + +#include "kosyncprefsdialog.h" +#include "koglobals.h" +#include "kosyncprefsdialog.moc" + + +KOSyncPrefsDialog::KOSyncPrefsDialog(QWidget *parent, char *name, bool modal) : + KDialog(parent,name,true) +{ + + setCaption( i18n("Synchronization Preferences")); + + mSyncProfiles.setAutoDelete( true ); + setupSyncAlgTab(); +} + + +KOSyncPrefsDialog::~KOSyncPrefsDialog() +{ +} + +#include <qlayout.h> +#include <qscrollview.h> +void KOSyncPrefsDialog::setupSyncAlgTab() +{ + QLabel * lab; + //QFrame *page = addPage(i18n("Sync Prefs"),0,0); + QVBox * mainbox = new QVBox( this ); + QScrollView* sv = new QScrollView( mainbox ); + QHBoxLayout * lay = new QHBoxLayout( this ); + lay->addWidget( mainbox ); + QHBox * b_box = new QHBox( mainbox ); + + QPushButton* button = new QPushButton( i18n("Ok"), b_box ); + connect ( button, SIGNAL( clicked()), this, SLOT (slotOK() ) ); + button = new QPushButton( i18n("Cancel"), b_box ); + connect ( button, SIGNAL( clicked()), this, SLOT (reject() ) ); + //QBoxLayout * sl = new QVBoxLayout(this ); + //sl->addWidget ( sv ); + sv->setResizePolicy ( QScrollView::AutoOneFit ); + QFrame *topFrame = new QFrame ( sv ); + sv->addChild( topFrame ); + mSetupSyncAlgTab = topFrame; + QGridLayout *topLayout = new QGridLayout(topFrame,6,2); + topLayout->setSpacing(spacingHint()); + topLayout->setMargin(marginHint()); + + //lab = new QLabel(i18n("Sync settings not yet implemented. DO NOT USE!"), topFrame); + int iii = 0; + //topLayout->addMultiCellWidget(lab , iii,iii,0,1); + //++iii; + + mMyMachineName = new QLineEdit(topFrame); + lab = new QLabel(mMyMachineName, i18n("Local device name:"), topFrame); + topLayout->addWidget(lab ,iii,0); + topLayout->addWidget(mMyMachineName,iii,1); + ++iii; + + QHBox* buttonbox = new QHBox( topFrame); + topLayout->addMultiCellWidget(buttonbox, iii,iii,0,1); + ++iii; + button = new QPushButton( i18n("New profile"), buttonbox ); + connect ( button, SIGNAL( clicked()), this, SLOT (newProfile() ) ); + + button = new QPushButton( i18n("Clone profile"), buttonbox ); + connect ( button, SIGNAL( clicked()), this, SLOT ( cloneProfile() ) ); + + button = new QPushButton( i18n("Delete profile"), buttonbox ); + connect ( button, SIGNAL( clicked()), this, SLOT (deleteProfile() ) ); + + mProfileBox = new QComboBox(topFrame); + mProfileBox->setEditable ( true ); + connect ( mProfileBox, SIGNAL(activated ( int ) ), this, SLOT (profileChanged( int ) ) ); + connect ( mProfileBox, SIGNAL( textChanged ( const QString & ) ), this, SLOT (textChanged( const QString & ) ) ); + + lab = new QLabel(mProfileBox, i18n("Profile:"), topFrame); + topLayout->addWidget(lab ,iii,0); + topLayout->addWidget(mProfileBox, iii,1); + ++iii; + + mIncludeInRing = new QCheckBox( i18n("Include in multiple sync"), topFrame ); + topLayout->addMultiCellWidget(mIncludeInRing, iii,iii,0,1); + ++iii; + + mAskForPreferences = new QCheckBox( i18n("Ask for preferences before sync"), topFrame ); + topLayout->addMultiCellWidget(mAskForPreferences, iii,iii,0,1); + ++iii; + QButtonGroup* gr = new QButtonGroup ( 1, Qt::Horizontal, i18n("Sync preferences"), topFrame); + topLayout->addMultiCellWidget(gr, iii,iii,0,1); + ++iii; + loc = new QRadioButton ( i18n("Take local entry on conflict"), gr ); + rem = new QRadioButton ( i18n("Take remote entry on conflict"), gr ); + newest = new QRadioButton ( i18n("Take newest entry on conflict"), gr ); + ask = new QRadioButton ( i18n("Ask for every entry on conflict"), gr ); + f_loc= new QRadioButton ( i18n("Force: Take local entry always"), gr ); + f_rem = new QRadioButton ( i18n("Force: Take remote entry always"), gr ); + // both = new QRadioButton ( i18n("Take both on conflict"), gr ); + + mShowSummaryAfterSync = new QCheckBox( i18n("Show summary after sync"), topFrame ); + topLayout->addMultiCellWidget(mShowSummaryAfterSync, iii,iii,0,1); + ++iii; + + mWriteBackExisting= new QCheckBox( i18n("Write back existing entries only"), topFrame ); + topLayout->addMultiCellWidget(mWriteBackExisting, iii,iii,0,1); + ++iii; + + mWriteBackFile = new QCheckBox( i18n("Write back file"), topFrame ); + topLayout->addMultiCellWidget(mWriteBackFile, iii,iii,0,1); + ++iii; + + proGr = new QButtonGroup ( 1, Qt::Horizontal, i18n("Profile kind"), topFrame); + gr = proGr; + topLayout->addMultiCellWidget(gr, iii,iii,0,1); + ++iii; + mIsLocal = new QRadioButton ( i18n("Local file"), gr ); + mIsNotLocal = new QRadioButton ( i18n("Remote file (w down/upload command)"), gr ); + connect (mIsLocal, SIGNAL( toggled(bool)), this, SLOT (kindChanged(bool) ) ); + + localFileWidget = new QVBox( topFrame); + topLayout->addMultiCellWidget(localFileWidget, iii,iii,0,1); + ++iii; + QHBox* temphb = new QHBox( localFileWidget ); + lab = new QLabel( i18n("Local file:"), temphb); + mRemoteFile = new QLineEdit(localFileWidget); + + button = new QPushButton( i18n("Choose..."), temphb ); + connect ( button, SIGNAL( clicked()), this, SLOT ( chooseFile() ) ); + + + remoteFileWidget = new QVBox( topFrame); + topLayout->addMultiCellWidget(remoteFileWidget, iii,iii,0,1); + ++iii; + lab = new QLabel( i18n("Pre sync (download) command:"), remoteFileWidget); + mRemotePrecommand = new QLineEdit(remoteFileWidget); + + lab = new QLabel( i18n("Local temp file:"), remoteFileWidget); + mLocalTempFile = new QLineEdit(remoteFileWidget); + + + lab = new QLabel( i18n("Post sync (upload) command:"), remoteFileWidget); + mRemotePostcommand = new QLineEdit(remoteFileWidget); + + lab = new QLabel( i18n("Fill in default values for:"), remoteFileWidget); + temphb = new QHBox( remoteFileWidget ); + button = new QPushButton( i18n("ssh/scp"), temphb ); + connect ( button, SIGNAL( clicked()), this, SLOT (fillSSH() ) ); + button = new QPushButton( i18n("ftp"), temphb ); + connect ( button, SIGNAL( clicked()), this, SLOT (fillFTP() ) ); + lab = new QLabel( i18n("Hint: Use $PWD$ for placeholder of password!"), remoteFileWidget); + + +} +void KOSyncPrefsDialog::slotOK() +{ + if ( mMyMachineName->text() == "undefined" ) { + KMessageBox::error(this,i18n("Local device name undefined!\nPlease define device name!"),i18n("KO/Pi config error")); + return; + } + int i; + for (i = 0; i < mSyncProfileNames.count(); ++ i) { + if ( mSyncProfileNames.contains( mSyncProfileNames[i]) > 1 ) { + KMessageBox::error(this,i18n("Multiple profiles with same name!\nPlease use unique profile names!"),i18n("KO/Pi config error")); + return; + } + } + usrWriteConfig(); + QDialog::accept(); +} +void KOSyncPrefsDialog::accept() +{ + slotOK(); +} +void KOSyncPrefsDialog::chooseFile() +{ + QString fn =KOPrefs::instance()->mLastSyncedLocalFile; + + fn =KFileDialog:: getOpenFileName( fn, i18n("Sync filename(*.ics/*.vcs)"), this ); + if ( fn == "" ) + return; + mRemoteFile->setText( fn ); +} + +void KOSyncPrefsDialog::textChanged( const QString & s ) +{ + if ( mProfileBox->count() == 0 ) + return; + if ( currentSelection < 3 ) { + //KMessageBox::error(this,i18n("This profil name\ncannot be edited!\n"),i18n("KO/Pi config error")); + mProfileBox->blockSignals( true ); + mProfileBox->setCurrentItem(mProfileBox-> currentItem ()); + mProfileBox->blockSignals( false ); + return; + } + //qDebug("cur i %d ",mProfileBox-> currentItem () ); + mProfileBox->changeItem ( s, mProfileBox-> currentItem () ) ; + KSyncProfile* prof = mSyncProfiles.at(mProfileBox-> currentItem ()) ; + prof->setName( s ); + mSyncProfileNames[mProfileBox-> currentItem ()] = s; +} +void KOSyncPrefsDialog::profileChanged( int item ) +{ + //qDebug("KOSyncPrefsDialog::profileChanged %d ", item ); + KSyncProfile* prof; + saveProfile(); + currentSelection = item; + prof = mSyncProfiles.at(item) ; + mRemotePrecommand->setText(prof->getPreSyncCommand()); + mRemotePostcommand->setText(prof->getPostSyncCommand()); + mLocalTempFile->setText(prof->getLocalTempFile()); + mRemoteFile->setText(prof->getRemoteFileName()) ; + mShowSummaryAfterSync->setChecked( prof->getShowSummaryAfterSync()); + mAskForPreferences->setChecked( prof->getAskForPreferences()); + mWriteBackExisting->setChecked( prof->getWriteBackExisting() ); + mWriteBackFile->setChecked( prof->getWriteBackFile()); + mIncludeInRing->setChecked( prof->getIncludeInRingSync() ); + + switch ( prof->getSyncPrefs() ) { + case 0: + loc->setChecked( true); + break; + case 1: + rem->setChecked( true ); + break; + case 2: + newest->setChecked( true); + break; + case 3: + ask->setChecked( true); + break; + case 4: + f_loc->setChecked( true); + break; + case 5: + f_rem->setChecked( true); + break; + case 6: + //both->setChecked( true); + break; + default: + break; + } + mIsLocal->setChecked(prof->getIsLocalFileSync()) ; + mIsNotLocal->setChecked(!prof->getIsLocalFileSync()); + proGr->setEnabled( item > 2 ); + if ( item < 3 ) { + localFileWidget->setEnabled(false); + remoteFileWidget->setEnabled(false); + + } else + kindChanged( prof->getIsLocalFileSync() ); +} + +void KOSyncPrefsDialog::fillSSH() +{ + mRemotePrecommand->setText("scp zaurus@192.168.0.65:/home/zaurus/kdepim/apps/korganizer/mycalendar.ics /tmp/mycalendar.ics" ); + mLocalTempFile->setText("/tmp/mycalendar.ics" ); + mRemotePostcommand->setText("scp /tmp/mycalendar.ics zaurus@192.168.0.65:/home/zaurus/kdepim/apps/korganizer/mycalendar.ics" ); +} +void KOSyncPrefsDialog::fillFTP() +{ + mRemotePrecommand->setText("cd /tmp;ftp ftp://zaurus:a@192.168.0.65/kdepim/apps/korganizer/mycalendar.ics" ); + mLocalTempFile->setText("/tmp/mycalendar.ics" ); + mRemotePostcommand->setText("ftp -u ftp://zaurus:a@192.168.0.65/kdepim/apps/korganizer/mycalendar.ics /tmp/mycalendar.ics" ); + +} +void KOSyncPrefsDialog::kindChanged( bool b ) +{ + + localFileWidget->setEnabled(b); + remoteFileWidget->setEnabled(!b); + +} +void KOSyncPrefsDialog::deleteProfile() +{ + //qDebug("KOSyncPrefsDialog::deleteProfile() "); + if ( currentSelection >= 0 ) { + if ( currentSelection < 3 ) { + KMessageBox::error(this,i18n("This profil cannot be deleted!\n"),i18n("KO/Pi config error")); + return; + } + KSyncProfile* temp = mSyncProfiles.at(currentSelection); + mSyncProfiles.remove( temp ); + mSyncProfileNames.remove( mSyncProfileNames.at( currentSelection )); + insertProfiles(); + } +} + +void KOSyncPrefsDialog::saveProfile() +{ + KSyncProfile* prof; + if ( currentSelection >= 0 ) { + prof = mSyncProfiles.at(currentSelection) ; + prof->setPreSyncCommand( mRemotePrecommand->text()); + prof->setPostSyncCommand( mRemotePostcommand->text() ); + prof->setLocalTempFile( mLocalTempFile->text()); + prof->setRemoteFileName( mRemoteFile->text() ); + prof->setShowSummaryAfterSync( mShowSummaryAfterSync->isChecked() ); + prof->setAskForPreferences( mAskForPreferences->isChecked()); + prof->setWriteBackExisting(mWriteBackExisting->isChecked() ); + prof->setWriteBackFile( mWriteBackFile->isChecked()); + prof->setIncludeInRingSync( mIncludeInRing->isChecked() ); + int syncprefs = rem->isChecked()*1+newest->isChecked()*2+ ask->isChecked()*3+ f_loc->isChecked()*4+ f_rem->isChecked()*5 ;//+ both->isChecked()*6 ; + prof->setSyncPrefs( syncprefs); + prof->setIsLocalFileSync( mIsLocal->isChecked() ); + } + +} + +void KOSyncPrefsDialog::insertProfiles() +{ + int curItem = mProfileBox->currentItem(); + mProfileBox->blockSignals( true ); + mProfileBox->clear(); + mProfileBox->insertStringList (mSyncProfileNames ); + int item = mSyncProfileNames.count() -1; + if ( curItem >= 0 && mSyncProfileNames.count() > 0 && curItem < mSyncProfileNames.count() ) + mProfileBox->setCurrentItem( curItem ); + else if ( item >= 0 ) { + mProfileBox->setCurrentItem( item ); + } + currentSelection = -1; + if ( mSyncProfileNames.count() > 0 ) { + //qDebug(" profileChanged( mProfileBox->currentItem() "); + profileChanged( mProfileBox->currentItem() ); + currentSelection = mProfileBox->currentItem(); + } + mProfileBox->blockSignals( false ); +} + +void KOSyncPrefsDialog::addProfile ( KSyncProfile* temp ) +{ + saveProfile(); + mSyncProfiles.append( temp ); + mSyncProfileNames << temp->getName(); + insertProfiles(); + int last = mProfileBox->count() -1; + mProfileBox->blockSignals( true ); + mProfileBox->setCurrentItem( last ); + mProfileBox->blockSignals( false ); + profileChanged(last); +} +void KOSyncPrefsDialog::newProfile() +{ + addProfile ( new KSyncProfile () ); +} + +void KOSyncPrefsDialog::cloneProfile() +{ + if ( currentSelection >= 0 ) + addProfile (mSyncProfiles.at(currentSelection)->clone()) ; + else + newProfile(); +} + + +void KOSyncPrefsDialog::usrReadConfig() +{ + KConfig *config = KOGlobals::config(); + config->setGroup("SyncProfiles"); + mSyncProfileNames = KOPrefs::instance()->mSyncProfileNames; + int i; + KSyncProfile* temp ; + mSyncProfiles.clear(); + for ( i = 0; i < mSyncProfileNames.count();++i ) { + temp = new KSyncProfile (); + temp->setName( mSyncProfileNames[i] ); + temp->readConfig( config ); + mSyncProfiles.append( temp ); + } + insertProfiles(); + mMyMachineName->setText(KOPrefs::instance()->mLocalMachineName ); +} + + +void KOSyncPrefsDialog::usrWriteConfig() +{ + saveProfile(); + if ( currentSelection >= 0 ) + profileChanged(currentSelection); + KConfig *config = KOGlobals::config(); + config->setGroup("SyncProfiles"); + KSyncProfile* prof = mSyncProfiles.first(); + while ( prof ) { + prof->writeConfig(config); + prof = mSyncProfiles.next(); + } + KOPrefs::instance()->mSyncProfileNames = mSyncProfileNames; + KOPrefs::instance()->mLocalMachineName = mMyMachineName->text(); + config->writeEntry("SyncProfileNames",&mSyncProfileNames); +} + diff --git a/korganizer/kosyncprefsdialog.h b/korganizer/kosyncprefsdialog.h new file mode 100644 index 0000000..d2d8c6f --- a/dev/null +++ b/korganizer/kosyncprefsdialog.h @@ -0,0 +1,109 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOPREFSDIALOG_H +#define _KOPREFSDIALOG_H + +//#include <qframe.h> +//#include <qdict.h> +#include <qvbox.h> +#include <qhbox.h> +//#include <qcolor.h> +//#include <qlistview.h> + +#include <kdialogbase.h> + +#include <libkdepim/kprefsdialog.h> + +class KColorButton; +class QSpinBox;; +class QRadioButton; +class QCheckBox; +class QSlider; +class KURLRequester; +class QComboBox; +class QLineEdit; +class QStringList; +class KSyncProfile; + +/** Dialog to change the korganizer configuration. + */ +class KOSyncPrefsDialog : public KDialog +{ + Q_OBJECT + public: + /** Initialize dialog and pages */ + KOSyncPrefsDialog(QWidget *parent=0,char *name=0,bool modal=false); + ~KOSyncPrefsDialog(); + void usrReadConfig(); + + public slots: + protected slots: + void accept(); + void deleteProfile(); + void newProfile(); + void cloneProfile(); + void kindChanged(bool); + void fillSSH(); + void fillFTP(); + void textChanged( const QString & ); + void profileChanged( int ); + void chooseFile(); + void slotOK(); + + protected: + void usrWriteConfig(); + + void setupSyncAlgTab(); + + private: + int currentSelection; + QPtrList<KSyncProfile> mSyncProfiles; + QStringList mSyncProfileNames; + QLineEdit * mMyMachineName; + QComboBox * mProfileBox; + QRadioButton* mIsLocal; + QRadioButton* mIsNotLocal; + QCheckBox* mIncludeInRing; + void addProfile ( KSyncProfile* ); + void insertProfiles(); + void saveProfile(); + QButtonGroup* proGr; + + QRadioButton* loc, *rem, *newest, *ask, *f_loc,* f_rem, *both; + + + QLineEdit * mRemotePostcommand; + QLineEdit * mRemotePrecommand; + QLineEdit * mRemoteFile; + QLineEdit * mLocalTempFile; + QWidget* mSetupSyncAlgTab; + + QVBox* localFileWidget; + QVBox* remoteFileWidget; + QCheckBox* mWriteBackFile; + QCheckBox* mWriteBackExisting; + QCheckBox* mAskForPreferences; + QCheckBox* mShowSummaryAfterSync; +}; + +#endif diff --git a/korganizer/kosyncprefsdialog.moc b/korganizer/kosyncprefsdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kosyncprefsdialog.moc diff --git a/korganizer/kotimespanview.cpp b/korganizer/kotimespanview.cpp new file mode 100644 index 0000000..266a403 --- a/dev/null +++ b/korganizer/kotimespanview.cpp @@ -0,0 +1,110 @@ +#include <qlayout.h> + +#include <kconfig.h> + +#include "timespanview.h" +#include "koglobals.h" + +#include "kotimespanview.h" +#include "kotimespanview.moc" + +KOTimeSpanView::KOTimeSpanView(Calendar *calendar, QWidget *parent, + const char *name) : + KOEventView( calendar, parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); + + mTimeSpanView = new TimeSpanView( this ); + topLayout->addWidget( mTimeSpanView ); + + connect( mTimeSpanView, SIGNAL( dateRangeChanged() ), SLOT( updateView() ) ); +} + +KOTimeSpanView::~KOTimeSpanView() +{ +} + +void KOTimeSpanView::readSettings() +{ + readSettings(KOGlobals::config()); +} + +void KOTimeSpanView::readSettings(KConfig *config) +{ +// kdDebug() << "KOTimeSpanView::readSettings()" << endl; + + config->setGroup("Views"); + + QValueList<int> sizes = config->readIntListEntry("Separator TimeSpanView"); + if (sizes.count() == 2) { + mTimeSpanView->setSplitterSizes(sizes); + } +} + +void KOTimeSpanView::writeSettings(KConfig *config) +{ +// kdDebug() << "KOTimeSpanView::writeSettings()" << endl; + + config->setGroup("Views"); + + QValueList<int> list = mTimeSpanView->splitterSizes(); + config->writeEntry("Separator TimeSpanView",list); +} + +int KOTimeSpanView::maxDatesHint() +{ + return 0; +} + +int KOTimeSpanView::currentDateCount() +{ + return 0; +} + +QPtrList<Incidence> KOTimeSpanView::selectedIncidences() +{ + QPtrList<Incidence> selected; + + return selected; +} + +void KOTimeSpanView::updateView() +{ + insertItems( mTimeSpanView->startDateTime().date(), + mTimeSpanView->endDateTime().date() ); +} + +void KOTimeSpanView::showDates(const QDate &start, const QDate &end) +{ + QDate s = start.addDays( -2 ); + QDate e = end.addDays( 2 ); + + insertItems( s, e ); +} + +void KOTimeSpanView::insertItems(const QDate &start, const QDate &end) +{ + mTimeSpanView->clear(); + mTimeSpanView->setDateRange( start, end ); + + QPtrList<Event> events = calendar()->events( start, end ); + Event *event = events.first(); + while( event ) { +// kdDebug() << "KOTimeSpanView::showDates() add event: " << event->summary() +// << endl; + + mTimeSpanView->addItem( event ); + + event = events.next(); + } + + mTimeSpanView->updateView(); +} + +void KOTimeSpanView::showEvents(QPtrList<Event> eventList) +{ +} + +void KOTimeSpanView::changeEventDisplay(Event *, int) +{ +} diff --git a/korganizer/kotimespanview.h b/korganizer/kotimespanview.h new file mode 100644 index 0000000..c682ed8 --- a/dev/null +++ b/korganizer/kotimespanview.h @@ -0,0 +1,41 @@ +#ifndef KOTIMESPANVIEW_H +#define KOTIMESPANVIEW_H + +#include "koeventview.h" + +class KConfig; +class TimeSpanView; + +class KOTimeSpanView : public KOEventView +{ + Q_OBJECT + public: + KOTimeSpanView(Calendar *calendar, QWidget *parent = 0, + const char *name = 0); + ~KOTimeSpanView(); + + virtual int maxDatesHint(); + virtual int currentDateCount(); + virtual QPtrList<Incidence> selectedIncidences(); + DateList selectedDates() + {DateList q; + return q;} + + void readSettings(); + void readSettings( KConfig * ); + void writeSettings( KConfig * ); + + public slots: + virtual void updateView(); + virtual void showDates(const QDate &start, const QDate &end); + virtual void showEvents(QPtrList<Event> eventList); + + void changeEventDisplay(Event *, int); + + private: + void insertItems( const QDate &start, const QDate & end ); + + TimeSpanView *mTimeSpanView; +}; + +#endif diff --git a/korganizer/kotimespanview.moc b/korganizer/kotimespanview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kotimespanview.moc diff --git a/korganizer/kotodoeditor.cpp b/korganizer/kotodoeditor.cpp new file mode 100644 index 0000000..1c44f2b --- a/dev/null +++ b/korganizer/kotodoeditor.cpp @@ -0,0 +1,373 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1997, 1998 Preston Brown + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qtooltip.h> +#include <qframe.h> +#include <qpixmap.h> +#include <qlayout.h> +#include <qhbox.h> +#include <qdir.h> +#include <qdatetime.h> +#include <qapplication.h> + +#include <kiconloader.h> +#include <klocale.h> +#include <kfiledialog.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> + +#include <libkdepim/categoryselectdialog.h> +#include <libkcal/calendarlocal.h> +#include <libkcal/calendarresources.h> +#include <libkcal/resourcecalendar.h> +#include <libkcal/icalformat.h> +#include <kresources/resourceselectdialog.h> + +#include "koprefs.h" + +#include "kotodoeditor.h" +#include "kotodoeditor.moc" +extern int globalFlagBlockAgenda; + +KOTodoEditor::KOTodoEditor( Calendar *calendar, QWidget *parent ) : + KOIncidenceEditor( i18n("Edit To-Do"), calendar, parent ) +{ + mTodo = 0; + mRelatedTodo = 0; + findButton(User1)->hide(); + init(); +} + +KOTodoEditor::~KOTodoEditor() +{ + emit dialogClose( mTodo ); +} + +void KOTodoEditor::init() +{ + setupGeneral(); + setupAttendeesTab(); +} +void KOTodoEditor::setCategories( QString s ) +{ + mGeneral->setCategories(s); +} +void KOTodoEditor::setSecrecy( int sec ) +{ + mGeneral->setSecrecy( sec ); +} +void KOTodoEditor::reload() +{ + if ( mTodo ) readTodo( mTodo ); +} + +void KOTodoEditor::setupGeneral() +{ + mGeneral = new KOEditorGeneralTodo(this); + connect ( mGeneral, SIGNAL ( allAccepted() ), this, SLOT ( slotOk () ) ); + + // connect(mGeneral,SIGNAL(openCategoryDialog()),mCategoryDialog,SLOT(show())); + //connect(mCategoryDialog, SIGNAL(categoriesSelected(const QString &)), + // mGeneral,SLOT(setCategories(const QString &))); + + if (KOPrefs::instance()->mCompactDialogs) { + QFrame *topFrame = addPage(i18n("General")); + + QBoxLayout *topLayout = new QVBoxLayout(topFrame); + if ( QApplication::desktop()->width() < 480 ) { + topLayout->setMargin(1); + topLayout->setSpacing(1); + } else { + topLayout->setMargin(marginHint()-1); + topLayout->setSpacing(spacingHint()-1); + } + mGeneral->initHeader(topFrame,topLayout); + mGeneral->initTime(topFrame,topLayout); + mGeneral->initAlarm(topFrame,topLayout); + mGeneral->enableAlarm( false ); + + + QBoxLayout *priorityLayout; + if ( QApplication::desktop()->width() < 500 ) + priorityLayout = new QVBoxLayout( topLayout ); + else + priorityLayout = new QHBoxLayout( topLayout ); + QWidget* prioWidget = new QWidget (topFrame); + priorityLayout->addWidget( prioWidget ); + QHBoxLayout* priorityLayout2 = new QHBoxLayout( prioWidget); + + + QIconSet icon; + if ( QApplication::desktop()->width() < 321 ) + icon = SmallIcon("fileexport16"); + else + icon = SmallIcon("fileexport"); + QPushButton * saveTemplate = new QPushButton( prioWidget); + saveTemplate->setIconSet (icon ) ; + int size = saveTemplate->sizeHint().height(); + saveTemplate->setFixedSize( size, size ); + if ( QApplication::desktop()->width() < 321 ) + icon = SmallIcon("fileimport16"); + else + icon = SmallIcon("fileimport"); + QPushButton * loadTemplate = new QPushButton( prioWidget); + loadTemplate->setIconSet (icon ) ; + loadTemplate->setFixedSize( size, size ); + + priorityLayout2->addWidget(loadTemplate); + priorityLayout2->addWidget(saveTemplate); + mGeneral->initPriority(prioWidget,priorityLayout2); + mGeneral->initCategories( topFrame, priorityLayout ); + topLayout->addStretch(1); + + QFrame *topFrame2 = addPage(i18n("Details")); + + QBoxLayout *topLayout2 = new QVBoxLayout(topFrame2); + topLayout2->setMargin(marginHint()); + topLayout2->setSpacing(spacingHint()); + + QHBoxLayout *completionLayout = new QHBoxLayout( topLayout2 ); + mGeneral->initCompletion(topFrame2,completionLayout); + + + mGeneral->initSecrecy( topFrame2, topLayout2 ); + mGeneral->initDescription(topFrame2,topLayout2); + + // QHBox * hb = new QHBox ( topFrame2 ); + // topLayout2->addWidget(hb); + // hb->setSpacing( 3 ); + + connect( saveTemplate, SIGNAL( clicked() ), this , SLOT( slotSaveTemplate() ) ); + connect( loadTemplate, SIGNAL( clicked() ), this , SLOT( slotLoadTemplate() ) ); + + } else { + QFrame *topFrame = addPage(i18n("General")); + + QBoxLayout *topLayout = new QVBoxLayout(topFrame); + topLayout->setSpacing(spacingHint()); + + mGeneral->initHeader(topFrame,topLayout); + mGeneral->initTime(topFrame,topLayout); + mGeneral->initStatus(topFrame,topLayout); + QBoxLayout *alarmLineLayout = new QHBoxLayout(topLayout); + mGeneral->initAlarm(topFrame,alarmLineLayout); + mGeneral->initDescription(topFrame,topLayout); + QBoxLayout *detailsLayout = new QHBoxLayout(topLayout); + mGeneral->initCategories( topFrame, detailsLayout ); + mGeneral->initSecrecy( topFrame, detailsLayout ); + } + mGeneral->finishSetup(); + +} + +void KOTodoEditor::editTodo(Todo *todo, bool editDescription) +{ + //init(); + + mTodo = todo; + readTodo(mTodo); + if ( editDescription ) { + showPage( 1 ); + mGeneral->setFocusOn( 1 ); + } else { + showPage( 0 ); + mGeneral->setFocusOn( 2 ); + } +} + +void KOTodoEditor::newTodo(QDateTime due,Todo *relatedTodo,bool allDay) +{ + //init(); + + mTodo = 0; + setDefaults(due,relatedTodo,allDay); +} + +void KOTodoEditor::loadDefaults() +{ + setDefaults(QDateTime::currentDateTime().addDays(7),0,false); +} + +bool KOTodoEditor::processInput( bool emitTime ) +{ + if (!validateInput()) return false; + + Todo *todo = 0; + + if (mTodo) todo = mTodo; + else { + todo = new Todo; + todo->setOrganizer(KOPrefs::instance()->email()); + } + + writeTodo(todo); + if ( emitTime ) { + globalFlagBlockAgenda = 1; + emit showAgendaView( false ); + if ( todo->hasDueDate() ) + emit jumpToTime( todo->dtDue().date() ); + globalFlagBlockAgenda = 2; + } + if (mTodo) { + todo->setRevision(todo->revision()+1); + emit todoChanged(todo); + } else { + mCalendar->addTodo(todo); + mTodo = todo; + emit todoAdded(todo); + } + + return true; +} + +void KOTodoEditor::deleteTodo() +{ + if (mTodo) { + if (KOPrefs::instance()->mConfirm) { + switch (msgItemDelete()) { + case KMessageBox::Continue: // OK + emit todoToBeDeleted(mTodo); + emit dialogClose(mTodo); + mCalendar->deleteTodo(mTodo); + emit todoDeleted(); + reject(); + break; + } + } + else { + emit todoToBeDeleted(mTodo); + emit dialogClose(mTodo); + mCalendar->deleteTodo(mTodo); + emit todoDeleted(); + reject(); + } + } else { + reject(); + } +} + +void KOTodoEditor::setDefaults(QDateTime due,Todo *relatedEvent,bool allDay) +{ + mRelatedTodo = relatedEvent; + + mGeneral->setDefaults(due,allDay); + mDetails->setDefaults(); + showPage( 0 ); + if ( mRelatedTodo ) + mGeneral->setCategories (mRelatedTodo->categoriesStr ()); + mGeneral->setFocusOn( 2 ); +} + +void KOTodoEditor::readTodo(Todo *todo) +{ + mGeneral->readTodo(todo); + mDetails->readEvent(todo); + mRelatedTodo = 0;//todo->relatedTo(); + // categories + // mCategoryDialog->setSelected(todo->categories()); + + // We should handle read-only events here. +} + +void KOTodoEditor::writeTodo(Todo *event) +{ + mGeneral->writeTodo(event); + mDetails->writeEvent(event); + + // set related event, i.e. parent to-do in this case. + if (mRelatedTodo) { + event->setRelatedTo(mRelatedTodo); + } +} + +bool KOTodoEditor::validateInput() +{ + if (!mGeneral->validateInput()) return false; + if (!mDetails->validateInput()) return false; + return true; +} + +int KOTodoEditor::msgItemDelete() +{ + return KMessageBox::warningContinueCancel(this, + i18n("This item will be permanently deleted."), + i18n("KOrganizer Confirmation"),i18n("Delete")); +} + +void KOTodoEditor::modified (int modification) +{ + if (modification == KOGlobals::CATEGORY_MODIFIED || + KOGlobals::UNKNOWN_MODIFIED == modification ) + // mCategoryDialog->setSelected (mTodo->categories ()); + mGeneral->modified (mTodo, modification); + +} + +void KOTodoEditor::slotLoadTemplate() +{ + + QString fileName =locateLocal( "templates", "todos" ); + QDir t_dir; + if ( !t_dir.exists(fileName) ) + t_dir.mkdir ( fileName ); + fileName += "/todo"; + fileName = KFileDialog::getSaveFileName( fileName , "Load Todo template", this ); + if ( fileName.length() == 0 ) + return; + CalendarLocal cal; + ICalFormat format; + if ( !format.load( &cal, fileName ) ) { + KMessageBox::error( this, i18n("Error loading template file\n '%1'.") + .arg( fileName ) ); + return ; + } + QPtrList<Todo> todos = cal.todos(); + Todo * todo = todos.first(); + if ( !todo ) { + KMessageBox::error( this, + i18n("Template does not\ncontain a valid Todo.")); + } else { + readTodo( todo ); + } + +} + +void KOTodoEditor::slotSaveTemplate() +{ + QString fileName =locateLocal( "templates", "todos" ); + QDir t_dir; + if ( !t_dir.exists(fileName) ) + t_dir.mkdir ( fileName ); + fileName += "/todo"; + fileName = KFileDialog::getSaveFileName( fileName , "Save as Todo template", this ); + if ( fileName.length() > 0 ) + saveTemplate( fileName ); +} + +void KOTodoEditor::saveTemplate( const QString &templateName ) +{ + Todo *todo = new Todo; + writeTodo( todo ); + saveAsTemplate( todo, templateName ); +} diff --git a/korganizer/kotodoeditor.h b/korganizer/kotodoeditor.h new file mode 100644 index 0000000..2657bd8 --- a/dev/null +++ b/korganizer/kotodoeditor.h @@ -0,0 +1,102 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1997, 1998 Preston Brown + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KOTODOEDITOR_H +#define _KOTODOEDITOR_H + +#include <libkcal/calendar.h> + +#include "koeditorgeneraltodo.h" +#include "koeditordetails.h" +#include "koincidenceeditor.h" + +class QDateTime; + +/** + This class provides a dialog for editing a Todo. +*/ +class KOTodoEditor : public KOIncidenceEditor +{ + Q_OBJECT + public: + /** + Constructs a new todo editor. + */ + KOTodoEditor( Calendar *calendar, QWidget *parent ); + virtual ~KOTodoEditor(); + + void init(); + + void reload(); + void setSecrecy( int sec ); + /** + Clear editor for new todo, and preset the dates and times with hint. + */ + void newTodo(QDateTime due,Todo *relatedTodo=0,bool allDay=false); + + /** Edit an existing todo. */ + void editTodo(Todo * ,bool editDescription = false ); + + /** Set widgets to default values */ + void setDefaults(QDateTime due,Todo *relatedTodo,bool allDay); + /** Read event object and setup widgets accordingly */ + void readTodo(Todo *); + /** Write event settings to event object */ + void writeTodo(Todo *); + + /** Check if the input is valid. */ + bool validateInput(); + /** Process user input and create or update event. Returns false if input + * is not valid */ + bool processInput( bool ); + + /** This todo has been modified externally */ + void modified (int); + void setCategories( QString s ); + signals: + void todoChanged(Todo *); + void todoAdded(Todo *); + void todoToBeDeleted(Todo *); + void todoDeleted(); + + protected slots: + void loadDefaults(); + void deleteTodo(); + + void slotLoadTemplate(); + void slotSaveTemplate(); + void saveTemplate( const QString & ); + + protected: + void setupGeneral(); + int msgItemDelete(); + + private: + Todo *mTodo; + + Incidence *mRelatedTodo; + + KOEditorGeneralTodo *mGeneral; +}; + +#endif diff --git a/korganizer/kotodoeditor.moc b/korganizer/kotodoeditor.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kotodoeditor.moc diff --git a/korganizer/kotodoview.cpp b/korganizer/kotodoview.cpp new file mode 100644 index 0000000..0708a69 --- a/dev/null +++ b/korganizer/kotodoview.cpp @@ -0,0 +1,1028 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> +#include <qheader.h> +#include <qcursor.h> + +#include <qvbox.h> +#include <kdebug.h> +#include "koprefs.h" +#include <klocale.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kmessagebox.h> + +#include <libkcal/icaldrag.h> +#include <libkcal/vcaldrag.h> +#include <libkcal/calfilter.h> +#include <libkcal/dndfactory.h> +#include <libkcal/calendarresources.h> +#include <libkcal/resourcecalendar.h> +#include <kresources/resourceselectdialog.h> +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#else +#include <qapplication.h> +#endif +#ifndef KORG_NOPRINTER +#include "calprinter.h" +#endif +#include "docprefs.h" + +#include "kotodoview.h" +using namespace KOrg; +#include "kotodoview.moc" + +KOTodoListView::KOTodoListView(Calendar *calendar,QWidget *parent, + const char *name) : + KListView(parent,name) +{ + mCalendar = calendar; +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation(viewport(), QPEApplication::RightOnHold ); +#endif + mOldCurrent = 0; + mMousePressed = false; + + setAcceptDrops(true); + viewport()->setAcceptDrops(true); + int size = 16; + if (qApp->desktop()->width() < 300 ) + size = 12; + setTreeStepSize( size + 6 ); + +} + +void KOTodoListView::contentsDragEnterEvent(QDragEnterEvent *e) +{ +#ifndef KORG_NODND +// kdDebug() << "KOTodoListView::contentsDragEnterEvent" << endl; + if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) && + !QTextDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + mOldCurrent = currentItem(); +#endif +} + + +void KOTodoListView::contentsDragMoveEvent(QDragMoveEvent *e) +{ +#ifndef KORG_NODND +// kdDebug() << "KOTodoListView::contentsDragMoveEvent" << endl; + + if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) && + !QTextDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + e->accept(); +#endif +} + +void KOTodoListView::contentsDragLeaveEvent(QDragLeaveEvent *) +{ +#ifndef KORG_NODND +// kdDebug() << "KOTodoListView::contentsDragLeaveEvent" << endl; + + setCurrentItem(mOldCurrent); + setSelected(mOldCurrent,true); +#endif +} + +void KOTodoListView::contentsDropEvent(QDropEvent *e) +{ +#ifndef KORG_NODND +// kdDebug() << "KOTodoListView::contentsDropEvent" << endl; + + if ( !ICalDrag::canDecode( e ) && !VCalDrag::canDecode( e ) && + !QTextDrag::canDecode( e ) ) { + e->ignore(); + return; + } + + DndFactory factory( mCalendar ); + Todo *todo = factory.createDropTodo(e); + + if (todo) { + e->acceptAction(); + + KOTodoViewItem *destination = + (KOTodoViewItem *)itemAt(contentsToViewport(e->pos())); + Todo *destinationEvent = 0; + if (destination) destinationEvent = destination->todo(); + + Todo *existingTodo = mCalendar->todo(todo->uid()); + + if(existingTodo) { +// kdDebug() << "Drop existing Todo" << endl; + Incidence *to = destinationEvent; + while(to) { + if (to->uid() == todo->uid()) { + KMessageBox::sorry(this, + i18n("Cannot move To-Do to itself or a child of itself"), + i18n("Drop To-Do")); + delete todo; + return; + } + to = to->relatedTo(); + } + existingTodo->setRelatedTo(destinationEvent); + emit todoDropped(todo); + delete todo; + } else { +// kdDebug() << "Drop new Todo" << endl; + todo->setRelatedTo(destinationEvent); + mCalendar->addTodo(todo); + + emit todoDropped(todo); + } + } + else { + QString text; + if (QTextDrag::decode(e,text)) { + //QListViewItem *qlvi = itemAt( contentsToViewport(e->pos()) ); + KOTodoViewItem *todoi = static_cast<KOTodoViewItem *>(itemAt( contentsToViewport(e->pos()) )); + kdDebug() << "Dropped : " << text << endl; + QStringList emails = QStringList::split(",",text); + for(QStringList::ConstIterator it = emails.begin();it!=emails.end();++it) { + kdDebug() << " Email: " << (*it) << endl; + int pos = (*it).find("<"); + QString name = (*it).left(pos); + QString email = (*it).mid(pos); + if (!email.isEmpty() && todoi) { + todoi->todo()->addAttendee(new Attendee(name,email)); + } + } + } + else { + kdDebug() << "KOTodoListView::contentsDropEvent(): Todo from drop not decodable" << endl; + e->ignore(); + } + } +#endif +} + +void KOTodoListView::contentsMousePressEvent(QMouseEvent* e) +{ + QListView::contentsMousePressEvent(e); +#ifndef KORG_NODND + QPoint p(contentsToViewport(e->pos())); + QListViewItem *i = itemAt(p); + if (i) { + // if the user clicked into the root decoration of the item, don't + // try to start a drag! + if (p.x() > header()->sectionPos(header()->mapToIndex(0)) + + treeStepSize() * (i->depth() + (rootIsDecorated() ? 1 : 0)) + + itemMargin() || + p.x() < header()->sectionPos(header()->mapToIndex(0))) { + if (e->button()==Qt::LeftButton) { + mPressPos = e->pos(); + mMousePressed = true; + } + } + } +#endif +} + +void KOTodoListView::contentsMouseMoveEvent(QMouseEvent* e) +{ +#ifndef KORG_NODND +// kdDebug() << "KOTodoListView::contentsMouseMoveEvent()" << endl; + QListView::contentsMouseMoveEvent(e); + if (mMousePressed && (mPressPos - e->pos()).manhattanLength() > + QApplication::startDragDistance()) { + mMousePressed = false; + QListViewItem *item = itemAt(contentsToViewport(mPressPos)); + if (item) { +// kdDebug() << "Start Drag for item " << item->text(0) << endl; + DndFactory factory( mCalendar ); + ICalDrag *vd = factory.createDragTodo( + ((KOTodoViewItem *)item)->todo(),viewport()); + if (vd->drag()) { + kdDebug() << "KOTodoListView::contentsMouseMoveEvent(): Delete drag source" << endl; + } +/* + QString source = fullPath(item); + if ( QFile::exists(source) ) { + QUriDrag* ud = new QUriDrag(viewport()); + ud->setFilenames( source ); + if ( ud->drag() ) + QMessageBox::information( this, "Drag source", + QString("Delete ")+source, "Not implemented" ); +*/ + } + } +#endif +} +void KOTodoListView::keyPressEvent ( QKeyEvent * e ) +{ + + QListViewItem* cn; + if ( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter ) { + cn = currentItem(); + if ( cn ) { + KOTodoViewItem* ci = (KOTodoViewItem*)( cn ); + if ( ci ){ + if ( e->state() == ShiftButton ) + ci->setOn( false ); + else + ci->setOn( true ); + cn = cn->nextSibling(); + if ( cn ) { + setCurrentItem ( cn ); + ensureItemVisible ( cn ); + } + + } + } + + return; + } + + // qDebug("KOTodoListView::keyPressEvent "); + if ( e->state() == Qt::ControlButton || e->state() == Qt::ShiftButton || ( height() > 150 && width() > 200 ) ) { + switch ( e->key() ) { + case Qt::Key_Down: + case Qt::Key_Up: + QListView::keyPressEvent ( e ); + break; + default: + e->ignore(); + break; + } + return; + } + e->ignore(); +} +void KOTodoListView::contentsMouseReleaseEvent(QMouseEvent *e) +{ + QListView::contentsMouseReleaseEvent(e); + mMousePressed = false; +} + +void KOTodoListView::contentsMouseDoubleClickEvent(QMouseEvent *e) +{ + if (!e) return; + + QPoint vp = contentsToViewport(e->pos()); + + QListViewItem *item = itemAt(vp); + + emit double_Clicked(item); + if (!item) return; + + emit doubleClicked(item,vp,0); +} + +///////////////////////////////////////////////////////////////////////////// + +KOQuickTodo::KOQuickTodo(QWidget *parent) : + QLineEdit(parent) +{ + setText(i18n("Click to add a new Todo")); +} + +void KOQuickTodo::focusInEvent(QFocusEvent *ev) +{ + if ( text()==i18n("Click to add a new Todo") ) + setText(""); + QLineEdit::focusInEvent(ev); +} + +void KOQuickTodo::focusOutEvent(QFocusEvent *ev) +{ + setText(i18n("Click to add a new Todo")); + QLineEdit::focusOutEvent(ev); +} + +///////////////////////////////////////////////////////////////////////////// + +KOTodoView::KOTodoView(Calendar *calendar,QWidget* parent,const char* name) : + KOrg::BaseView(calendar,parent,name) +{ + QBoxLayout *topLayout = new QVBoxLayout(this); + mName = QString ( name ); + mBlockUpdate = false; + mQuickAdd = new KOQuickTodo(this); + topLayout->addWidget(mQuickAdd); + + if ( !KOPrefs::instance()->mEnableQuickTodo ) mQuickAdd->hide(); + + mTodoListView = new KOTodoListView(calendar,this); + topLayout->addWidget(mTodoListView); + //mTodoListView->header()->setMaximumHeight(30); + mTodoListView->setRootIsDecorated(true); + mTodoListView->setAllColumnsShowFocus(true); + + mTodoListView->setShowSortIndicator(true); + + mTodoListView->addColumn(i18n("Todo")); + mTodoListView->addColumn(i18n("Prio")); + mTodoListView->setColumnAlignment(1,AlignHCenter); + mTodoListView->addColumn(i18n("Complete")); + mTodoListView->setColumnAlignment(2,AlignHCenter); + mTodoListView->addColumn(i18n("Due Date")); + mTodoListView->setColumnAlignment(3,AlignLeft); + mTodoListView->addColumn(i18n("Due Time")); + mTodoListView->setColumnAlignment(4,AlignHCenter); + mTodoListView->addColumn(i18n("Cancelled")); + mTodoListView->addColumn(i18n("Categories")); +#if 0 + mTodoListView->addColumn(i18n("Sort Id")); + mTodoListView->setColumnAlignment(4,AlignHCenter); +#endif + + mTodoListView->setMinimumHeight( 60 ); + mTodoListView->setItemsRenameable( true ); + mTodoListView->setRenameable( 0 ); + mTodoListView->setColumnWidth( 0, 120 ); + mTodoListView->setColumnWidthMode(0, QListView::Manual); + mTodoListView->setColumnWidthMode(1, QListView::Manual); + mTodoListView->setColumnWidthMode(2, QListView::Manual); + mTodoListView->setColumnWidthMode(3, QListView::Manual); + mTodoListView->setColumnWidthMode(4, QListView::Manual); + mTodoListView->setColumnWidthMode(5, QListView::Manual); + mTodoListView->setColumnAlignment( 2, AlignCenter ); +#if 0 + mTodoListView->setColumnWidthMode(6, QListView::Manual); +#endif + + mPriorityPopupMenu = new QPopupMenu(this); + for (int i = 1; i <= 5; i++) { + QString label = QString ("%1").arg (i); + mPriority[mPriorityPopupMenu->insertItem (label)] = i; + } + connect (mPriorityPopupMenu, SIGNAL(activated (int)), SLOT (setNewPriority(int))); + + mPercentageCompletedPopupMenu = new QPopupMenu(this); + for (int i = 0; i <= 100; i+=20) { + QString label = QString ("%1 %").arg (i); + mPercentage[mPercentageCompletedPopupMenu->insertItem (label)] = i; + } + connect (mPercentageCompletedPopupMenu, SIGNAL (activated (int)), SLOT (setNewPercentage (int))); + + + + mItemPopupMenu = new QPopupMenu(this); + mItemPopupMenu->insertItem(i18n("Show..."), this, + SLOT (showTodo())); + mItemPopupMenu->insertItem(i18n("Edit..."), this, + SLOT (editTodo())); + mItemPopupMenu->insertItem( i18n("Delete"), this, + SLOT (deleteTodo())); + mItemPopupMenu->insertItem( i18n("Clone..."), this, + SLOT (cloneTodo())); + mItemPopupMenu->insertItem( i18n("Move..."), this, + SLOT (moveTodo())); + mItemPopupMenu->insertItem( i18n("Beam..."), this, + SLOT (beamTodo())); + mItemPopupMenu->insertItem( i18n("Toggle Cancel"), this, + SLOT (cancelTodo())); + mItemPopupMenu->insertSeparator(); + + mItemPopupMenu->insertItem( i18n("New Todo..."), this, + SLOT (newTodo())); + mItemPopupMenu->insertItem(i18n("New Sub-Todo..."), this, + SLOT (newSubTodo())); + mItemPopupMenu->insertItem(i18n("Unparent Todo"), this, + SLOT (unparentTodo())); + mItemPopupMenu->insertSeparator(); + mItemPopupMenu->insertItem(i18n("Delete completed To-Dos","Purge Completed"), + this, SLOT( purgeCompleted() ) ); + mItemPopupMenu->insertItem(i18n("toggle completed To-Dos","Show Completed"), + this, SLOT( toggleCompleted() ),0, 33 ); + mItemPopupMenu->insertItem(i18n("toggle quick todo","Show Quick Todo"), + this, SLOT( toggleQuickTodo() ),0, 34 ); + + mPopupMenu = new QPopupMenu(this); + mPopupMenu->insertItem(SmallIconSet("todo"), i18n("New Todo..."), this, + SLOT (newTodo()),0,1); + mPopupMenu->insertItem(i18n("delete completed To-Dos","Purge Completed"), + this, SLOT(purgeCompleted()),0,2); + mPopupMenu->insertItem(i18n("Show Completed"), + this, SLOT( toggleCompleted() ),0,3 ); + mPopupMenu->insertItem(i18n("toggle quick todo","Show Quick Todo"), + this, SLOT( toggleQuickTodo() ),0,4 ); + mDocPrefs = new DocPrefs( name ); + + mPopupMenu->setCheckable( true ); + mItemPopupMenu->setCheckable( true ); + // Double clicking conflicts with opening/closing the subtree + connect( mTodoListView, SIGNAL( doubleClicked( QListViewItem *) ), + SLOT( editItem( QListViewItem *) ) ); + connect( mTodoListView, SIGNAL( rightButtonClicked ( QListViewItem *, + const QPoint &,int ) ), + SLOT( popupMenu( QListViewItem *, const QPoint & ,int) ) ); + connect( mTodoListView, SIGNAL( clicked( QListViewItem * ) ), + SLOT( itemClicked( QListViewItem * ) ) ); + connect( mTodoListView, SIGNAL( double_Clicked( QListViewItem * ) ), + SLOT( itemDoubleClicked( QListViewItem * ) ) ); + connect( mTodoListView, SIGNAL( todoDropped( Todo * ) ), + SLOT( updateView() ) ); + connect( mTodoListView, SIGNAL( expanded( QListViewItem * ) ), + SLOT( itemStateChanged( QListViewItem * ) ) ); + connect( mTodoListView, SIGNAL( collapsed( QListViewItem * ) ), + SLOT( itemStateChanged( QListViewItem * ) ) ); + +#if 0 + connect(mTodoListView,SIGNAL(selectionChanged(QListViewItem *)), + SLOT(selectionChanged(QListViewItem *))); + connect(mTodoListView,SIGNAL(clicked(QListViewItem *)), + SLOT(selectionChanged(QListViewItem *))); + connect(mTodoListView,SIGNAL(pressed(QListViewItem *)), + SLOT(selectionChanged(QListViewItem *))); +#endif + connect( mTodoListView, SIGNAL(selectionChanged() ), + SLOT( processSelectionChange() ) ); + connect( mQuickAdd, SIGNAL( returnPressed () ), + SLOT( addQuickTodo() ) ); +// if ( QApplication::desktop()->width() < 480 ) { +// setNarrow(); + // mTodoListView->setColumnWidth( 0, 100 ); + + // } + +} + +KOTodoView::~KOTodoView() +{ + delete mDocPrefs; +} + +void KOTodoView::jumpToDate () +{ + // if (mActiveItem) { +// mActiveItem->todo()); +// if ( mActiveItem->todo()->hasDueDate() ) +// emit mActiveItem->todo()jumpToTime( mTodo->dtDue().date() ); +} + +void KOTodoView::setNarrow() +{ + //mTodoListView->setColumnWidth( 0, 120 ); + mTodoListView->setColumnWidth( 1, 35 ); + mTodoListView->setColumnWidth( 2, 40 ); + mTodoListView->setColumnWidth( 3, 80 ); + mTodoListView->setColumnWidth( 4, 40 ); + mTodoListView->setColumnWidth( 5, 90 ); + +} +void KOTodoView::updateView() +{ +// kdDebug() << "KOTodoView::updateView()" << endl; + QFont fo = KOPrefs::instance()->mTodoViewFont; + mTodoListView->clear(); + if ( mName == "todolistsmall" ) { + if ( KOPrefs::instance()->mTodoViewUsesSmallFont ) { + int ps = fo.pointSize() -2; + if ( ps > 12 ) + ps -= 2; + fo.setPointSize( ps ); + } + } + + mTodoListView->setFont( fo ); + // QFontMetrics fm ( KOPrefs::instance()->mTodoViewFont ); + //mTodoListView->header()->setMaximumHeight(fm.height()); + QPtrList<Todo> todoList = calendar()->todos(); + +/* + kdDebug() << "KOTodoView::updateView(): Todo List:" << endl; + Event *t; + for(t = todoList.first(); t; t = todoList.next()) { + kdDebug() << " " << t->getSummary() << endl; + + if (t->getRelatedTo()) { + kdDebug() << " (related to " << t->getRelatedTo()->getSummary() << ")" << endl; + } + + QPtrList<Event> l = t->getRelations(); + Event *c; + for(c=l.first();c;c=l.next()) { + kdDebug() << " - relation: " << c->getSummary() << endl; + } + } +*/ + + // Put for each Event a KOTodoViewItem in the list view. Don't rely on a + // specific order of events. That means that we have to generate parent items + // recursively for proper hierarchical display of Todos. + mTodoMap.clear(); + Todo *todo; + todo = todoList.first();// todo; todo = todoList.next()) { + while ( todo ) { + bool next = true; + // qDebug("todo %s ", todo->summary().latin1()); + Incidence *incidence = todo->relatedTo(); + while ( incidence ) { + if ( incidence->type() == "Todo") { + //qDebug("related %s ",incidence->summary().latin1() ); + if ( !(todoList.contains ( ((Todo* )incidence ) ) )) { + //qDebug("related not found "); + todoList.remove( ); + todo = todoList.current(); + next = false; + incidence = 0; + + } else { + //qDebug("related found "); + incidence = incidence->relatedTo(); + } + } else + incidence = 0; + } + if ( next ) + todo = todoList.next(); + } +// qDebug("again .... "); +// for(todo = todoList.first(); todo; todo = todoList.next()) { + +// qDebug("yytodo %s ", todo->summary().latin1()); +// } + //qDebug("for "); + for(todo = todoList.first(); todo; todo = todoList.next()) { + if (!mTodoMap.contains(todo) && ( KOPrefs::instance()->mShowCompletedTodo || !todo->isCompleted() ) ) + { + insertTodoItem(todo); + } + } + //qDebug("for end "); + // Restore opened/closed state + mTodoListView->blockSignals( true ); + if( mDocPrefs ) restoreItemState( mTodoListView->firstChild() ); + mTodoListView->blockSignals( false ); + mTodoListView->setFocus(); + processSelectionChange(); +} + +void KOTodoView::restoreItemState( QListViewItem *item ) +{ + while( item ) { + KOTodoViewItem *todoItem = (KOTodoViewItem *)item; + todoItem->setOpen( mDocPrefs->readBoolEntry( todoItem->todo()->uid() ) ); + if( item->childCount() > 0 ) restoreItemState( item->firstChild() ); + item = item->nextSibling(); + } +} + + +QMap<Todo *,KOTodoViewItem *>::ConstIterator + KOTodoView::insertTodoItem(Todo *todo) +{ +// kdDebug() << "KOTodoView::insertTodoItem(): " << todo->getSummary() << endl; + // TODO: Check, if dynmaic cast is necessary + + + Incidence *incidence = todo->relatedTo(); + if (incidence && incidence->type() == "Todo") { + Todo *relatedTodo = static_cast<Todo *>(incidence); + +// kdDebug() << " has Related" << endl; + QMap<Todo *,KOTodoViewItem *>::ConstIterator itemIterator; + itemIterator = mTodoMap.find(relatedTodo); + if (itemIterator == mTodoMap.end()) { +// kdDebug() << " related not yet in list" << endl; + itemIterator = insertTodoItem (relatedTodo); + } + // isn't this pretty stupid? We give one Todo to the KOTodoViewItem + // and one into the map. Sure finding is more easy but why? -zecke + KOTodoViewItem *todoItem = new KOTodoViewItem(*itemIterator,todo,this); + return mTodoMap.insert(todo,todoItem); + } else { +// kdDebug() << " no Related" << endl; + // see above -zecke + KOTodoViewItem *todoItem = new KOTodoViewItem(mTodoListView,todo,this); + return mTodoMap.insert(todo,todoItem); + } +} + + +void KOTodoView::updateConfig() +{ + updateView(); + mTodoListView->repaintContents(); +} + +QPtrList<Incidence> KOTodoView::selectedIncidences() +{ + QPtrList<Incidence> selected; + + KOTodoViewItem *item = (KOTodoViewItem *)(mTodoListView->selectedItem()); +// if (!item) item = mActiveItem; + if (item) selected.append(item->todo()); + + return selected; +} + +QPtrList<Todo> KOTodoView::selectedTodos() +{ + QPtrList<Todo> selected; + + KOTodoViewItem *item = (KOTodoViewItem *)(mTodoListView->selectedItem()); +// if (!item) item = mActiveItem; + if (item) selected.append(item->todo()); + + return selected; +} + +void KOTodoView::changeEventDisplay(Event *, int) +{ + updateView(); +} + +void KOTodoView::showDates(const QDate &, const QDate &) +{ +} + +void KOTodoView::showEvents(QPtrList<Event>) +{ + kdDebug() << "KOTodoView::selectEvents(): not yet implemented" << endl; +} + +void KOTodoView::printPreview(CalPrinter *calPrinter, const QDate &fd, + const QDate &td) +{ +#ifndef KORG_NOPRINTER + calPrinter->preview(CalPrinter::Todolist, fd, td); +#endif +} + +void KOTodoView::editItem(QListViewItem *item ) +{ + // qDebug("editItem(QListViewItem *item ) "); + emit editTodoSignal(((KOTodoViewItem *)item)->todo()); +} + +void KOTodoView::showItem(QListViewItem *item,const QPoint &,int) +{ + emit showTodoSignal(((KOTodoViewItem *)item)->todo()); +} + +void KOTodoView::popupMenu(QListViewItem *item,const QPoint &,int column) +{ + + mActiveItem = (KOTodoViewItem *)item; + if (item) { + switch (column){ + case 1: + mPriorityPopupMenu->popup(QCursor::pos ()); break; + case 2: + mPercentageCompletedPopupMenu->popup(QCursor::pos ()); break; + case 3: + moveTodo(); + break; + case 6: + getCategoryPopupMenu((KOTodoViewItem *)item)->popup(QCursor::pos ()); break; + default: + mItemPopupMenu->popup(QCursor::pos()); + } + } else mPopupMenu->popup(QCursor::pos()); +} +void KOTodoView::newTodo() +{ + emit newTodoSignal(); +} + +void KOTodoView::newSubTodo() +{ + if (mActiveItem) { + emit newSubTodoSignal(mActiveItem->todo()); + } +} +void KOTodoView::unparentTodo() +{ + if (mActiveItem) { + emit unparentTodoSignal(mActiveItem->todo()); + } +} +void KOTodoView::editTodo() +{ + if (mActiveItem) { + emit editTodoSignal(mActiveItem->todo()); + } +} +void KOTodoView::cloneTodo() +{ + if (mActiveItem) { + emit cloneTodoSignal((Incidence*)mActiveItem->todo()); + } +} +void KOTodoView::cancelTodo() +{ + if (mActiveItem) { + emit cancelTodoSignal((Incidence*)mActiveItem->todo()); + } +} +void KOTodoView::moveTodo() +{ + if (mActiveItem) { + emit moveTodoSignal((Incidence*)mActiveItem->todo()); + } +} +void KOTodoView::beamTodo() +{ + if (mActiveItem) { + emit beamTodoSignal((Incidence*)mActiveItem->todo()); + } +} + + +void KOTodoView::showTodo() +{ + if (mActiveItem) { + emit showTodoSignal(mActiveItem->todo()); + } +} + +void KOTodoView::deleteTodo() +{ + if (mActiveItem) { + if (mActiveItem->childCount()) { + KMessageBox::sorry(this,i18n("Cannot delete To-Do which has children."), + i18n("Delete To-Do")); + } else { + emit deleteTodoSignal(mActiveItem->todo()); + } + } +} + +void KOTodoView::setNewPriority(int index) +{ + if (mActiveItem && !mActiveItem->todo()->isReadOnly ()) { + mActiveItem->todo()->setPriority(mPriority[index]); + mActiveItem->construct(); + todoModified (mActiveItem->todo(), KOGlobals::PRIORITY_MODIFIED); + mActiveItem->todo()->setRevision( mActiveItem->todo()->revision()+1 ); + } +} + +void KOTodoView::setNewPercentage(int index) +{ + if (mActiveItem && !mActiveItem->todo()->isReadOnly ()) { + if (mPercentage[index] == 100) { + mActiveItem->todo()->setCompleted(QDateTime::currentDateTime()); + } else { + mActiveItem->todo()->setCompleted(false); + } + mActiveItem->todo()->setPercentComplete(mPercentage[index]); + mActiveItem->construct(); + todoModified (mActiveItem->todo (), KOGlobals::COMPLETION_MODIFIED); + mActiveItem->todo()->setRevision( mActiveItem->todo()->revision()+1 ); + } +} + + +QPopupMenu * KOTodoView::getCategoryPopupMenu (KOTodoViewItem *todoItem) +{ + QPopupMenu* tempMenu = new QPopupMenu (this); + QStringList checkedCategories = todoItem->todo()->categories (); + + tempMenu->setCheckable (true); + for (QStringList::Iterator it = KOPrefs::instance()->mCustomCategories.begin (); + it != KOPrefs::instance()->mCustomCategories.end (); + ++it) { + int index = tempMenu->insertItem (*it); + mCategory[index] = *it; + if (checkedCategories.find (*it) != checkedCategories.end ()) tempMenu->setItemChecked (index, true); + } + + connect (tempMenu, SIGNAL (activated (int)), SLOT (changedCategories (int))); + return tempMenu; + + +} +void KOTodoView::changedCategories(int index) +{ + if (mActiveItem && !mActiveItem->todo()->isReadOnly ()) { + QStringList categories = mActiveItem->todo()->categories (); + if (categories.find (mCategory[index]) != categories.end ()) + categories.remove (mCategory[index]); + else + categories.insert (categories.end(), mCategory[index]); + categories.sort (); + mActiveItem->todo()->setCategories (categories); + mActiveItem->construct(); + mActiveItem->todo()->setRevision( mActiveItem->todo()->revision()+1 ); + todoModified (mActiveItem->todo (), KOGlobals::CATEGORY_MODIFIED); + } +} +void KOTodoView::itemDoubleClicked(QListViewItem *item) +{ + if (!item) { + newTodo(); + return; + } + if ( KOPrefs::instance()->mEditOnDoubleClick ) + editItem( item ); + else + showItem( item , QPoint(), 0 ); +} +void KOTodoView::itemClicked(QListViewItem *item) +{ + if (!item) { + return; + } + + KOTodoViewItem *todoItem = (KOTodoViewItem *)item; + int completed = todoItem->todo()->isCompleted(); // Completed or not? + + if (todoItem->isOn()) { + if (!completed) { + todoItem->todo()->setCompleted(QDateTime::currentDateTime()); + } + } else { + if (completed) { + todoItem->todo()->setCompleted(false); + } + } +} + +void KOTodoView::setDocumentId( const QString &id ) +{ + kdDebug() << "KOTodoView::setDocumentId()" << endl; + + mDocPrefs->setDoc( id ); +} + +void KOTodoView::itemStateChanged( QListViewItem *item ) +{ + if (!item) return; + + KOTodoViewItem *todoItem = (KOTodoViewItem *)item; + +// kdDebug() << "KOTodoView::itemStateChanged(): " << todoItem->todo()->summary() << endl; + + if( mDocPrefs ) mDocPrefs->writeEntry( todoItem->todo()->uid(), todoItem->isOpen() ); +} + +void KOTodoView::saveLayout(KConfig *config, const QString &group) const +{ + mTodoListView->saveLayout(config,group); +} + +void KOTodoView::restoreLayout(KConfig *config, const QString &group) +{ + mTodoListView->restoreLayout(config,group); +} + +void KOTodoView::processSelectionChange() +{ +// kdDebug() << "KOTodoView::processSelectionChange()" << endl; + + KOTodoViewItem *item = + static_cast<KOTodoViewItem *>( mTodoListView->selectedItem() ); + + if ( !item ) { + emit incidenceSelected( 0 ); + } else { + emit incidenceSelected( item->todo() ); + } +} + +void KOTodoView::modified(bool b) +{ + emit isModified(b); +} +void KOTodoView::setTodoModified( Todo* todo ) +{ + todoModified( todo, KOGlobals::UNKNOWN_MODIFIED ); +} +void KOTodoView::clearSelection() +{ + mTodoListView->selectAll( false ); +} + +void KOTodoView::purgeCompleted() +{ + emit purgeCompletedSignal(); +} +void KOTodoView::toggleQuickTodo() +{ + if ( mQuickAdd->isVisible() ) { + mQuickAdd->hide(); + KOPrefs::instance()->mEnableQuickTodo = false; + } + else { + mQuickAdd->show(); + KOPrefs::instance()->mEnableQuickTodo = true; + } + mPopupMenu->setItemChecked(4,KOPrefs::instance()->mEnableQuickTodo); + mItemPopupMenu->setItemChecked( 34 , KOPrefs::instance()->mEnableQuickTodo ); +} +void KOTodoView::toggleCompleted() +{ + KOPrefs::instance()->mShowCompletedTodo = !KOPrefs::instance()->mShowCompletedTodo; + mPopupMenu->setItemChecked( 3,KOPrefs::instance()->mShowCompletedTodo ); + mItemPopupMenu->setItemChecked( 33 , KOPrefs::instance()->mShowCompletedTodo ); + updateView(); +} + +void KOTodoView::addQuickTodo() +{ + Todo *todo = new Todo(); + todo->setSummary(mQuickAdd->text()); + todo->setOrganizer(KOPrefs::instance()->email()); + CalFilter * cf = mCalendar->filter(); + if ( cf ) { + if ( cf->isEnabled()&& cf->showCategories()) { + todo->setCategories(cf->categoryList()); + } + if ( cf->isEnabled() ) + todo->setSecrecy( cf->getSecrecy()); + } + mCalendar->addTodo(todo); + mQuickAdd->setText(""); + todoModified (todo, KOGlobals::EVENTADDED ); + updateView(); +} +void KOTodoView::keyPressEvent ( QKeyEvent * e ) +{ + // e->ignore(); + //return; + switch ( e->key() ) { + case Qt::Key_Down: + QWidget::keyPressEvent ( e ); + break; + + case Qt::Key_Up: + QWidget::keyPressEvent ( e ); + break; + case Qt::Key_Q: + toggleQuickTodo(); + break; + + default: + e->ignore(); + } + + if ( e->state() == Qt::ControlButton || e->state() == Qt::ShiftButton || ( height() > 150 && width() > 200 ) ) { + if ( e->key() == Qt::Key_I ) { + KOTodoViewItem*cn = (KOTodoViewItem*)mTodoListView->currentItem(); + if ( cn ) { + mActiveItem = cn; + KOTodoViewItem* ci = (KOTodoViewItem*)( cn ); + if ( ci ){ + showTodo(); + cn = (KOTodoViewItem*)cn->itemBelow(); + if ( cn ) { + mTodoListView->setCurrentItem ( cn ); + mTodoListView->ensureItemVisible ( cn ); + } + + } + } + e->accept(); + + } + + } + +} +void KOTodoView::updateTodo( Todo * t, int type ) +{ + if ( mBlockUpdate) + return; + + QMap<Todo *,KOTodoViewItem *>::ConstIterator itemIterator; + itemIterator = mTodoMap.find(t); + if (itemIterator != mTodoMap.end()) { + (*itemIterator)->construct(); + } else { + if ( type == KOGlobals::EVENTADDED ) { + insertTodoItem( t ); + } + } + +} + +void KOTodoView::todoModified(Todo * t , int p ) +{ + mBlockUpdate = true; + emit todoModifiedSignal ( t, p ); + mBlockUpdate = false; +} diff --git a/korganizer/kotodoview.h b/korganizer/kotodoview.h new file mode 100644 index 0000000..4495702 --- a/dev/null +++ b/korganizer/kotodoview.h @@ -0,0 +1,230 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000, 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KOTODOVIEW_H +#define KOTODOVIEW_H + +#include <qfont.h> +#include <qfontmetrics.h> +#include <qlineedit.h> +#include <qptrlist.h> +#include <qstrlist.h> +#include <qlistbox.h> +#include <qpopupmenu.h> +#include <qlabel.h> +#include <qmap.h> +#include <qlistview.h> +#include <klistview.h> + +#include <libkcal/calendar.h> +#include <libkcal/todo.h> + +#include <korganizer/baseview.h> + +#include "kotodoviewitem.h" +#include "koprefs.h" +#include "koglobals.h" + +class QDragEnterEvent; +class QDragMoveEvent; +class QDragLeaveEvent; +class QDropEvent; + +class DocPrefs; + +class KOTodoListView : public KListView +{ + Q_OBJECT + public: + KOTodoListView(Calendar *,QWidget *parent=0,const char *name=0); + virtual ~KOTodoListView() {} + + signals: + void todoDropped(Todo *); + void double_Clicked(QListViewItem *item); + + protected: + void contentsDragEnterEvent(QDragEnterEvent *); + void contentsDragMoveEvent(QDragMoveEvent *); + void contentsDragLeaveEvent(QDragLeaveEvent *); + void contentsDropEvent(QDropEvent *); + + void contentsMousePressEvent(QMouseEvent *); + void contentsMouseMoveEvent(QMouseEvent *); + void contentsMouseReleaseEvent(QMouseEvent *); + void contentsMouseDoubleClickEvent(QMouseEvent *); + + private: + Calendar *mCalendar; + QPoint mPressPos; + bool mMousePressed; + QListViewItem *mOldCurrent; + void keyPressEvent ( QKeyEvent * ) ; +}; + + +/** + This is the line-edit on top of the todoview for fast addition of new todos +*/ +class KOQuickTodo : public QLineEdit +{ + public: + KOQuickTodo(QWidget *parent=0); + protected: + void focusInEvent(QFocusEvent *ev); + void focusOutEvent(QFocusEvent *ev); +}; + + +/** + This class provides a multi-column list view of todo events. + + @short multi-column list view of todo events. + @author Cornelius Schumacher <schumacher@kde.org> +*/ +class KOTodoView : public KOrg::BaseView +{ + Q_OBJECT + public: + KOTodoView(Calendar *, QWidget* parent=0, const char* name=0 ); + ~KOTodoView(); + + QPtrList<Incidence> selectedIncidences(); + QPtrList<Todo> selectedTodos(); + + DateList selectedDates() + {DateList q; + return q;} + + /** Return number of shown dates. TodoView does not show dates, */ + int currentDateCount() { return 0; } + void setNarrow(); + + void printPreview(CalPrinter *calPrinter, const QDate &fd, const QDate &td); + + void setDocumentId( const QString & ); + + void saveLayout(KConfig *config, const QString &group) const; + void restoreLayout(KConfig *config, const QString &group); + /** Create a popup menu to set categories */ + QPopupMenu *getCategoryPopupMenu (KOTodoViewItem *todoItem); + + public slots: + void updateView(); + void updateConfig(); + + void changeEventDisplay(Event *, int); + + void showDates(const QDate &start, const QDate &end); + void showEvents(QPtrList<Event> eventList); + + void clearSelection(); + void jumpToDate (); + + void editItem(QListViewItem *item); + void showItem(QListViewItem *item,const QPoint &,int); + void popupMenu(QListViewItem *item,const QPoint &,int); + void newTodo(); + void newSubTodo(); + void unparentTodo(); + void showTodo(); + void editTodo(); + void cloneTodo(); + void cancelTodo(); + void moveTodo(); + void beamTodo(); + void deleteTodo(); + + void setNewPriority(int); + void setNewPercentage(int); + void changedCategories(int); + + void purgeCompleted(); + void toggleCompleted(); + void toggleQuickTodo(); + void updateTodo( Todo *, int ); + + void itemClicked(QListViewItem *); + void itemStateChanged(QListViewItem *); + void modified(bool); + void itemDoubleClicked(QListViewItem *item); + + signals: + void newTodoSignal(); + void newSubTodoSignal(Todo *); + void unparentTodoSignal(Todo *); + void showTodoSignal(Todo *); + + void editTodoSignal(Todo *); + void deleteTodoSignal(Todo *); + void todoModifiedSignal (Todo *, int); + + void isModified(bool); + void cloneTodoSignal( Incidence * ); + void cancelTodoSignal( Incidence * ); + void moveTodoSignal( Incidence * ); + void beamTodoSignal( Incidence * ); + void purgeCompletedSignal(); + + protected slots: + void processSelectionChange(); + void addQuickTodo(); + + private: + /* + * the TodoEditor approach is rather unscaling in the long + * run. + * Korganizer keeps it in memory and we need to update + * 1. make KOTodoViewItem a QObject again? + * 2. add a public method for setting one todo modified? + * 3. add a private method for setting a todo modified + friend here? + * -- zecke 2002-07-08 + */ + friend class KOTodoViewItem; + void setTodoModified( Todo* ); + QMap<Todo *,KOTodoViewItem *>::ConstIterator insertTodoItem(Todo *todo); + void restoreItemState( QListViewItem * ); + + KOTodoListView *mTodoListView; + QPopupMenu *mItemPopupMenu; + QPopupMenu *mPopupMenu; + QPopupMenu *mPriorityPopupMenu; + QPopupMenu *mPercentageCompletedPopupMenu; + QPopupMenu *mCategoryPopupMenu; + + QMap<int, int> mPercentage; + QMap<int, int> mPriority; + QMap<int, QString> mCategory; + KOTodoViewItem *mActiveItem; + + QMap<Todo *,KOTodoViewItem *> mTodoMap; + QString mName; + + DocPrefs *mDocPrefs; + QString mCurrentDoc; + KOQuickTodo *mQuickAdd; + bool mBlockUpdate; + void todoModified(Todo *, int ); + void keyPressEvent ( QKeyEvent * ) ; +}; + +#endif diff --git a/korganizer/kotodoview.moc b/korganizer/kotodoview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kotodoview.moc diff --git a/korganizer/kotodoviewitem.cpp b/korganizer/kotodoviewitem.cpp new file mode 100644 index 0000000..85647b1 --- a/dev/null +++ b/korganizer/kotodoviewitem.cpp @@ -0,0 +1,432 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <klocale.h> +#include <kdebug.h> +#include <qapp.h> + +#include <kiconloader.h> +#include "kotodoviewitem.h" +#include "kotodoview.h" +#include "koprefs.h" + +KOTodoViewItem::KOTodoViewItem( QListView *parent, Todo *todo, KOTodoView *kotodo) + : QCheckListItem( parent , "", CheckBox ), mTodo( todo ), mTodoView( kotodo ) +{ + construct(); +} + +KOTodoViewItem::KOTodoViewItem( KOTodoViewItem *parent, Todo *todo, KOTodoView *kotodo ) + : QCheckListItem( parent, "", CheckBox ), mTodo( todo ), mTodoView( kotodo ) +{ + construct(); +} + +QString KOTodoViewItem::key(int column,bool) const +{ + QMap<int,QString>::ConstIterator it = mKeyMap.find(column); + if (it == mKeyMap.end()) { + return text(column); + } else { + return *it; + } +} + +void KOTodoViewItem:: setup() +{ + + int h = 20; + if ( listView () ) { + QFontMetrics fm ( listView ()->font () ); + h = fm.height(); + } + setHeight( h ); + +} +void KOTodoViewItem::setSortKey(int column,const QString &key) +{ + mKeyMap.insert(column,key); +} + +#if QT_VERSION >= 300 +void KOTodoViewItem::paintBranches(QPainter *p,const QColorGroup & cg,int w, + int y,int h) +{ + QListViewItem::paintBranches(p,cg,w,y,h); +} +#else +#endif + +void KOTodoViewItem::construct() +{ + // qDebug("KOTodoViewItem::construct() "); + m_init = true; + QString keyd = "=="; + QString keyt = "=="; + + setOn(mTodo->isCompleted()); + setText(0,mTodo->summary()); + setText(1,QString::number(mTodo->priority())); + setText(2,i18n("%1 %").arg(QString::number(mTodo->percentComplete()))); + if (mTodo->percentComplete()<100) { + if (mTodo->isCompleted()) setSortKey(2,QString::number(999)); + else setSortKey(2,QString::number(mTodo->percentComplete())); + } + else { + if (mTodo->isCompleted()) setSortKey(2,QString::number(999)); + else setSortKey(2,QString::number(99)); + } + if (mTodo->hasDueDate()) { + setText(3, mTodo->dtDueDateStr()); + QDate d = mTodo->dtDue().date(); + keyd.sprintf("%04d%02d%02d",d.year(),d.month(),d.day()); + setSortKey(3,keyd); + if (mTodo->doesFloat()) { + setText(4,""); + } + else { + setText(4,mTodo->dtDueTimeStr()); + QTime t = mTodo->dtDue().time(); + keyt.sprintf("%02d%02d",t.hour(),t.minute()); + setSortKey(4,keyt); + } + } else { + setText(3,""); + setText(4,""); + } + setSortKey(3,keyd); + setSortKey(4,keyt); + + if (mTodo->isCompleted()) setSortKey(1,"6" + QString::number(mTodo->priority())+keyd+keyt); + else setSortKey(1,QString::number(mTodo->priority())+keyd+keyt); + + setText(5,mTodo->cancelled() ? i18n("Yes") : i18n("No")); + setText(6,mTodo->categoriesStr()); + +#if 0 + // Find sort id in description. It's the text behind the last '#' character + // found in the description. White spaces are removed from beginning and end + // of sort id. + int pos = mTodo->description().findRev('#'); + if (pos < 0) { + setText(6,""); + } else { + QString str = mTodo->description().mid(pos+1); + str.stripWhiteSpace(); + setText(6,str); + } +#endif + + m_known = false; + m_init = false; + + setMyPixmap(); + +} +void KOTodoViewItem::setMyPixmap() +{ + int size = 5; + QPixmap pixi = QPixmap( 1, 1 ); + // if ( !mTodo->isCompleted() && mTodo->hasDueDate() && mTodo->dtDue() < QDateTime::currentDateTime() ) { +// pixi = SmallIcon("redcross16"); +// } else { + QPainter p; + + int pixSize = 0; + QPixmap pPix = QPixmap( size, size ); + if ( mTodo->description().length() > 0 ) { + pixi.resize(size, pixSize+size); + pPix.fill( Qt::darkGreen ); + p.begin( &pixi ); + p. drawPixmap ( 0, pixSize, pPix); + p.end(); + pixSize += size; + } + if ( mTodo->isAlarmEnabled() ) { + pixi.resize(size, pixSize+size); + pPix.fill( Qt::red ); + p.begin( &pixi ); + p. drawPixmap ( 0, pixSize, pPix); + p.end(); + pixSize += size; + } + // } + if ( pixi.width() > 1 ) { + setPixmap ( 0,pixi ) ; + } + + +} +void KOTodoViewItem::stateChange(bool state) +{ + // qDebug("KOTodoViewItem::stateChange "); + // do not change setting on startup + if ( m_init ) return; + + kdDebug() << "State changed, modified " << state << endl; + QString keyd = "=="; + QString keyt = "=="; + + if (state) mTodo->setCompleted(state); + else mTodo->setPercentComplete(0); + if (isOn()!=state) { + setOn(state); + } + + if (mTodo->hasDueDate()) { + setText(3, mTodo->dtDueDateStr()); + QDate d = mTodo->dtDue().date(); + keyd.sprintf("%04d%02d%02d",d.year(),d.month(),d.day()); + setSortKey(3,keyd); + if (mTodo->doesFloat()) { + setText(4,""); + } + else { + setText(4,mTodo->dtDueTimeStr()); + QTime t = mTodo->dtDue().time(); + keyt.sprintf("%02d%02d",t.hour(),t.minute()); + setSortKey(4,keyt); + } + } + if (mTodo->isCompleted()) setSortKey(1,QString::number(9)+keyd+keyt); + else setSortKey(1,QString::number(mTodo->priority())+keyd+keyt); + + setText(2,i18n("%1 %").arg(QString::number(mTodo->percentComplete()))); + if (mTodo->percentComplete()<100) { + if (mTodo->isCompleted()) setSortKey(2,QString::number(999)); + else setSortKey(2,QString::number(mTodo->percentComplete())); + } + else { + if (mTodo->isCompleted()) setSortKey(2,QString::number(999)); + else setSortKey(2,QString::number(99)); + } + QListViewItem * myChild = firstChild(); + KOTodoViewItem *item; + while( myChild ) { + item = static_cast<KOTodoViewItem*>(myChild); + item->stateChange(state); + myChild = myChild->nextSibling(); + } + mTodoView->modified(true); + mTodoView->setTodoModified( mTodo ); + setMyPixmap(); +} + +bool KOTodoViewItem::isAlternate() +{ +#ifndef KORG_NOLVALTERNATION + KOTodoListView *lv = static_cast<KOTodoListView *>(listView()); + if (lv && lv->alternateBackground().isValid()) + { + KOTodoViewItem *above = 0; + above = dynamic_cast<KOTodoViewItem *>(itemAbove()); + m_known = above ? above->m_known : true; + if (m_known) + { + m_odd = above ? !above->m_odd : false; + } + else + { + KOTodoViewItem *item; + bool previous = true; + if (QListViewItem::parent()) + { + item = dynamic_cast<KOTodoViewItem *>(QListViewItem::parent()); + if (item) + previous = item->m_odd; + item = dynamic_cast<KOTodoViewItem *>(QListViewItem::parent()->firstChild()); + } + else + { + item = dynamic_cast<KOTodoViewItem *>(lv->firstChild()); + } + + while(item) + { + item->m_odd = previous = !previous; + item->m_known = true; + item = dynamic_cast<KOTodoViewItem *>(item->nextSibling()); + } + } + return m_odd; + } + return false; +#else + return false; +#endif +} + +void KOTodoViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + QColorGroup _cg = cg; + QColorGroup::ColorRole role; + if ( KOPrefs::instance()->mTodoViewUsesForegroundColor ) + role = QColorGroup::Text; + else + role = QColorGroup::Base; + //#ifndef KORG_NOLVALTERNATION + // if (isAlternate()) + // _cg.setColor(QColorGroup::Base, static_cast< KOTodoListView* >(listView())->alternateBackground()); + bool setColor = KOPrefs::instance()->mTodoViewUsesCatColors; + QColor colorToSet; + if ( setColor ) { + QStringList categories = mTodo->categories(); + QString cat = categories.first(); + if ( !cat.isEmpty()) { + colorToSet = *(KOPrefs::instance()->categoryColor(cat) ); + } else + setColor = false; + } + if (mTodo->hasDueDate()) { + if (mTodo->dtDue().date()==QDate::currentDate() && + !mTodo->isCompleted()) { + //_cg.setColor( role , KOPrefs::instance()->mTodoDueTodayColor); + colorToSet = KOPrefs::instance()->mTodoDueTodayColor; + setColor = true; + } + if (mTodo->dtDue().date() < QDate::currentDate() && + !mTodo->isCompleted()) { + //_cg.setColor( role, KOPrefs::instance()->mTodoOverdueColor); + colorToSet = KOPrefs::instance()->mTodoOverdueColor; + setColor = true; + } + } + + if ( setColor ) { + _cg.setColor(role,colorToSet ); + if ( role == QColorGroup::Base) { + int rgb = colorToSet.red(); + rgb += colorToSet.blue()/2; + rgb += colorToSet.green(); + if ( rgb < 200 ) + _cg.setColor(QColorGroup::Text,Qt::white ); + } + } + //#endif + if ( column > 0 ){ + if ( column == 2 && !KOPrefs::instance()->mTodoViewShowsPercentage ) { + p->save(); + int progress = (int)(( (width-6)*mTodo->percentComplete())/100.0 + 0.5); + + p->fillRect( 0, 0, width, height(), _cg.base() ); // background + // p->setPen(Qt::black ); //border + // p->setBrush( KOPrefs::instance()->mHighlightColorKGlobalSettings::baseColor() ); //filling + QColor fc = KOPrefs::instance()->mHighlightColor; + if ( mTodo->percentComplete() == 100 ) + fc = darkGreen; + p->drawRect( 2, 2, width-4, height()-4); + p->fillRect( 3, 3, progress, height()-6, + fc ); + p->restore(); + } else { + QCheckListItem::paintCell(p, _cg, column, width, alignment); + } + return; + } + + int align = alignment; + + if ( !p ) + return; + + p->fillRect( 0, 0, width, height(), _cg.brush( QColorGroup::Base ) ); + + QListView *lv = listView(); + if ( !lv ) + return; + int marg = 2;//lv->itemMargin(); + int r = 0; + QCheckListItem::Type myType = QCheckListItem::CheckBox; + int BoxSize = 20; + int boxOffset = 2; + int xOffset = 2; + if (qApp->desktop()->width() < 300 ) { + BoxSize = 14; + boxOffset = -1; + xOffset = 1; + // marg = 0; + } + if ( height() < BoxSize ) { + boxOffset = boxOffset - ((BoxSize - height())/2) ; + // qDebug("boxOffset %d height %d", boxOffset, height() ); + BoxSize = height(); + + } + //bool winStyle = lv->style() == WindowsStyle; + + int lineStart = 5; + if ( myType == Controller ) { + if ( !pixmap( 0 ) ) + r += BoxSize + 4; + } else { + ASSERT( lv ); //### + // QFontMetrics fm( lv->font() ); + // int d = fm.height(); + int x = 0; + int y = (height() - BoxSize) / 2; + // p->setPen( QPen( _cg.text(), winStyle ? 2 : 1 ) ); + if ( myType == CheckBox ) { + if ( isEnabled() ) + p->setPen( QPen( _cg.text(), 1 ) ); + else + p->setPen( QPen( listView()->palette().color( QPalette::Disabled, QColorGroup::Text ), 1 ) ); + p->drawRect( x+marg, y+2, BoxSize-4, BoxSize-4 ); + lineStart = x+marg; + ///////////////////// + x++; + y++; + if ( isOn() ) { + QPointArray a( 7*2 ); + int i, xx, yy; + xx = x+xOffset+marg+(boxOffset/2); + yy = y+5+boxOffset; + for ( i=0; i<3; i++ ) { + a.setPoint( 2*i, xx, yy ); + a.setPoint( 2*i+1, xx, yy+2 ); + // qDebug(" "); + xx++; yy++; + } + yy -= 2; + for ( i=3; i<7; i++ ) { + a.setPoint( 2*i, xx, yy ); + a.setPoint( 2*i+1, xx, yy+2 ); + xx++; yy--; + } + p->setPen( darkGreen ); + p->drawLineSegments( a ); + } + //////////////////////// + } + r += BoxSize + 4; + } + + p->translate( r, 0 ); + p->setPen( QPen( _cg.text() ) ); + QListViewItem::paintCell( p, _cg, column, width - r, align ); + if ( mTodo->cancelled () ) { + p->setPen( black ); + QRect br = p->boundingRect( 1,1,1,1,0,mTodo->summary() ); + int wid = br.width() +lineStart; + if ( wid > width-3 ) + wid = width-3; + p->drawLine( lineStart, height()/2+1, wid, height()/2+1 ); + + } + +} diff --git a/korganizer/kotodoviewitem.h b/korganizer/kotodoviewitem.h new file mode 100644 index 0000000..74dbe98 --- a/dev/null +++ b/korganizer/kotodoviewitem.h @@ -0,0 +1,93 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000, 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef KOTODOVIEWITEM_H +#define KOTODOVIEWITEM_H + +#include <qfont.h> +#include <qfontmetrics.h> +#include <qlineedit.h> +#include <qptrlist.h> +#include <qstrlist.h> +#include <qlistbox.h> +#include <qpopupmenu.h> +#include <qlabel.h> +#include <qmap.h> +#include <qlistview.h> +#include <qpainter.h> + +#include <libkcal/calendar.h> +#include <libkcal/todo.h> + +using namespace KCal; + +class KOTodoView; + +/** + This class provides a way of displaying a single Event of Todo-Type in a + KTodoView. + + @author Cornelius Schumacher <schumacher@kde.org> + @see KOTodoView +*/ +class KOTodoViewItem : public QCheckListItem +{ + public: + /** + Constructor. + + @param parent is the list view to which this item belongs. + @param ev is the event to have the item display information for. + */ + KOTodoViewItem(QListView *parent, Todo *todo, KOTodoView *kotodo); + KOTodoViewItem(KOTodoViewItem *parent, Todo *todo, KOTodoView *kotodo); + //~KOTodoViewItem() { qDebug("~KOTodoViewItem() %s ", text(0).latin1() );} + + void construct(); + + Todo *todo() { return mTodo; } + + QString key(int, bool) const; + + void setSortKey(int column,const QString &key); + + bool isAlternate(); + + virtual void paintCell(QPainter *p, const QColorGroup &cg, + int column, int width, int alignment); + virtual void setup(); + protected: +#if QT_VERSION >= 300 + void paintBranches(QPainter *p,const QColorGroup & cg,int w,int y,int h); +#else +#endif + virtual void stateChange(bool); + void setMyPixmap(); + + private: + Todo *mTodo; + KOTodoView *mTodoView; + + QMap<int,QString> mKeyMap; + uint m_odd : 1; + uint m_known : 1; + uint m_unused : 30; + bool m_init; +}; + +#endif diff --git a/korganizer/koviewmanager.cpp b/korganizer/koviewmanager.cpp new file mode 100644 index 0000000..88d69c6 --- a/dev/null +++ b/korganizer/koviewmanager.cpp @@ -0,0 +1,570 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2001 + Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qwidgetstack.h> + +#include <kconfig.h> +#include <kglobal.h> +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#else +#include <qapplication.h> +#endif +#include "calendarview.h" +#include "datenavigator.h" +#include "kotodoview.h" +#include "koagendaview.h" +#include "kodialogmanager.h" +#include "komonthview.h" +#include "kolistview.h" +#include "kowhatsnextview.h" +#include "kojournalview.h" +#include "kotimespanview.h" +#include "koprefs.h" +#include "navigatorbar.h" + +#include "koviewmanager.h" +#include "koviewmanager.moc" +//extern bool externFlagMonthviewBlockPainting; + +//bool globalFlagBlockPainting = false; +int globalFlagBlockAgenda = 0; +int globalFlagBlockLabel = 0; +int globalFlagBlockAgendaItemPaint = 1; +int globalFlagBlockAgendaItemUpdate = 1; + + +KOViewManager::KOViewManager( CalendarView *mainView ) : + QObject(), mMainView( mainView ) +{ + mCurrentView = 0; + + mWhatsNextView = 0; + mTodoView = 0; + mAgendaView = 0; + mMonthView = 0; + mListView = 0; + mJournalView = 0; + mTimeSpanView = 0; + mCurrentAgendaView = 0 ; + mFlagShowNextxDays = false; +} + +KOViewManager::~KOViewManager() +{ +} + + +KOrg::BaseView *KOViewManager::currentView() +{ + return mCurrentView; +} + +void KOViewManager::readSettings(KConfig *config) +{ + config->setGroup("General"); + QString view = config->readEntry("Current View"); + if (view == "WhatsNext") showWhatsNextView(); + else if (view == "Month") showMonthView(); + else if (view == "List") showListView(); + else if (view == "Journal") showJournalView(); + else if (view == "TimeSpan") showTimeSpanView(); + else if (view == "Todo") showTodoView(); + else { + showAgendaView(); + } +} + +void KOViewManager::writeSettings(KConfig *config) +{ + config->setGroup("General"); + + QString view; + if (mCurrentView == mWhatsNextView) view = "WhatsNext"; + else if (mCurrentView == mMonthView) view = "Month"; + else if (mCurrentView == mListView) view = "List"; + else if (mCurrentView == mJournalView) view = "Journal"; + else if (mCurrentView == mTimeSpanView) view = "TimeSpan"; + else if (mCurrentView == mTodoView) view = "Todo"; + else view = "Agenda"; + + config->writeEntry("Current View",view); + + if (mAgendaView) { + mAgendaView->writeSettings(config); + } + if (mTimeSpanView) { + mTimeSpanView->writeSettings(config); + } + if (mListView) { + mListView->writeSettings(config); + } + if (mTodoView) { + mTodoView->saveLayout(config,"Todo View"); + } +} + +void KOViewManager::showView(KOrg::BaseView *view, bool fullScreen ) +{ + + //mFlagShowNextxDays = false; + //if(view == mCurrentView) return; + if ( view == 0 ) { + view = mCurrentView; + if ( view == 0 ) + return; + } + bool full = fullScreen; + if(view == mCurrentView && view != mWhatsNextView ) { + if ( mCurrentAgendaView < 0 ) + return; + full = mMainView->leftFrame()->isVisible(); + } else { + mCurrentView = view; + + // bool full = fullScreen; + bool isFull = !mMainView->leftFrame()->isVisible(); + if ( isFull && KOPrefs::instance()->mViewChangeHoldFullscreen ) + full = true; + if ( !isFull && KOPrefs::instance()->mViewChangeHoldNonFullscreen ) + full = false; + } + if ( mAgendaView ) mAgendaView->deleteSelectedDateTime(); + raiseCurrentView( full ); + mMainView->processIncidenceSelection( 0 ); + mMainView->updateView(); + mMainView->adaptNavigationUnits(); +} + +void KOViewManager::raiseCurrentView( bool fullScreen ) +{ + //qDebug("raiseCurrentView "); + mCurrentAgendaView = 0; + int wid = mMainView->width() ; + int hei = mMainView->height(); + if ( mCurrentView == mMonthView ) { + mMainView->navigatorBar()->show(); + hei -= mMainView->navigatorBar()->sizeHint().height(); + //mMainView->navigatorBar()->hide(); + } else { + mMainView->navigatorBar()->hide(); + } + if ( fullScreen ) { + mMainView->leftFrame()->hide(); + } else { + mMainView->leftFrame()->show(); + if ( KOPrefs::instance()->mVerticalScreen ) + hei -= mMainView->leftFrame()->height(); + else + wid -= mMainView->leftFrame()->width(); + } + + if ( globalFlagBlockAgenda == 5 ) { + globalFlagBlockAgenda = 4; + globalFlagBlockAgendaItemPaint = 1; + } + mMainView->viewStack()->raiseWidget(mCurrentView); + if ( globalFlagBlockAgenda == 4 ) { + if ( mCurrentView == mAgendaView ) { + //globalFlagBlockAgenda =1 ; + if ( KOPrefs::instance()->mSetTimeToDayStartAt ) + mAgendaView->setStartHour( KOPrefs::instance()->mDayBegins ); + else if ( KOPrefs::instance()->mCenterOnCurrentTime ) + mAgendaView->setStartHour( QTime::currentTime ().hour() ); + qApp->processEvents(); + //qDebug("qApp->processEvents() "); + globalFlagBlockAgenda = 0; + mAgendaView->repaintAgenda(); + + } + globalFlagBlockAgenda = 0; + } + //qDebug("raiseCurrentView ende "); +} + +void KOViewManager::updateView() +{ + // qDebug("KOViewManager::updateView() "); + // if we are updating mTodoView, we get endless recursion + if ( mTodoView == mCurrentView ) + return; + if ( mCurrentView ) mCurrentView->updateView(); + +} + +void KOViewManager::updateView(const QDate &start, const QDate &end) +{ + // kdDebug() << "KOViewManager::updateView()" << endl; + + if (mCurrentView) mCurrentView->showDates(start, end); + + if (mTodoView) mTodoView->updateView(); +} + + +void KOViewManager::showWhatsNextView() +{ + if (!mWhatsNextView) { + mWhatsNextView = new KOWhatsNextView(mMainView->calendar(),mMainView->viewStack(), + "KOViewManager::WhatsNextView"); + mWhatsNextView->setEventViewer( mMainView->getEventViewerDialog()); + connect(mMainView, SIGNAL(configChanged()), mWhatsNextView, SLOT(updateConfig())); + addView(mWhatsNextView); + } + globalFlagBlockAgenda = 1; + showView(mWhatsNextView, true ); + mWhatsNextView->updateView(); + +} + +void KOViewManager::showListView() +{ + if (!mListView) { + mListView = new KOListView(mMainView->calendar(), mMainView->viewStack(), "KOViewManager::ListView"); + addView(mListView); + + connect(mListView, SIGNAL(showIncidenceSignal(Incidence *)), + mMainView, SLOT(showIncidence(Incidence *))); + connect(mListView, SIGNAL(editIncidenceSignal(Incidence *)), + mMainView, SLOT(editIncidence(Incidence *))); + connect(mListView, SIGNAL(deleteIncidenceSignal(Incidence *)), + mMainView, SLOT(deleteIncidence(Incidence *))); + connect( mListView, SIGNAL( incidenceSelected( Incidence * ) ), + mMainView, SLOT( processMainViewSelection( Incidence * ) ) ); + connect( mListView, SIGNAL( signalNewEvent() ), + mMainView, SLOT( newEvent() ) ); + connect(mMainView, SIGNAL(configChanged()), mListView, SLOT(updateConfig())); + connect( mListView, SIGNAL( cloneIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( cloneIncidence( Incidence * ) ) ); + connect( mListView, SIGNAL( cancelIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( cancelIncidence( Incidence * ) ) ); + connect( mListView, SIGNAL( moveIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( moveIncidence( Incidence * ) ) ); + connect( mListView, SIGNAL( beamIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( beamIncidence( Incidence * ) ) ); + } + // bool temp = mFlagShowNextxDays; + //globalFlagBlockPainting = true; + globalFlagBlockAgenda = 1; + if ( KOPrefs::instance()->mListViewMonthTimespan ) + mMainView->dateNavigator()->selectMonth(); + showView(mListView, KOPrefs::instance()->mFullViewTodo); + //mFlagShowNextxDays = temp; +} + +void KOViewManager::showAgendaView( bool fullScreen ) +{ + + mMainView->dialogManager()->hideSearchDialog(); + // qDebug("KOViewManager::showAgendaView "); + bool full; + full = fullScreen; + if (!mAgendaView) { + full = false; + mAgendaView = new KOAgendaView(mMainView->calendar(), mMainView->viewStack(), "KOViewManager::AgendaView"); + addView(mAgendaView); +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( mAgendaView, QPEApplication::RightOnHold ); +#endif + connect( mAgendaView, SIGNAL( incidenceChanged(Incidence *, int )), + mMainView, SLOT( changeIncidenceDisplay( Incidence *, int ) )); + + // SIGNALS/SLOTS FOR DAY/WEEK VIEW + connect(mAgendaView,SIGNAL(newEventSignal(QDateTime)), + mMainView, SLOT(newEvent(QDateTime))); + // connect(mAgendaView,SIGNAL(newEventSignal(QDateTime,QDateTime)), + // mMainView, SLOT(newEvent(QDateTime,QDateTime))); + connect(mAgendaView,SIGNAL(newEventSignal(QDate)), + mMainView, SLOT(newEvent(QDate))); + + connect(mAgendaView, SIGNAL(editIncidenceSignal(Incidence *)), + mMainView, SLOT(editIncidence(Incidence *))); + connect(mAgendaView, SIGNAL(showIncidenceSignal(Incidence *)), + mMainView, SLOT(showIncidence(Incidence *))); + connect(mAgendaView, SIGNAL(deleteIncidenceSignal(Incidence *)), + mMainView, SLOT(deleteIncidence(Incidence *))); + + connect( mAgendaView, SIGNAL( incidenceSelected( Incidence * ) ), + mMainView, SLOT( processMainViewSelection( Incidence * ) ) ); + + connect(mAgendaView, SIGNAL( toggleExpand() ), + mMainView, SLOT( toggleExpand() ) ); + + connect(mMainView, SIGNAL( calendarViewExpanded( bool ) ), + mAgendaView, SLOT( setExpandedButton( bool ) ) ); + connect( mAgendaView, SIGNAL( cloneIncidenceSignal(Incidence *) ), + mMainView, SLOT(cloneIncidence(Incidence *) ) ) ; + connect( mAgendaView, SIGNAL( cancelIncidenceSignal(Incidence *) ), + mMainView, SLOT(cancelIncidence(Incidence *) ) ) ; + connect(mMainView, SIGNAL(configChanged()), mAgendaView, SLOT(updateConfig())); + connect( mMainView, SIGNAL( todoModified( Todo *, int )), mAgendaView, + SLOT( updateTodo( Todo *, int ) ) ); + connect( mAgendaView,SIGNAL( todoMoved( Todo *, int )), + mMainView, SIGNAL( todoModified( Todo *, int ))); + connect( mAgendaView, SIGNAL( moveIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( moveIncidence( Incidence * ) ) ); + connect( mAgendaView, SIGNAL( beamIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( beamIncidence( Incidence * ) ) ); + mAgendaView->readSettings(); + mAgendaView->updateConfig(); + } + + showView( mAgendaView, full); + +} + +void KOViewManager::showDayView() +{ + mFlagShowNextxDays = false; + globalFlagBlockLabel = 1; + globalFlagBlockAgenda = 1; + if ( mCurrentAgendaView != 1 ) + mCurrentAgendaView = -1; + showAgendaView(); + qApp->processEvents(); + globalFlagBlockAgenda = 2; + globalFlagBlockLabel = 0; + mMainView->dateNavigator()->selectDates( 1 ); + mCurrentAgendaView = 1 ; + +} + +void KOViewManager::showWorkWeekView() +{ + mFlagShowNextxDays = false; + globalFlagBlockAgenda = 1; + globalFlagBlockLabel = 1; + if ( mCurrentAgendaView != 5 ) + mCurrentAgendaView = -1; + showAgendaView(); + qApp->processEvents(); + globalFlagBlockAgenda = 2; + globalFlagBlockLabel = 0; + mMainView->dateNavigator()->selectWorkWeek(); + mCurrentAgendaView = 5 ; + +} + +void KOViewManager::showWeekView() +{ + /* + globalFlagBlockAgenda = 2; + qDebug("4globalFlagBlockAgenda = 2; "); + //globalFlagBlockPainting = true; + mMainView->dateNavigator()->selectWeek(); + showAgendaView(); + */ + + + mFlagShowNextxDays = false; + globalFlagBlockAgenda = 1; + globalFlagBlockLabel = 1; + if ( mCurrentAgendaView != 7 ) + mCurrentAgendaView = -1; + showAgendaView(); + qApp->processEvents(); + globalFlagBlockAgenda = 2; + globalFlagBlockLabel = 0; + mMainView->dateNavigator()->selectWeek(); + mCurrentAgendaView = 7 ; +} + +void KOViewManager::showNextXView() +{ + + globalFlagBlockAgenda = 1; + if ( mCurrentAgendaView != 3 ) + mCurrentAgendaView = -1; + showAgendaView(KOPrefs::instance()->mFullViewMonth); + globalFlagBlockAgenda = 2; + mMainView->dateNavigator()->selectDates( QDate::currentDate(), + KOPrefs::instance()->mNextXDays ); + mFlagShowNextxDays = true; + mCurrentAgendaView = 3 ; +} +bool KOViewManager::showsNextDays() +{ + return mFlagShowNextxDays; +} +void KOViewManager::showMonthView() +{ + if (!mMonthView) { + mMonthView = new KOMonthView(mMainView->calendar(), mMainView->viewStack(), "KOViewManager::MonthView"); + + addView(mMonthView); + // mMonthView->show(); + // SIGNALS/SLOTS FOR MONTH VIEW + connect(mMonthView, SIGNAL(newEventSignal(QDateTime)), + mMainView, SLOT(newEvent(QDateTime))); + + connect(mMonthView, SIGNAL(showIncidenceSignal(Incidence *)), + mMainView, SLOT(showIncidence(Incidence *))); + connect(mMonthView, SIGNAL(editIncidenceSignal(Incidence *)), + mMainView, SLOT(editIncidence(Incidence *))); + connect(mMonthView, SIGNAL(deleteIncidenceSignal(Incidence *)), + mMainView, SLOT(deleteIncidence(Incidence *))); + + connect( mMonthView, SIGNAL( incidenceSelected( Incidence * ) ), + mMainView, SLOT( processMainViewSelection( Incidence * ) ) ); + connect( mMonthView, SIGNAL( cloneIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( cloneIncidence( Incidence * ) ) ); + connect( mMonthView, SIGNAL( cancelIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( cancelIncidence( Incidence * ) ) ); + + connect( mMonthView, SIGNAL( moveIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( moveIncidence( Incidence * ) ) ); + connect( mMonthView, SIGNAL( beamIncidenceSignal( Incidence * ) ), + mMainView, SLOT ( beamIncidence( Incidence * ) ) ); + connect( mMonthView, SIGNAL( selectWeekNum( int ) ), + mMainView, SLOT ( selectWeekNum( int ) ) ); + connect(mMainView, SIGNAL(configChanged()), mMonthView, SLOT(updateConfig())); + mMonthView->updateConfig(); + } + + globalFlagBlockAgenda = 1; + //mFlagShowNextxDays = false; + // if(mMonthView == mCurrentView) return; + mMainView->dateNavigator()->selectMonth(); + // DateList tmpList = mMainView->dateNavigator()->selectedDates( ); + //mMonthView->showDates(tmpList.first(), tmpList.last()); + + showView(mMonthView, true ); + +} + +void KOViewManager::showTodoView() +{ + //mFlagShowNextxDays = false; + if ( !mTodoView ) { + mTodoView = new KOTodoView( mMainView->calendar(), mMainView->viewStack(), + "KOViewManager::TodoView" ); + + addView( mTodoView ); + // QPEApplication::setStylusOperation( mTodoView, QPEApplication::RightOnHold ); + + // SIGNALS/SLOTS FOR TODO VIEW + connect( mTodoView, SIGNAL( newTodoSignal() ), + mMainView, SLOT( newTodo() ) ); + connect( mTodoView, SIGNAL( newSubTodoSignal( Todo * ) ), + mMainView, SLOT( newSubTodo( Todo *) ) ); + connect( mTodoView, SIGNAL( showTodoSignal( Todo *) ), + mMainView, SLOT( showTodo( Todo * ) ) ); + connect( mTodoView, SIGNAL( editTodoSignal( Todo * ) ), + mMainView, SLOT( editTodo( Todo * ) ) ); + connect( mTodoView, SIGNAL( deleteTodoSignal( Todo * ) ), + mMainView, SLOT( deleteTodo( Todo * ) ) ); + connect( mTodoView, SIGNAL( purgeCompletedSignal() ), + mMainView, SLOT( purgeCompleted() ) ); + + connect( mTodoView, SIGNAL( incidenceSelected( Incidence * ) ), + mMainView, SLOT( processMainViewSelection( Incidence * ) ) ); + + connect( mMainView, SIGNAL( configChanged() ), mTodoView, + SLOT( updateConfig() ) ); + connect( mMainView, SIGNAL( todoModified( Todo *, int )), mTodoView, + SLOT( updateTodo( Todo *, int ) ) ); + connect( mTodoView, SIGNAL( todoModifiedSignal( Todo *, int ) ), + mMainView, SIGNAL ( todoModified( Todo *, int ) ) ); + connect( mTodoView, SIGNAL( cloneTodoSignal( Incidence * ) ), + mMainView, SLOT ( cloneIncidence( Incidence * ) ) ); + connect( mTodoView, SIGNAL( cancelTodoSignal( Incidence * ) ), + mMainView, SLOT ( cancelIncidence( Incidence * ) ) ); + connect( mTodoView, SIGNAL( unparentTodoSignal( Todo * ) ), + mMainView, SLOT ( todo_unsub( Todo * ) ) ); + connect( mTodoView, SIGNAL( moveTodoSignal( Incidence * ) ), + mMainView, SLOT ( moveIncidence( Incidence * ) ) ); + connect( mTodoView, SIGNAL( beamTodoSignal( Incidence * ) ), + mMainView, SLOT ( beamIncidence( Incidence * ) ) ); + KConfig *config = KOGlobals::config(); + mTodoView->restoreLayout(config,"Todo View"); + } + + globalFlagBlockAgenda = 1; + showView( mTodoView, true ); + +} + +void KOViewManager::showJournalView() +{ + //mFlagShowNextxDays = false; + if (!mJournalView) { + mJournalView = new KOJournalView(mMainView->calendar(),mMainView->viewStack(), + "KOViewManager::JournalView"); + connect( mMainView, SIGNAL( configChanged() ), mJournalView, + SLOT( updateConfig() ) ); + connect(mJournalView, SIGNAL(deleteJournal(Journal *) ), mMainView,SLOT(deleteJournal(Journal *)) ); + addView(mJournalView); + } + + showView(mJournalView); +} + +void KOViewManager::showTimeSpanView() +{ + //mFlagShowNextxDays = false; + if (!mTimeSpanView) { + mTimeSpanView = new KOTimeSpanView(mMainView->calendar(),mMainView->viewStack(), + "KOViewManager::TimeSpanView"); + addView(mTimeSpanView); + + mTimeSpanView->readSettings(); + } + + showView(mTimeSpanView); +} + +Incidence *KOViewManager::currentSelection() +{ + if (!mCurrentView) return 0; + if ( mCurrentView == mListView ) { + if ( mListView->currentItem() ) + return mListView->currentItem(); + } + return mCurrentView->selectedIncidences().first(); +} + +QDate KOViewManager::currentSelectionDate() +{ + QDate qd; + if (mCurrentView) { + DateList qvl = mCurrentView->selectedDates(); + if (!qvl.isEmpty()) qd = qvl.first(); + } + return qd; +} + +void KOViewManager::addView(KOrg::BaseView *view) +{ +#if QT_VERSION >= 300 + mMainView->viewStack()->addWidget( view ); +#else + mMainView->viewStack()->addWidget( view, 1 ); +#endif +} + +void KOViewManager::setDocumentId( const QString &id ) +{ + if (mTodoView) mTodoView->setDocumentId( id ); +} diff --git a/korganizer/koviewmanager.h b/korganizer/koviewmanager.h new file mode 100644 index 0000000..f814c36 --- a/dev/null +++ b/korganizer/koviewmanager.h @@ -0,0 +1,113 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 + Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KOVIEWMANAGER_H +#define KOVIEWMANAGER_H + +#include <qobject.h> + +#include <korganizer/baseview.h> + +class CalendarView; + +class KOListView; +class KOAgendaView; +class KOMonthView; +class KOTimeSpanView; +class KOTodoView; +class KOWhatsNextView; +class KOJournalView; + +using namespace KCal; + +/** + This class manages the views of the calendar. It owns the objects and handles + creation and selection. +*/ +class KOViewManager : public QObject +{ + Q_OBJECT + public: + KOViewManager( CalendarView * ); + virtual ~KOViewManager(); + + /** changes the view to be the currently selected view */ + void showView(KOrg::BaseView *, bool fullScreen = false ); + + void readSettings(KConfig *config); + void writeSettings(KConfig *config); + bool showsNextDays(); + /** Read which view was shown last from config file */ + void readCurrentView(KConfig *); + /** Write which view is currently shown to config file */ + void writeCurrentView(KConfig *); + + KOrg::BaseView *currentView(); + + void setDocumentId( const QString & ); + + void updateView(); + void updateView( const QDate &start, const QDate &end ); + + void raiseCurrentView( bool fullScreen = false ); + + void addView(KOrg::BaseView *); + + Incidence *currentSelection(); + QDate currentSelectionDate(); + + KOAgendaView *agendaView() const { return mAgendaView; } + + public slots: + void showWhatsNextView(); + void showListView(); + void showAgendaView( bool fullScreen = false ); + void showDayView(); + void showWorkWeekView(); + void showWeekView(); + void showNextXView(); + void showMonthView(); + void showTodoView(); + void showJournalView(); + void showTimeSpanView(); + + private: + CalendarView *mMainView; + + int mCurrentAgendaView; + KOAgendaView *mAgendaView; + KOListView *mListView; + KOMonthView *mMonthView; + KOTodoView *mTodoView; + KOWhatsNextView *mWhatsNextView; + KOJournalView *mJournalView; + KOTimeSpanView *mTimeSpanView; + + KOrg::BaseView *mCurrentView; // currently active event view + + int mAgendaViewMode; + bool mFlagShowNextxDays; + +}; + +#endif diff --git a/korganizer/koviewmanager.moc b/korganizer/koviewmanager.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/koviewmanager.moc diff --git a/korganizer/kowhatsnextview.cpp b/korganizer/kowhatsnextview.cpp new file mode 100644 index 0000000..ffaea37 --- a/dev/null +++ b/korganizer/kowhatsnextview.cpp @@ -0,0 +1,650 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <qlayout.h> +#include <qtextbrowser.h> +#include <qtextcodec.h> +#include <qfileinfo.h> +#include <qlabel.h> + +#include <qapplication.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kmessagebox.h> + +#include <libkcal/calendar.h> + +#ifndef KORG_NOPRINTER +#include "calprinter.h" +#endif +#include "koglobals.h" +#include "koprefs.h" +#include "koeventviewerdialog.h" + +#include "kowhatsnextview.h" +using namespace KOrg; +#include "kowhatsnextview.moc" + +void WhatsNextTextBrowser::setSource(const QString& n) +{ + + if (n.startsWith("event:")) { + emit showIncidence(n); + return; + } else if (n.startsWith("todo:")) { + emit showIncidence(n); + return; + } else { + QTextBrowser::setSource(n); + } +} + +KOWhatsNextView::KOWhatsNextView(Calendar *calendar, QWidget *parent, + const char *name) + : KOrg::BaseView(calendar, parent, name) +{ + // mDateLabel = + // new QLabel(KGlobal::locale()->formatDate(QDate::currentDate()),this); + // mDateLabel->setMargin(2); + // mDateLabel->setAlignment(AlignCenter); + setFont( KOPrefs::instance()->mWhatsNextFont ); + mView = new WhatsNextTextBrowser(this); + connect(mView,SIGNAL(showIncidence(const QString &)),SLOT(showIncidence(const QString &))); + + mEventViewer = 0; + + QBoxLayout *topLayout = new QVBoxLayout(this); + // topLayout->addWidget(mDateLabel); + topLayout->addWidget(mView); +} + +KOWhatsNextView::~KOWhatsNextView() +{ +} + +int KOWhatsNextView::maxDatesHint() +{ + return 0; +} + +int KOWhatsNextView::currentDateCount() +{ + return 0; +} + +QPtrList<Incidence> KOWhatsNextView::selectedIncidences() +{ + QPtrList<Incidence> eventList; + + return eventList; +} + + +void KOWhatsNextView::printPreview(CalPrinter *calPrinter, const QDate &fd, + const QDate &td) +{ +#ifndef KORG_NOPRINTER + calPrinter->preview(CalPrinter::Day, fd, td); +#endif +} +void KOWhatsNextView::updateConfig() +{ + setFont( KOPrefs::instance()->mWhatsNextFont ); + updateView(); + +} +void KOWhatsNextView::updateView() +{ + + // mDateLabel->setText(KGlobal::locale()->formatDate(QDate::currentDate())); + KIconLoader kil("korganizer"); + QString ipath;// = new QString(); + // kil.loadIcon("korganizer",KIcon::NoGroup,32,KIcon::DefaultState,&ipath); + //<big><big><strong>" + date + "</strong></big></big>\n"; + mText = "<table width=\"100%\">\n"; + //mText += "<tr bgcolor=\"#3679AD\"><td><h2>"; +#ifdef DESKTOP_VERSION + mText += "<tr bgcolor=\"#5699CD\"><td align=\"center\"><h1>"; +#else + mText += "<tr bgcolor=\"#5699CD\"><td align=\"center\"><h2>"; +#endif + // mText += "<img src=\""; + // mText += ipath; + // mText += "\">"; + mEventDate = QDate::currentDate(); +#ifdef DESKTOP_VERSION + mText += "<font color=\"#FFFFFF\"> <em>" + KGlobal::locale()->formatDate( mEventDate , false )+"</em></font></h1>"; +#else + mText += "<font color=\"#FFFFFF\"> <em>" + KGlobal::locale()->formatDate( mEventDate , false )+"</em></font></h2>"; +#endif + mText += "</td></tr>\n<tr bgcolor=\"#EAF8FA\"><td>"; + int iii; + mTodos.clear(); + QPtrList<Event> events; + QPtrList<Todo> todos = calendar()->todos(); + Todo * todo; + //mText += "<h2>" + i18n("Events: ") + "</h2>\n"; + int daysToShow = KOPrefs::instance()->mWhatsNextDays ; + bool itemAdded = false; + for ( iii = 0; iii < daysToShow; ++iii ) { + QString date; + itemAdded = false; + events = calendar()->events( mEventDate, true ); + + if ( iii == 0 ) { // today !!! + todo = todos.first(); + while(todo) { + if ( !todo->isCompleted() &&todo->hasDueDate() && todo->dtDue().date() < mEventDate ) { + if ( ! itemAdded ) { + appendDay ( iii, mEventDate ); + itemAdded = true; + + } + appendEvent(todo); + } + todo = todos.next(); + } + } + + + if (events.count() > 0) { + // mText += "<p></p>"; + // kil.loadIcon("month",KIcon::NoGroup,22,KIcon::DefaultState,&ipath); + // mText += "<h2>"; + //mText += " <img src=\""; + //mText += ipath; + //mText += "\">"; + if ( ! itemAdded ) { + appendDay ( iii, mEventDate ); + itemAdded = true; + + } + Event *ev = events.first(); + while(ev) { + //qDebug("+++++event append %s", ev->summary().latin1()); + if ( true /*!ev->recurrence()->doesRecur() || ev->recursOn( mEventDate)*/) { + appendEvent(ev, false , iii!= 0 ); + } + ev = events.next(); + } + + //mText += "</table>\n"; + } + + todo = todos.first(); + while(todo) { + if ( !todo->isCompleted() &&todo->hasDueDate() && todo->dtDue().date() == mEventDate ) { + if ( ! itemAdded ) { + appendDay ( iii, mEventDate ); + itemAdded = true; + } + appendEvent(todo); + } + todo = todos.next(); + } + if ( !itemAdded && iii == 0 ) { + // appendDay ( iii, mEventDate ); + //mText += "<table>"; + // mText += "<b><font color=\"#000080\"><em>"+i18n("No event, nothing to do.") +"</em></font></b>\n"; + mText += "<h3 align=\"center\"><font color=\"#008000\"><em>"+i18n("No event, nothing to do. ") +"</em></font></h3>\n"; + //mText +="</table>"; + } + if ( itemAdded ) + mText += "</table>\n"; + mEventDate = mEventDate.addDays( 1 ); + } + + int topmostPrios = KOPrefs::instance()->mWhatsNextPrios; + if (todos.count() > 0 && topmostPrios > 0 ) { + // kil.loadIcon("todo",KIcon::NoGroup,22,KIcon::DefaultState,&ipath); + // mText += "<h2>"; + //<img src=\""; + // mText += ipath; + // mText += "\">"; + // mText += i18n("Overdue To-Do:") + "</h2>\n"; + + //mText += "<ul>\n"; + bool gotone = false; + int priority = 1; + int priosFound = 0; +#ifdef DESKTOP_VERSION + mText +="<p></p>"; +#endif + + mText +="<big><big><strong><em><font color=\"#000080\">" + i18n("Incomplete Todo:") + "</font></em></strong></big></big>\n"; + mText += "<ul>\n"; + while (!gotone && priority<6) { + todo = todos.first(); + while(todo) { + if (!todo->isCompleted() && (todo->priority() == priority) ) { + if ( appendTodo(todo) ) + gotone = true; + } + todo = todos.next(); + } + if ( gotone ) { + gotone = false; + ++priosFound; + if ( priosFound == topmostPrios ) + break; + } + priority++; + // kdDebug() << "adding the todos..." << endl; + } + mText += "</ul>\n"; + } + + int replys = 0; + events = calendar()->events(QDate::currentDate(), QDate(2975,12,6)); + if (events.count() > 0) { + Event *ev = events.first(); + while(ev) { + Attendee *me = ev->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email()); + if (me!=0) { + if (me->status()==Attendee::NeedsAction && me->RSVP()) { + if (replys == 0) { + mText += "<p></p>"; + // kil.loadIcon("reply",KIcon::NoGroup,22,KIcon::DefaultState,&ipath); + mText += "<h2>"; + //<img src=\""; + // mText += ipath; + // mText += "\">"; + mText += i18n("Events and To-Dos that need a reply:") + "</h2>\n"; + mText += "<table>\n"; + } + replys++; + appendEvent(ev,true); + } + } + ev = events.next(); + } + } + todos = calendar()->todos(); + if (todos.count() > 0) { + Todo *to = todos.first(); + while(to) { + Attendee *me = to->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email()); + if (me!=0) { + if (me->status()==Attendee::NeedsAction && me->RSVP()) { + if (replys == 0) { + mText += "<p></p>"; + // kil.loadIcon("reply",KIcon::NoGroup,22,KIcon::DefaultState,&ipath); + mText += "<h2>"; + //<img src=\""; + // mText += ipath; + // mText += "\">"; + mText += i18n("Events and To-Dos that need a reply:") + "</h2>\n"; + mText += "<table>\n"; + } + replys++; + appendEvent(to); + } + } + kdDebug () << "check for todo-replys..." << endl; + to = todos.next(); + } + } + if (replys > 0 ) mText += "</table>\n"; + + + mText += "</td></tr>\n</table>\n"; + + kdDebug() << "KOWhatsNextView::updateView: text: " << mText << endl; + mView->setText(mText); + mView->setFocus(); + + // QPixmap bPix = SmallIcon( "back" ); + // qDebug("xxxxxxxxxxxxxxxxxxxxx "); + // QWidget* test = new QWidget(); + // test->setBackgroundMode(FixedPixmap ); + // test->setBackgroundPixmap ( bPix ); + // test->resize( 300, 400 ); + // test->show(); + // mView->setBackgroundMode(FixedPixmap ); + // mView->setBackgroundPixmap ( bPix ); +} + +void KOWhatsNextView::appendDay( int i, QDate eventDate ) +{ + QString date; + QString day = KGlobal::locale()->formatDate( eventDate , KOPrefs::instance()->mShortDateInViewer); + if ( ! KOPrefs::instance()->mShortDateInViewer && QApplication::desktop()->width() < 320 ) { + if ( i == 0 ) { + mText += "<table>\n"; + return;//date = "<em><font color=\"#008000\"><em>" + day+"</font></em>"; + } + else if ( i == 1 ) + date = "<em><font color=\"#000080\">" + day + "</font></em>" ; + else date = "<em><font color=\"#000080\">" + day + "</font></em>"; + //mText += "<h2>" + date + "</h2>\n"; + mText += "<big><big><strong>" + date + "</strong></big></big>\n"; + mText += "<table>\n"; + + + + } else { + if ( i == 0 ) { + mText += "<table>\n"; + return;// date = "<font color=\"#008000\"><em>" +i18n("Today: ") +"</em>" + day+"</font>"; + } + +#ifdef DESKTOP_VERSION + else if ( i == 1 ) { + date = "<h2><em><font color=\"#000080\">" + i18n("Tomorrow: ") + day +"</font></em></h2>" ; + } + else date = "<h2><em><font color=\"#000080\">" + i18n("In %1 days: ").arg( i ) +day + "</font></em></h2>"; +#else + else if ( i == 1 ) { + date = "<em><font color=\"#000080\">" + i18n("Tomorrow: ") + day +"</font></em>" ; + } + else date = "<em><font color=\"#000080\">" + i18n("In %1 days: ").arg( i ) +day + "</font></em>"; + +#endif + //mText += "<h2>" + date + "</h2>\n"; + mText += "<big><big><strong>" + date + "</strong></big></big>\n"; + mText += "<table>\n"; + } +} + + +void KOWhatsNextView::showDates(const QDate &, const QDate &) +{ + updateView(); +} + +void KOWhatsNextView::showEvents(QPtrList<Event>) +{ +} + +void KOWhatsNextView::changeEventDisplay(Event *, int action) +{ + switch(action) { + case KOGlobals::EVENTADDED: + updateView(); + break; + case KOGlobals::EVENTEDITED: + updateView(); + break; + case KOGlobals::EVENTDELETED: + updateView(); + break; + default: + updateView(); + kdDebug() << "KOWhatsNextView::changeEventDisplay(): Illegal action " << action << endl; + } +} + +void KOWhatsNextView::appendEvent(Incidence *ev, bool reply, bool notRed ) +{ + if ( !KOPrefs::instance()->mShowSyncEvents && ev->uid().left(21) == QString("last-syncEvent-device") ) + return; + QDateTime cdt = QDateTime::currentDateTime(); + mText += "<tr><td><b>"; + if (ev->type()=="Event") { + + if (!ev->doesFloat()) { + Event *event = static_cast<Event *>(ev); + QDateTime st,end; + if ( event->recurrence()->doesRecur() ) { + QDate recDate= mEventDate; + int days = event->dtStart().date().daysTo (event->dtEnd().date() ); + while ( ! event->recursOn( recDate ) ) { + recDate = recDate.addDays( -1 ); + + } + st = QDateTime ( recDate, event->dtStart().time() ); + end = QDateTime ( recDate.addDays( days ), event->dtEnd().time() ); + } + else { + st = event->dtStart(); + end = event->dtEnd(); + } + + if (reply) mText += "on " + event->dtStartDateStr() + ": "; + QString dateText; + // qDebug("%s %s %s %s ", mEventDate.toString().latin1(),event->summary().latin1(), st .toString().latin1(),end.toString().latin1() ); + if ( st.date() < mEventDate ) + dateText = "++:++-"; + else + dateText = event->dtStartTimeStr() + "-"; + if ( end.date() > mEventDate ) + dateText += "++:++"; + else + dateText += event->dtEndTimeStr(); + if ( notRed ) + mText += dateText; + else { + if ( end < cdt ) + mText += "<font color=\"#F00000\">" + dateText + "</font>"; + else if ( st < cdt ) + mText += "<font color=\"#008000\">" + dateText + "</font>"; + else + mText += dateText; + } + + } else { + mText += i18n("Allday:"); + + } + } else { + mTodos.append( ev ); + mText += i18n("ToDo:"); + if ( ((Todo*)ev)->dtDue().date() < QDate::currentDate() ) { + // mText +="<font color=\"#F00000\">" + i18n("O-due!") + "</font>"; + QString dfs = KGlobal::locale()->dateFormatShort(); + KGlobal::locale()->setIntDateFormat( 3 ); + KGlobal::locale()->setDateFormatShort("%d.%b"); + mText +="<font color=\"#F00000\">" + KGlobal::locale()->formatDate(((Todo*)ev)->dtDue().date(), true) + "</font>"; + + KGlobal::locale()->setDateFormatShort(dfs); + KGlobal::locale()->setIntDateFormat( KOPrefs::instance()->mPreferredDate ); + } else { + if (!ev->doesFloat() ) + if( ( (Todo*)ev)->dtDue() < cdt ) { + mText +="<font color=\"#F00000\">" + ((Todo*)ev)->dtDueTimeStr() + "</font>"; + + + } else + mText +=((Todo*)ev)->dtDueTimeStr(); + mTodos.append( ev ); + } + } + mText += "</b></td><td>"; + bool needClose = false; + if ( ev->cancelled() ) { + mText += "<font color=\"#F00000\">[c"; + needClose =true; + + } + if ( ev->isAlarmEnabled() ) { + if ( !needClose) + mText +="["; + mText += "a"; + needClose =true; + + } + if ( ev->description().length() > 0 ) { + if ( !needClose) + mText +="["; + mText += "i"; + needClose =true; + } + if ( ev->recurrence()->doesRecur() ) { + if ( !needClose) + mText +="["; + mText += "r"; + needClose =true; + } + if ( needClose ) { + mText += "] "; + } + if ( ev->cancelled() ) + mText += "</font>"; + mText += "<a "; + if (ev->type()=="Event") mText += "href=\"event:"; + if (ev->type()=="Todo") mText += "href=\"todo:"; + mText += ev->uid() + "\">"; + if ( ev->summary().length() > 0 ) + mText += ev->summary(); + else + mText += i18n("-no summary-"); + mText += "</a>"; + if ( KOPrefs::instance()->mWNViewShowLocation ) + if ( !ev->location().isEmpty() ) + mText += " ("+ev->location() +")"; + if ( ev->relatedTo() && KOPrefs::instance()->mWNViewShowsParents) + mText += " ["+ev->relatedTo()->summary() +"]"; + mText += "</td></tr>\n"; +} + +bool KOWhatsNextView::appendTodo(Incidence *ev, QString ind , bool isSub ) +{ + if ( mTodos.find( ev ) != mTodos.end() ) return false; + + mTodos.append( ev ); + if ( !isSub ) + mText += "<p>"; + else + mText += "<li>"; + mText += "[" +QString::number(ev->priority()) + "/" + QString::number(((Todo*)ev)->percentComplete())+"%] "; + + + mText += ind; + bool needClose = false; + if ( ev->cancelled() ) { + mText += "<font color=\"#F00000\">[c"; + needClose =true; + + } + if ( ev->isAlarmEnabled() ) { + if ( !needClose) + mText +="["; + mText += "a"; + needClose =true; + + } + + if ( ev->description().length() > 0 ) { + if ( !needClose) + mText +="["; + mText += "i"; + needClose =true; + } + // if ( ev->recurrence()->doesRecur() ) { + // if ( !needClose) + // mText +="("; + // mText += "r"; + // needClose =true; + // } + if ( needClose ) + mText += "] "; + if ( ev->cancelled() ) + mText += "</font>"; + mText += "<a href=\"todo:" + ev->uid() + "\">"; + mText += ev->summary(); + mText += "</a>"; + if ( ((Todo*)ev)->hasDueDate () ) { + QString year = ""; + int ye = ((Todo*)ev)->dtDue().date().year(); + if ( QDateTime::currentDateTime().date().year() != ye ) + year = QString::number( ye ); + QString dfs = KGlobal::locale()->dateFormatShort(); + KGlobal::locale()->setIntDateFormat( 3 ); + KGlobal::locale()->setDateFormatShort("%d.%b"); + mText +="<font color=\"#00A000\"> [" + KGlobal::locale()->formatDate(((Todo*)ev)->dtDue().date(), true) + "."+ year +"]</font>"; + + KGlobal::locale()->setDateFormatShort(dfs); + KGlobal::locale()->setIntDateFormat( KOPrefs::instance()->mPreferredDate ); + } + if ( KOPrefs::instance()->mWNViewShowLocation ) + if ( !ev->location().isEmpty() ) + mText += " ("+ev->location() +")"; + if ( !isSub ) { + if ( ((Todo*)ev)->relatedTo()&& KOPrefs::instance()->mWNViewShowsParents) + mText += " ["+ev->relatedTo()->summary() +"]"; + mText += "</p>\n"; + } + else { + ind += "-"; + mText += "</li>\n"; + } + QPtrList<Incidence> Relations = ev->relations(); + Incidence *to; + for (to=Relations.first();to;to=Relations.next()) { + if (!((Todo*)to)->isCompleted()) + appendTodo( to, ind , true ); + } + + return true; +} + +/* + void KOWhatsNextView::createEventViewer() + { + if (!mEventViewer) { + + mEventViewer = new KOEventViewerDialog(this); + } + } +*/ +void KOWhatsNextView::setEventViewer(KOEventViewerDialog* v ) +{ + if ( mEventViewer ) + delete mEventViewer; + mEventViewer = v; +} + +// TODO: Create this function in CalendarView and remove it from here +void KOWhatsNextView::showIncidence(const QString &uid) +{ + if ( !mEventViewer ) { + qDebug("KOWhatsNextView::showIncidence::sorry, no event viewer set "); + return; + } + //kdDebug() << "KOWhatsNextView::showIncidence(): " << uid << endl; + //qDebug("KOWhatsNextView::showIncidence %s ", uid.latin1()); + if (uid.startsWith("event:")) { +#ifdef DESKTOP_VERSION + Event *event = calendar()->event(uid.mid(8)); +#else + Event *event = calendar()->event(uid.mid(6)); +#endif + //qDebug("event %d uid %s ", event, uid.mid(6).latin1()); + if (!event) return; + //createEventViewer(); + mEventViewer->setEvent(event); + } else if (uid.startsWith("todo:")) { +#ifdef DESKTOP_VERSION + Todo *todo = calendar()->todo(uid.mid(7)); +#else + Todo *todo = calendar()->todo(uid.mid(5)); +#endif + if (!todo) return; + //createEventViewer(); + mEventViewer->setTodo(todo); + } else { + return; + + } + mEventViewer->showMe(); + mEventViewer->raise(); +} diff --git a/korganizer/kowhatsnextview.h b/korganizer/kowhatsnextview.h new file mode 100644 index 0000000..fff769a --- a/dev/null +++ b/korganizer/kowhatsnextview.h @@ -0,0 +1,91 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef KOWHATSNEXTVIEW_H +#define KOWHATSNEXTVIEW_H + +#include <qtextbrowser.h> + +#include <korganizer/baseview.h> + +class QListView; +class QLabel; + +class KOEventViewerDialog; + +class WhatsNextTextBrowser : public QTextBrowser { + Q_OBJECT + public: + WhatsNextTextBrowser(QWidget *parent) : QTextBrowser(parent) {} + + void setSource(const QString &); + + signals: + void showIncidence(const QString &uid); +}; + + +/** + This class provides a view of the next events and todos +*/ +class KOWhatsNextView : public KOrg::BaseView +{ + Q_OBJECT + public: + KOWhatsNextView(Calendar *calendar, QWidget *parent = 0, + const char *name = 0); + ~KOWhatsNextView(); + + virtual int maxDatesHint(); + virtual int currentDateCount(); + void setEventViewer(KOEventViewerDialog* v ); + virtual QPtrList<Incidence> selectedIncidences(); + DateList selectedDates() + {DateList q; + return q;} + virtual void printPreview(CalPrinter *calPrinter, + const QDate &, const QDate &); + + public slots: + virtual void updateView(); + virtual void showDates(const QDate &start, const QDate &end); + virtual void showEvents(QPtrList<Event> eventList); + void updateConfig(); + void changeEventDisplay(Event *, int); + + protected: + void appendEvent(Incidence *, bool reply=false, bool notRed = true); + bool appendTodo(Incidence *, QString ind = "", bool isSub = false ); + void appendDay( int i, QDate date ); + QDate mEventDate; + + private slots: + void showIncidence(const QString &); + + private: + //void createEventViewer(); + + QTextBrowser *mView; + QString mText; + // QLabel *mDateLabel; + KOEventViewerDialog *mEventViewer; + + QValueList<Incidence *> mTodos; +}; + +#endif diff --git a/korganizer/kowhatsnextview.moc b/korganizer/kowhatsnextview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kowhatsnextview.moc diff --git a/korganizer/kprefsdialog.moc b/korganizer/kprefsdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/kprefsdialog.moc diff --git a/korganizer/ktimeedit.cpp b/korganizer/ktimeedit.cpp new file mode 100644 index 0000000..f9720f6 --- a/dev/null +++ b/korganizer/ktimeedit.cpp @@ -0,0 +1,528 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1999 Preston Brown, Ian Dawes + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qkeycode.h> +#include <qcombobox.h> +#include <qdatetime.h> +#include <qlineedit.h> +#include <qapplication.h> + +#include <kmessagebox.h> +#include <kglobal.h> +#include <kdebug.h> +#include <klocale.h> + +#include "ktimeedit.h" +#include "koprefs.h" +#include <qvalidator.h> +#include "ktimeedit.moc" + +// Validator for a time value with only hours and minutes (no seconds) +// Mostly locale aware. Author: David Faure <faure@kde.org> +class KOTimeValidator : public QValidator +{ +public: + KOTimeValidator(QWidget* parent, const char* name=0) : QValidator(parent, name) {} + + virtual State validate(QString& str, int& /*cursorPos*/) const + { + return Acceptable; + bool ok = false; + // TODO use KLocale::WithoutSeconds in HEAD + /*QTime time =*/ KGlobal::locale()->readTime(str, &ok); + if ( ok ) + return Acceptable; + // readTime doesn't help knowing when the string is "Intermediate". + int length = str.length(); + if ( !str ) // empty string? + return Invalid; // there should always be a ':' in it, right? + // HACK. Not fully locale aware etc. (esp. the separator is '.' in sv_SE...) + QChar sep = ':'; + // I want to allow "HH:", ":MM" and ":" to make editing easier + if ( str[0] == sep ) + { + if ( length == 1 ) // just ":" + return Intermediate; + QString minutes = str.mid(1); + int m = minutes.toInt(&ok); + if ( ok && m >= 0 && m < 60 ) + return Intermediate; + } else if ( str.at(str.length()-1) == sep ) + { + QString hours = str.left(length-1); + int h = hours.toInt(&ok); + if ( ok && h >= 0 && h < 24 ) + return Intermediate; + } + return Invalid; + } +}; + +// KTimeWidget/QTimeEdit provide nicer editing, but don't provide a combobox. +// Difficult to get all in one... +// But Qt-3.2 will offer QLineEdit::setMask, so a "99:99" mask would help. +KOTimeEdit::KOTimeEdit(QWidget *parent, QTime qt, const char *name) + : QComboBox(TRUE, parent, name) +{ + setInsertionPolicy(NoInsertion); + setValidator( new KOTimeValidator( this ) ); + mFlagKeyPressed = false; + + if ( QApplication::desktop()->width() < 650 ) + setSizeLimit ( 6 ); + mTime = qt; + +// mNoTimeString = i18n("No Time"); +// insertItem( mNoTimeString ); + + // Fill combo box with selection of times in localized format. + QTime timeEntry(0,0,0); + do { + insertItem(KGlobal::locale()->formatTime(timeEntry)); + timeEntry = timeEntry.addSecs(60*15); + } while (!timeEntry.isNull()); + // Add end of day. + insertItem( KGlobal::locale()->formatTime( QTime( 23, 59, 59 ) ) ); + + updateText(); + setFocusPolicy(QWidget::StrongFocus); + + connect(this, SIGNAL(activated(int)), this, SLOT(activ(int))); + connect(this, SIGNAL(highlighted(int)), this, SLOT(hilit(int))); + connect(this,SIGNAL(textChanged(const QString&)),this,SLOT(changedText())); + QFontMetrics fm ( font() ); + QString timeString = "24:00"; + if ( KOPrefs::instance()->mPreferredTime == 1 ) + timeString = "02:00pm"; + int addSpace = 32; + if ( QApplication::desktop()->width() > 320 ) + timeString += ":00"; + setFixedWidth(fm.width( timeString ) + 32 ); + + // Highlight Background and Textcolor change from default + QPalette palette = QWidget::palette(); + unsigned char red, green, blue; + red = palette.color( QPalette::Normal , QColorGroup::Background ).red() - 10; + green = palette.color( QPalette::Normal , QColorGroup::Background ).green() - 10; + blue = palette.color( QPalette::Normal , QColorGroup::Background ).blue() - 10; + palette.setColor( QColorGroup::Highlight, QColor(red,green,blue) ); + palette.setColor( QColorGroup::HighlightedText, palette.color( QPalette::Normal , QColorGroup::Foreground ) ); + setPalette( palette ); +} + +KOTimeEdit::~KOTimeEdit() +{ +} + +bool KOTimeEdit::hasTime() const +{ + // Can't happen + if ( currentText().isEmpty() ) return false; + //if ( currentText() == mNoTimeString ) return false; + + return true; // always +} + +QTime KOTimeEdit::getTime() const +{ + //kdDebug(5850) << "KOTimeEdit::getTime(), currentText() = " << currentText() << endl; + // TODO use KLocale::WithoutSeconds in HEAD + QTime time = KGlobal::locale()->readTime(currentText()); + // kdDebug(5850) << "KOTimeEdit::getTime(): " << time.toString() << endl; + return time; +} +/* +QSizePolicy KOTimeEdit::sizePolicy() const +{ + // Set size policy to Fixed, because edit cannot contain more text than the + // string representing the time. It doesn't make sense to provide more space. + QSizePolicy sizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + + return sizePolicy; +} +*/ +void KOTimeEdit::setTime(QTime newTime) +{ + if ( mTime != newTime ) + { + kdDebug(5850) << "KOTimeEdit::setTime(): " << newTime.toString() << endl; + + mTime = newTime; + updateText(); + } + +} + +void KOTimeEdit::activ(int i) +{ + // The last entry, 23:59, is a special case + if( i == count() - 1 ) + mTime = QTime( 23, 59, 0 ); + else + mTime = QTime(0,0,0).addSecs(i*15*60); + emit timeChanged(mTime); +} + +void KOTimeEdit::hilit(int ) +{ + // we don't currently need to do anything here. +} + +void KOTimeEdit::addTime(QTime qt, bool update) +{ + // Calculate the new time. + //qDebug("add h %d min %d ", qt.hour(),qt.minute() ); + mTime = mTime.addSecs(qt.minute()*60+qt.hour()*3600); + // if ( update ) + updateText(); + emit timeChanged(mTime); +} + +void KOTimeEdit::subTime(QTime qt, bool update) +{ + int h, m; + //qDebug("sub h %d min %d ", qt.hour(),qt.minute() ); + + mTime = mTime.addSecs(-(qt.minute()*60+qt.hour()*3600)); + // store the newly calculated time. + // mTime.setHMS(h, m, 0); + //if ( update ) + updateText(); + emit timeChanged(mTime); +} + +// void KOTimeEdit::mouseReleaseEvent ( QMouseEvent * ) +// { +// qDebug("mouseReleaseEvent ( QMouseEvent * ) "); +// } + +// void KOTimeEdit::focusInEvent ( QFocusEvent * ) +// { +// qDebug("focusInEvent ( QFocusEvent * ) "); +// } + +void KOTimeEdit::keyReleaseEvent(QKeyEvent *e) +{ + if ( !e->isAutoRepeat() ) { + mFlagKeyPressed = false; + } + +} +void KOTimeEdit::setSelect( int from, int to ) +{ + if ( KOPrefs::instance()->mHightlightDateTimeEdit) + lineEdit()->setSelection( from , to ); +} + + +void KOTimeEdit::keyPressEvent(QKeyEvent *e) +{ + + qApp->processEvents(); + bool hour12Format = ( KOPrefs::instance()->mPreferredTime == 1 ); + int maxpos = hour12Format?7:5; + if ( e->isAutoRepeat() && !mFlagKeyPressed ) { + e->ignore(); + // qDebug(" ignore %d",e->isAutoRepeat() ); + return; + } + if (! e->isAutoRepeat() ) { + mFlagKeyPressed = true; + } + // Tap -> Focus Next Widget + if ( e->key() == Key_Tab ) { + QComboBox::keyPressEvent(e); + return; + } + + // save Text from QLineEdit and CursorPosition + QString text = lineEdit()->text(); + int cpos = lineEdit()->cursorPosition(); + // qDebug("cpos %d ", cpos); + + // Switch for arrows, backspace and escape + switch(e->key()) { + case Key_Escape: + lineEdit()->deselect(); + case Key_Tab: + QComboBox::keyPressEvent(e); + break; + case Key_Up: + if ( e->state () == Qt::ControlButton ) { + addTime(QTime(0,15,0), false ); + lineEdit()->setCursorPosition(3); + setSelect( 3 , 2 ); + } + else + if ( e->state () == Qt::ShiftButton ) { + addTime(QTime(1,0,0), false ); + lineEdit()->setCursorPosition(0); + setSelect( 0 , 2 ); + } + else + // switch time up, cursor location depend + switch (cpos) { + case 7: + case 6: + case 5: + if(!hour12Format) { + lineEdit()->setCursorPosition(cpos = 4); + } else { + addTime(QTime(12,0,0), false ); + setSelect ( 5 , 2 ); + break; + } + case 4: + addTime(QTime(0,1,0), false ); + setSelect ( cpos , 1 ); + break; + case 3: + addTime(QTime(0,10,0), false ); + setSelect ( cpos , 1 ); + break; + case 2: + lineEdit()->setCursorPosition(--cpos); + case 1: + case 0: + addTime(QTime(1,0,0), false ); + setSelect ( 0, 2 ); + break; + } + break; + case Key_Down: + if ( e->state () == Qt::ControlButton ) { + subTime(QTime(0,15,0), false ); + lineEdit()->setCursorPosition(3); + setSelect( 3 , 2 ); + } + else + if ( e->state () == Qt::ShiftButton ) { + subTime(QTime(1,0,0), false ); + lineEdit()->setCursorPosition(0); + setSelect( 0 , 2 ); + } + else + // switch time down, cursor location depend + switch (cpos) { + case 7: + case 6: + case 5: + if(!hour12Format) { + lineEdit()->setCursorPosition(cpos = 4); + } else { + subTime(QTime(12,0,0), false ); + setSelect ( 5 , 2 ); + break; + } + case 4: + subTime(QTime(0,1,0), false ); + setSelect ( cpos , 1 ); + break; + case 3: + subTime(QTime(0,10,0), false ); + setSelect ( cpos , 1 ); + break; + case 2: + lineEdit()->setCursorPosition(--cpos); + case 1: + case 0: + subTime(QTime(1,0,0), false ); + setSelect ( 0 , 2 ); + break; + } + break; + // set cursor to correct place + case Key_Left: + if ( cpos == 3 ) + --cpos; + if ( cpos > 0) { + lineEdit()->setCursorPosition(--cpos); + setSelect ( cpos , 1 ); + } + else + setSelect ( 0 , 1 ); + break; + // set cursor to correct place + case Key_Right: + if ( cpos == 1 ) + ++cpos; + if ( cpos < maxpos ) { + lineEdit()->setCursorPosition(++cpos); + setSelect ( cpos , 1 ); + } + break; + // rest + case Key_Prior: + subTime(QTime(1,0,0)); + break; + case Key_Next: + addTime(QTime(1,0,0)); + break; + case Key_Backspace: + if ( cpos > 0) { + if ( cpos == 3 ) + --cpos; + if ( cpos > 5) + cpos = 5; + text.at( cpos-1 ) = '0'; + lineEdit()->setText( text ); + lineEdit()->setCursorPosition(--cpos); + setSelect ( cpos , 1 ); + changedText(); + } + break; + } // switch arrows + + // if cursor at string end, alltext market and keyEvent don't ArrowLeft -> deselect and cpos + if( cpos > 4 && lineEdit()->markedText().length() == 5 && e->key() != Key_Left ) { + lineEdit()->deselect(); + cpos = 0; + lineEdit()->setCursorPosition(cpos); + setSelect(cpos , 1); + } + + if ( cpos == 2 ) { + lineEdit()->setCursorPosition(++cpos); + } + + // num keys when cursorPos preEnd + if ( cpos < 5 ) { + // switch another keys + switch(e->key()) { + case Key_Delete: + text.at( cpos ) = '0'; + lineEdit()->setText( text ); + lineEdit()->setCursorPosition(cpos); + setSelect ( cpos , 1 ); + changedText(); + break; + case Key_9: + case Key_8: + case Key_7: + case Key_6: + if ( !(cpos == 1 || cpos == 4) ) + return; + if ( cpos == 1 && text.at( 0 ) > '1') + text.at( 0 ) = '1'; + case Key_5: + case Key_4: + case Key_3: + if ( cpos < 1 ) + return; + if ( hour12Format && cpos == 1 ) + return; + case Key_2: + if ( hour12Format && cpos == 0 ) + return; + if ( cpos == 0 && text.at( 1 ) > '3') + text.at( 1 ) = '3'; + case Key_1: + case Key_0: + if ( hour12Format ) { + if ( e->key() == Key_0 && cpos == 1 && text.at( 0 ) == '0' ) + return; + if ( e->key() == Key_0 && cpos == 0 && text.at( 1 ) == '0' ) + text.at( 1 ) = '1'; + } + text.at( cpos ) = QChar ( e->key() ); + lineEdit()->setText( text ); + if ( cpos == 1 ) + ++cpos; + if ( cpos < 5) + lineEdit()->setCursorPosition(++cpos); + setSelect( cpos , 1 ); + changedText(); + break; + case Key_Home: + lineEdit()->setCursorPosition(0); + setSelect( cpos , 1 ); + break; + case Key_End: + lineEdit()->setCursorPosition(5); + lineEdit()->deselect(); + break; + default: +// QComboBox::keyPressEvent(e); + break; + } // switch num keys + } else if ( cpos == 5 ) {// if cpos < 5 + if ( hour12Format ) { + if ( e->key() == Key_A ) { + text.at( 5 ) = 'a'; + lineEdit()->setText( text ); + lineEdit()->setCursorPosition(5); + + } else if ( e->key() == Key_P ) { + text.at( 5 ) = 'p'; + lineEdit()->setText( text ); + lineEdit()->setCursorPosition(5); + + } + } + } + + +} + +void KOTimeEdit::updateText() +{ +// kdDebug(5850) << "KOTimeEdit::updateText() " << endl + QString s = KGlobal::locale()->formatTime(mTime); + // Set the text but without emitting signals, nor losing the cursor position + QLineEdit *line = lineEdit(); + line->blockSignals(true); + int pos = line->cursorPosition(); + // qDebug(" settext *%s* ", s.latin1()); + line->setText(s); + // line->setCursorPosition(pos); +// line->blockSignals(false); + +// kdDebug(5850) << "KOTimeEdit::updateText(): " << s << endl; + + if (!mTime.minute() % 15) { + setCurrentItem((mTime.hour()*4)+(mTime.minute()/15)); + } + line->setCursorPosition(pos); + line->blockSignals(false); + +} + +bool KOTimeEdit::inputIsValid() const +{ + int cursorPos = lineEdit()->cursorPosition(); + QString str = currentText(); + return validator()->validate( str, cursorPos ) == QValidator::Acceptable; +} + +void KOTimeEdit::changedText() +{ + //kdDebug(5850) << "KOTimeEdit::changedText()" << endl; + if ( inputIsValid() ) + { + int pos = lineEdit()->cursorPosition(); + mTime = getTime(); + // updateText(); + emit timeChanged(mTime); + lineEdit()->setCursorPosition(pos); + } +} diff --git a/korganizer/ktimeedit.h b/korganizer/ktimeedit.h new file mode 100644 index 0000000..7923070 --- a/dev/null +++ b/korganizer/ktimeedit.h @@ -0,0 +1,97 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1999 Preston Brown, Ian Dawes + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KTIMEEDIT_H +#define _KTIMEEDIT_H + +#include <qevent.h> +#include <qkeycode.h> +#include <qstring.h> +#include <qdatetime.h> +#include <qcombobox.h> + +#include <kapplication.h> + +/** + This is a class that provides an easy, user friendly way to edit times. + up/down/ increase or decrease time, respectively. + + @short Provides a way to edit times in a user-friendly manner. + @author Preston Brown, Ian Dawes +*/ +class KOTimeEdit : public QComboBox +{ + Q_OBJECT + public: + /** constructs a new time edit. */ + KOTimeEdit(QWidget *parent=0, QTime qt=QTime(12,0), const char *name=0); + + virtual ~KOTimeEdit(); + + /** + Returns, if a time is selected. Can not return false anymore.... + */ + bool hasTime() const; + + /** returns the time that is currently set in the timeLineEdit. */ + QTime getTime() const; + + /** returns the prefered size policy of the KOTimeEdit */ + //QSizePolicy sizePolicy() const; + + /** return true if input is a valid time and false if not */ + bool inputIsValid() const; + + signals: + /** + Emitted every time the time displayed changes. "newt" is the new + time. + */ + void timeChanged(QTime newt); + + public slots: + /** used to set the time which is displayed to a specific value. */ + void setTime(QTime qt); + + protected slots: + void activ(int); + void hilit(int); + void changedText(); + + protected: + void keyPressEvent(QKeyEvent *qke); + void keyReleaseEvent(QKeyEvent *qke); + void setSelect ( int, int ); + bool mFlagKeyPressed; + void addTime(QTime qt, bool update = true ); + void subTime(QTime qt, bool update = true ); + // Update the lineedit text from mTime + void updateText(); + // void mouseReleaseEvent ( QMouseEvent * ) ; + //void focusInEvent ( QFocusEvent * ) ; + +private: + QTime mTime; // the widget's displayed time. + //QString mNoTimeString; +}; + +#endif diff --git a/korganizer/ktimeedit.moc b/korganizer/ktimeedit.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/ktimeedit.moc diff --git a/korganizer/lineview.cpp b/korganizer/lineview.cpp new file mode 100644 index 0000000..f1ff29f --- a/dev/null +++ b/korganizer/lineview.cpp @@ -0,0 +1,94 @@ +#include <qpainter.h> + +#include <kdebug.h> + +#include "koprefs.h" + +#include "lineview.h" +#include "lineview.moc" + +LineView::LineView( QWidget *parent, const char *name ) : + QScrollView( parent, name ) +{ + mPixelWidth = 1000; + + mLines.setAutoDelete( true ); + + resizeContents( mPixelWidth, contentsHeight() ); + + viewport()->setBackgroundColor(KOPrefs::instance()->mAgendaBgColor); +} + +LineView::~LineView() +{ +} + +int LineView::pixelWidth() +{ + return mPixelWidth; +} + +void LineView::addLine( int start, int end ) +{ + int count = mLines.count(); + + if( start < 0 ) start = 0; + if( end > mPixelWidth) end = mPixelWidth; + + kdDebug() << "LineView::addLine() col: " << count << " start: " << start + << " end: " << end << endl; + + mLines.append( new Line( count, start, end ) ); +} + +void LineView::clear() +{ + mLines.clear(); + update(); +} + +void LineView::drawContents(QPainter* p, int cx, int cy, int cw, int ch) +{ +// kdDebug() << "LineView::drawContents()" << endl; + + int mGridSpacingX = 10; + int mGridSpacingY = 20; + +#if 0 + // Draw vertical lines of grid + // kdDebug() << "drawContents cx: " << cx << " cy: " << cy << " cw: " << cw << " ch: " << ch << endl; + int x = ((int)(cx/mGridSpacingX))*mGridSpacingX; + while (x < cx + cw) { + p->drawLine(x,cy,x,cy+ch); + x+=mGridSpacingX; + } +#endif + + // Draw horizontal lines of grid + int y = ((int)(cy/mGridSpacingY))*mGridSpacingY + 10; + while (y < cy + ch) { +// kdDebug() << " y: " << y << endl; + p->drawLine(cx,y,cx+cw,y); + y+=mGridSpacingY; + } + + Line *line; + for( line = mLines.first(); line; line = mLines.next() ) { + int ctop = line->column * 20 + 10 - 5; + int cbottom = line->column * 20 + 10 + 5; + int s = line->start; + int e = line->end; +// kdDebug() << " LineView::drawContents(): ctop: " << ctop << " cbottom: " +// << cbottom << " s: " << s << " e: " << e << endl; + if ( ctop <= (cy+ch) && cbottom >= cy && + s <= (cx+cw) && e >= cx ) { + if ( s < cx ) s = cx; + if ( e > (cx+cw) ) e = cx+cw; + if ( ctop < cy ) ctop = cy; + if ( cbottom > (cy+ch) ) cbottom = cy+ch; +// kdDebug() << " drawContents(): ctop: " << ctop << " cbottom: " +// << cbottom << " s: " << s << " e: " << e << endl; + p->fillRect( s, ctop, e - s + 1, cbottom - ctop + 1, QBrush("red") ); + } + } +} diff --git a/korganizer/lineview.h b/korganizer/lineview.h new file mode 100644 index 0000000..aa34dbc --- a/dev/null +++ b/korganizer/lineview.h @@ -0,0 +1,36 @@ +#ifndef LINEVIEW_H +#define LINEVIEW_H + +#include <qscrollview.h> +#include <qptrlist.h> + +class LineView : public QScrollView +{ + Q_OBJECT + public: + LineView( QWidget *parent = 0, const char *name = 0 ); + virtual ~LineView(); + + int pixelWidth(); + + void addLine( int start, int end ); + + void clear(); + + protected: + void drawContents(QPainter* p, int cx, int cy, int cw, int ch); + + private: + struct Line { + Line( int c, int s, int e ) : column( c ), start( s ), end( e ) {} + int column; + int start; + int end; + }; + + QPtrList<Line> mLines; + int mPixelWidth; +}; + +#endif + diff --git a/korganizer/lineview.moc b/korganizer/lineview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/lineview.moc diff --git a/korganizer/main.cpp b/korganizer/main.cpp new file mode 100644 index 0000000..6843595 --- a/dev/null +++ b/korganizer/main.cpp @@ -0,0 +1,107 @@ + + +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#include <qpe/global.h> +#include <stdlib.h> +#else +#include <qapplication.h> +#include <qstring.h> +#include <qwindowsstyle.h> +#include <qplatinumstyle.h> +#include <qsgistyle.h> +#endif + +#include <qdir.h> +#include <kstandarddirs.h> +#include <kglobal.h> +#include <stdio.h> +#include "mainwindow.h" + +int main( int argc, char **argv ) +{ +#ifndef DESKTOP_VERSION + QPEApplication a( argc, argv ); + a.setKeepRunning (); +#else + QApplication a( argc, argv ); + QApplication::setStyle( new QPlatinumStyle ()); +#endif + bool exitHelp = false; + if ( argc > 1 ) { + QString command = argv[1]; + if ( command == "-help" ){ + printf("KO/Pi command line commands:\n"); + printf(" no command: Start KO/Pi in usual way\n"); + printf(" -help: This output\n"); + printf("Next Option: Open or Show after start:\n"); + printf(" -newTodo: New Todo dialog\n"); + printf(" -newEvent: New Event dialog\n"); + printf(" -showList: List view\n"); + printf(" -showDay: Day view\n"); + printf(" -showWWeek: Work Week view\n"); + printf(" -showWeek: Week view\n"); + printf(" -showTodo: Todo view\n"); + printf(" -showJournal: Journal view\n"); + printf(" -showKO: Next Days view\n"); + printf(" -showWNext: What's Next view\n"); + printf(" -showNextXView: Next X View\n"); + printf(" -new[Y] and -show[X] may be used togehther\n"); + printf(" KO/Pi is exiting now. Bye!\n"); + exitHelp = true; + } + } + if ( ! exitHelp ) { + KGlobal::setAppName( "korganizer" ); + + + QString fileName ; +#ifndef DESKTOP_VERSION + KStandardDirs::setAppDir( Global::applicationFileName( "korganizer", "" ) ); + fileName = getenv("QPEDIR"); + KGlobal::iconLoader()->setIconPath( fileName +"/pics/kdepim/korganizer/"); +#else + +#ifndef _WIN32_ + fileName = qApp->applicationDirPath () + "/kdepim/korganizer/"; +#else + fileName = qApp->applicationDirPath () + "\\kdepim\\korganizer\\"; +#endif + + KGlobal::iconLoader()->setIconPath(fileName); + + QString appdir = QDir::homeDirPath(); + //appdir = "C:\\"; + if ( appdir.right(1) == "\\" || appdir.right(1) == "/" ) + appdir += "korganizer"; + else + appdir += "/korganizer"; + KStandardDirs::setAppDir( QDir::convertSeparators( appdir )); + // qDebug(" %s ",KStandardDirs::appDir().latin1() ); +#endif + QDir app_dir; + if ( !app_dir.exists(KStandardDirs::appDir()) ) + app_dir.mkdir (KStandardDirs::appDir()); + MainWindow m; +#ifndef DESKTOP_VERSION + QObject::connect( &a, SIGNAL (appMessage ( const QCString &, const QByteArray & )),&m, SLOT(recieve( const QCString&, const QByteArray& ))); + a.showMainWidget(&m ); +#else + a.setMainWidget(&m ); + m.show(); + //m.resize( 800, 600 ); + QObject::connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); +#endif + if ( argc > 1 ) { + QCString command = argv[1]; + if ( argc > 2 ) + command += argv[2]; + qApp->processEvents(); + m.recieve(command, QByteArray() ); + + } + a.exec(); + + } + qDebug("KO: Bye! "); +} diff --git a/korganizer/mainwindow.cpp b/korganizer/mainwindow.cpp new file mode 100644 index 0000000..40f2cf4 --- a/dev/null +++ b/korganizer/mainwindow.cpp @@ -0,0 +1,1974 @@ +#include <stdlib.h> + +#include <qaction.h> +#include <qpopupmenu.h> +#include <qpainter.h> +#include <qwhatsthis.h> +#include <qmessagebox.h> +#include <qlineedit.h> +#include <qfile.h> +#include <qdir.h> +#include <qapp.h> +#include <qfileinfo.h> +#include <qlabel.h> +#include <qwmatrix.h> +#include <qtextbrowser.h> +#include <qtextstream.h> +#ifndef DESKTOP_VERSION +#include <qpe/global.h> +#include <qpe/qpemenubar.h> +#include <qpe/qpetoolbar.h> +#include <qpe/resource.h> +#include <qpe/qpeapplication.h> +#include <qtopia/alarmserver.h> +#include <qtopia/qcopenvelope_qws.h> +#else +#include <qmenubar.h> +#include <qtoolbar.h> +#include <qapplication.h> +//#include <resource.h> + +#endif +#include <libkcal/calendarlocal.h> +#include <libkcal/todo.h> +#include <libkdepim/ksyncprofile.h> +#include <libkdepim/kincidenceformatter.h> + +#include "calendarview.h" +#include "koviewmanager.h" +#include "datenavigator.h" +#include "koagendaview.h" +#include "koagenda.h" +#include "kodialogmanager.h" +#include "kdialogbase.h" +#include "kstandarddirs.h" +#include "koprefs.h" +#include "kfiledialog.h" +#include "koglobals.h" +#include "kglobal.h" +#include "klocale.h" +#include "kconfig.h" +#include "simplealarmclient.h" + +using namespace KCal; +#ifndef _WIN32_ +#include <unistd.h> +#endif +#include "mainwindow.h" + +int globalFlagBlockStartup; +MainWindow::MainWindow( QWidget *parent, const char *name, QString msg) : + QMainWindow( parent, name ) +{ + +#ifdef DESKTOP_VERSION + setFont( QFont("Arial"), 14 ); +#endif + + //QString confFile = KStandardDirs::appDir() + "config/korganizerrc"; + QString confFile = locateLocal("config","korganizerrc"); + QFileInfo finf ( confFile ); + bool showWarning = !finf.exists(); + setIcon(SmallIcon( "ko24" ) ); + mBlockAtStartup = true; + mFlagKeyPressed = false; + setCaption("KOrganizer/Pi"); + KOPrefs *p = KOPrefs::instance(); + // if ( QApplication::desktop()->height() > 480 ) { +// if ( p->mHourSize == 4 ) +// p->mHourSize = 6; +// } + if ( p->mHourSize > 18 ) + p->mHourSize = 18; + QMainWindow::ToolBarDock tbd; + if ( p->mToolBarHor ) { + if ( p->mToolBarUp ) + tbd = Bottom; + else + tbd = Top; + } + else { + if ( p->mToolBarUp ) + tbd = Right; + else + tbd = Left; + } + if ( KOPrefs::instance()->mUseAppColors ) + QApplication::setPalette( QPalette (KOPrefs::instance()->mAppColor1, KOPrefs::instance()->mAppColor2), true ); + globalFlagBlockStartup = 1; + iconToolBar = new QPEToolBar( this ); + addToolBar (iconToolBar , tbd ); + mBlockSaveFlag = false; + mCalendarModifiedFlag = false; + + QLabel* splash = new QLabel(i18n("KO/Pi is starting ... "), this ); + splash->setAlignment ( AlignCenter ); + setCentralWidget( splash ); +#ifndef DESKTOP_VERSION + showMaximized(); +#endif + //qDebug("Mainwidget x %d y %d w %d h %d", x(), y(), width(), height ()); + setDefaultPreferences(); + mCalendar = new CalendarLocal(); + mView = new CalendarView( mCalendar, this,"mCalendar " ); + mView->hide(); + //mView->resize(splash->size() ); + initActions(); +#ifndef DESKTOP_VERSION + iconToolBar->show(); + qApp->processEvents(); +#endif + //qDebug("Splashwidget x %d y %d w %d h %d", splash-> x(), splash->y(), splash->width(),splash-> height ()); + int vh = height() ; + int vw = width(); + //qDebug("Toolbar hei %d ",iconToolBar->height() ); + if ( iconToolBar->orientation () == Qt:: Horizontal ) { + vh -= iconToolBar->height(); + } else { + vw -= iconToolBar->height(); + } + //mView->setMaximumSize( splash->size() ); + //mView->resize( splash->size() ); + //qDebug("MainView x %d y %d w %d h %d", mView->x(),mView-> y(), mView->width(), mView->height ()); + mView->readSettings(); + bool oldOpened = false; + bool newFile = false; + if( !QFile::exists( defaultFileName() ) ) { + QFileInfo finfo ( defaultFileName() ); + QString oldFile = QDir::convertSeparators( QDir::homeDirPath()+"/Applications/korganizer/mycalendar.ics"); + qDebug("oldfile %s ", oldFile.latin1()); + QString message = "You are starting KO/Pi for the\nfirst time after updating to a\nversion >= 1.9.1. The location of the\ndefault calendar file has changed.\nA mycalendar.ics file was detected\nat the old location.\nThis file will be loaded now\nand stored at the new location!\n(Config file location has changed, too!)\nPlease read menu Help-What's New!\n"; + finfo.setFile( oldFile ); + if (finfo.exists() ) { + KMessageBox::information( this, message); + mView->openCalendar( oldFile ); + qApp->processEvents(); + } else { + oldFile = QDir::convertSeparators( QDir::homeDirPath()+"/korganizer/mycalendar.ics"); + finfo.setFile( oldFile ); + if (finfo.exists() ) { + KMessageBox::information( this, message); + mView->openCalendar( oldFile ); + qApp->processEvents(); + } + } + mView->saveCalendar( defaultFileName() ); + newFile = true; + } + + QTime neededSaveTime = QDateTime::currentDateTime().time(); + if ( ! oldOpened ) + mView->openCalendar( defaultFileName() ); + int msNeeded = neededSaveTime.msecsTo( QDateTime::currentDateTime().time() ); + qDebug("KO: Calendar loading time: %d ms",msNeeded ); + + if ( KOPrefs::instance()->mLanguageChanged ) { + KOPrefs::instance()->setCategoryDefaults(); + int count = mView->addCategories(); + KOPrefs::instance()->mLanguageChanged = false; + } + processIncidenceSelection( 0 ); + connect( mView, SIGNAL( incidenceSelected( Incidence * ) ), + SLOT( processIncidenceSelection( Incidence * ) ) ); + connect( mView, SIGNAL( modifiedChanged( bool ) ), + SLOT( slotModifiedChanged( bool ) ) ); + + + connect( &mSaveTimer, SIGNAL( timeout() ), SLOT( save() ) ); + mView->setModified( false ); + mBlockAtStartup = false; + mView->setModified( false ); + setCentralWidget( mView ); + globalFlagBlockStartup = 0; + mView->show(); + delete splash; + if ( newFile ) + mView->updateConfig(); + // qApp->processEvents(); + //qDebug("MainView x %d y %d w %d h %d", mView->x(),mView-> y(), mView->width(), mView->height ()); + fillSyncMenu(); + mView->viewManager()->agendaView()->setStartHour( KOPrefs::instance()->mDayBegins ); + if ( showWarning ) { + KMessageBox::information( this, + "You are starting KO/Pi for the first time.\nPlease read menu: Help-What's New,\nif you did an update!\nPlease choose your timezone in the \nConfigure Dialog TAB Time Zone!\nPlease choose your language\nin the TAB Locale!\nYou get the Configure Dialog\nvia Menu: Actions - Configure....\nClick OK to show the Configure Dialog!\n", "KO/Pi information"); + qApp->processEvents(); + mView->dialogManager()->showSyncOptions(); + } +} +MainWindow::~MainWindow() +{ + //qDebug("MainWindow::~MainWindow() "); + //save toolbar location + + delete mCalendar; + delete KOPrefs::instance(); + delete KIncidenceFormatter::instance(); + + +} +void MainWindow::closeEvent( QCloseEvent* ce ) +{ + + + + if ( ! KOPrefs::instance()->mAskForQuit ) { + saveOnClose(); + ce->accept(); + return; + + } + + switch( QMessageBox::information( this, "KO/Pi", + i18n("Do you really want\nto close KO/Pi?"), + i18n("Close"), i18n("No"), + 0, 0 ) ) { + case 0: + saveOnClose(); + ce->accept(); + break; + case 1: + ce->ignore(); + break; + case 2: + + default: + break; + } + + +} + +void MainWindow::recieve( const QCString& cmsg, const QByteArray& data ) +{ + QDataStream stream( data, IO_ReadOnly ); + // QMessageBox::about( this, "About KOrganizer/Pi", "*" +msg +"*" ); + //QString datamess; + //qDebug("message "); + qDebug("KO: QCOP message received: %s ", cmsg.data() ); + if ( cmsg == "-writeFile" ) { + // I made from the "-writeFile" an "-writeAlarm" + mView->viewManager()->showWhatsNextView(); + mCalendar->checkAlarmForIncidence( 0, true); + showMaximized(); + raise(); + return; + + } + if ( cmsg == "-writeFileSilent" ) { + // I made from the "-writeFile" an "-writeAlarm" + // mView->viewManager()->showWhatsNextView(); + mCalendar->checkAlarmForIncidence( 0, true); + //showMaximized(); + //raise(); + hide(); + return; + } + if ( cmsg == "-newCountdown" ) { + qDebug("newCountdown "); + + } + QString msg ; + QString allmsg = cmsg; + while ( allmsg.length() > 0 ) { + int nextC = allmsg.find( "-", 1 ); + if ( nextC == -1 ) { + msg = allmsg; + allmsg = ""; + } else{ + msg = allmsg.left( nextC ); + allmsg = allmsg.mid( nextC, allmsg.length()-nextC ); + } + //qDebug("msg: %s all: %s ", msg.latin1(), allmsg.latin1() ); + if ( msg == "-newEvent" ) { + mView->newEvent(); + } + if ( msg == "-newTodo" ) { + mView->newTodo(); + + } + if ( msg == "-showWN" ) { + mView->viewManager()->showWhatsNextView(); + } + if ( msg == "-showTodo" ) { + mView->viewManager()->showTodoView(); + } + if ( msg == "-showList" ) { + mView->viewManager()->showListView(); + } + else if ( msg == "-showDay" ) { + mView->viewManager()->showDayView(); + } + else if ( msg == "-showWWeek" ) { + mView->viewManager()->showWorkWeekView(); + } + else if ( msg == "-ringSync" ) { + multiSync( false ); + } + else if ( msg == "-showWeek" ) { + mView->viewManager()->showWeekView(); + } + else if ( msg == "-showTodo" ) { + mView->viewManager()->showTodoView(); + } + else if ( msg == "-showJournal" ) { + mView->dateNavigator()->selectDates( 1 ); + mView->dateNavigator()->selectToday(); + mView->viewManager()->showJournalView(); + } + else if ( msg == "-showKO" ) { + mView->viewManager()->showNextXView(); + } + else if ( msg == "-showWNext" || msg == "nextView()" ) { + mView->viewManager()->showWhatsNextView(); + } + else if ( msg == "-showNextXView" ) { + mView->viewManager()->showNextXView(); + } + + + } + + showMaximized(); + raise(); +} + +QPixmap MainWindow::loadPixmap( QString name ) +{ + return SmallIcon( name ); + +} +void MainWindow::initActions() +{ + //KOPrefs::instance()->mShowFullMenu + iconToolBar->clear(); + KOPrefs *p = KOPrefs::instance(); + //QPEMenuBar *menuBar1;// = new QPEMenuBar( iconToolBar ); + + QPopupMenu *viewMenu = new QPopupMenu( this ); + QPopupMenu *actionMenu = new QPopupMenu( this ); + QPopupMenu *importMenu = new QPopupMenu( this ); + + syncMenu = new QPopupMenu( this ); + configureAgendaMenu = new QPopupMenu( this ); + configureToolBarMenu = new QPopupMenu( this ); + QPopupMenu *helpMenu = new QPopupMenu( this ); + if ( KOPrefs::instance()->mShowFullMenu ) { + QMenuBar *menuBar1; + menuBar1 = menuBar(); + menuBar1->insertItem( i18n("File"), importMenu ); + menuBar1->insertItem( i18n("View"), viewMenu ); + menuBar1->insertItem( i18n("Actions"), actionMenu ); + menuBar1->insertItem( i18n("Synchronize"), syncMenu ); + menuBar1->insertItem( i18n("AgendaSize"),configureAgendaMenu ); + //menuBar1->insertItem( i18n("Toolbar"),configureToolBarMenu ); + menuBar1->insertItem( i18n("Help"), helpMenu ); + } else { + QPEMenuBar *menuBar1; + menuBar1 = new QPEMenuBar( iconToolBar ); + QPopupMenu *menuBar = new QPopupMenu( this ); + menuBar1->insertItem( i18n("ME"), menuBar); + menuBar->insertItem( i18n("File"), importMenu ); + menuBar->insertItem( i18n("View"), viewMenu ); + menuBar->insertItem( i18n("Actions"), actionMenu ); + menuBar->insertItem( i18n("Synchronize"), syncMenu ); + menuBar->insertItem( i18n("AgendaSize"),configureAgendaMenu ); + menuBar->insertItem( i18n("Toolbar"),configureToolBarMenu ); + menuBar->insertItem( i18n("Help"), helpMenu ); + //menuBar1->setMaximumWidth( menuBar1->sizeHint().width() ); + menuBar1->setMaximumSize( menuBar1->sizeHint( )); + } + connect ( syncMenu, SIGNAL( activated ( int ) ), this, SLOT (slotSyncMenu( int ) ) ); + // ****************** + QAction *action; + QIconSet icon; + // QPopupMenu *configureMenu= new QPopupMenu( menuBar ); + configureToolBarMenu->setCheckable( true ); + + QString pathString = ""; + if ( !p->mToolBarMiniIcons ) { + if ( QApplication::desktop()->width() < 480 ) + pathString += "icons16/"; + } else + pathString += "iconsmini/"; + configureAgendaMenu->setCheckable( true ); + configureAgendaMenu->insertItem(i18n("Toggle Allday"), 1 ); + configureAgendaMenu->insertSeparator(); + configureAgendaMenu->insertItem(i18n("Tiny"), 4 ); + configureAgendaMenu->insertItem(i18n("Small"), 6 ); + configureAgendaMenu->insertItem(i18n("Medium"), 8 ); + configureAgendaMenu->insertItem(i18n("Normal"), 10 ); + configureAgendaMenu->insertItem(i18n("Large"), 12 ); + configureAgendaMenu->insertItem(i18n("Big"), 14 ); + configureAgendaMenu->insertItem(i18n("Bigger"), 16 ); + configureAgendaMenu->insertItem(i18n("Biggest"), 18 ); + //configureMenu->insertItem( "AgendaSize",configureAgendaMenu ); + + icon = loadPixmap( pathString + "configure" ); + action = new QAction( i18n("Configure"),icon, i18n("Configure..."), 0, this ); + action->addTo( actionMenu ); + connect( action, SIGNAL( activated() ), + mView, SLOT( edit_options() ) ); + actionMenu->insertSeparator(); + icon = loadPixmap( pathString + "newevent" ); + configureToolBarMenu->insertItem(i18n("Stretched TB"), 5 ); + configureToolBarMenu->insertSeparator(); + configureToolBarMenu->insertItem(icon, i18n("New Event..."), 10 ); + QAction* ne_action = new QAction( i18n("New Event..."), icon, i18n("New Event..."), 0, this ); + ne_action->addTo( actionMenu ); + connect( ne_action, SIGNAL( activated() ), + mView, SLOT( newEvent() ) ); + icon = loadPixmap( pathString + "newtodo" ); + configureToolBarMenu->insertItem(icon, i18n("New Todo..."), 20 ); + QAction* nt_action = new QAction( i18n("New Todo..."), icon, i18n("New Todo..."), 0, this ); + nt_action->addTo( actionMenu ); + connect( nt_action, SIGNAL( activated() ), + mView, SLOT( newTodo() ) ); + icon = loadPixmap( pathString + "navi" ); + action = new QAction( i18n("Toggle DateNavigator"), icon, i18n("Toggle DateNavigator"), 0, this ); + action->addTo( viewMenu ); + connect( action, SIGNAL( activated() ), + mView, SLOT( toggleDateNavigatorWidget() ) ); + icon = loadPixmap( pathString + "filter" ); + action = new QAction( i18n("Toggle FilterView"), icon, i18n("Toggle FilterView"), 0, this ); + action->addTo( viewMenu ); + connect( action, SIGNAL( activated() ), + mView, SLOT( toggleFilter() ) ); + + + viewMenu->insertSeparator(); + icon = loadPixmap( pathString + "picker" ); + action = new QAction( i18n("Date Picker"), icon, i18n("Date Picker"), 0, this ); + action->addTo( viewMenu ); + connect( action, SIGNAL( activated() ), + mView, SLOT( showDatePicker() ) ); + action->addTo( iconToolBar ); + viewMenu->insertSeparator(); + icon = loadPixmap( pathString + "list" ); + configureToolBarMenu->insertItem(icon, i18n("List View"), 30 ); + QAction* showlist_action = new QAction( i18n("List View"), icon, i18n("List View"), 0, this ); + showlist_action->addTo( viewMenu ); + connect( showlist_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showListView() ) ); + + + icon = loadPixmap( pathString + "day" ); + configureToolBarMenu->insertItem(icon, i18n("Day View"), 40 ); + QAction* day1_action = new QAction( i18n("Day View"), icon, i18n("Day View"), 0, this ); + day1_action->addTo( viewMenu ); + // action->addTo( toolBar ); + connect( day1_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showDayView() ) ); + + icon = loadPixmap( pathString + "workweek" ); + configureToolBarMenu->insertItem(icon, i18n("Work Week"), 50 ); + QAction* day5_action = new QAction( i18n("Work Week"), icon, i18n("Work Week"), 0, this ); + day5_action->addTo( viewMenu ); + connect( day5_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showWorkWeekView() ) ); + + icon = loadPixmap( pathString + "week" ); + configureToolBarMenu->insertItem(icon, i18n("Week"), 60 ); + QAction* day7_action = new QAction( i18n("Week"), icon, i18n("Week"), 0, this ); + day7_action->addTo( viewMenu ); + connect( day7_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showWeekView() ) ); + + icon = loadPixmap( pathString + "month" ); + configureToolBarMenu->insertItem(icon, i18n("Month"), 70 ); + QAction* month_action = new QAction( i18n("Month"), icon, i18n("Month"), 0, this ); + month_action->addTo( viewMenu ); + connect( month_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showMonthView() ) ); + + icon = loadPixmap( pathString + "todo" ); + configureToolBarMenu->insertItem(icon, i18n("Todo View"), 80 ); + QAction* todoview_action = new QAction( i18n("Todo View"), icon, i18n("Todo View"), 0, this ); + todoview_action->addTo( viewMenu ); + connect( todoview_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showTodoView() ) ); + + icon = loadPixmap( pathString + "journal" ); + configureToolBarMenu->insertItem(icon, i18n("Journal"), 90 ); + QAction* viewjournal_action = new QAction( i18n("Journal"), icon, i18n("Journal"), 0, this ); + viewjournal_action->addTo( viewMenu ); + connect( viewjournal_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showJournalView() ) ); + + icon = loadPixmap( pathString + "xdays" ); + configureToolBarMenu->insertItem(icon, i18n("Next days"), 100,4 ); + QAction* xdays_action = new QAction( i18n("Next days"), icon, i18n("Next days"), 0, this ); + xdays_action->addTo( viewMenu ); + connect( xdays_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showNextXView() ) ); + + icon = loadPixmap( pathString + "whatsnext" ); + configureToolBarMenu->insertItem(icon, i18n("What's Next"), 110, 4 ); + QAction* whatsnext_action = new QAction( i18n("What's Next"), icon, i18n("What's Next"), 0, this ); + whatsnext_action->addTo( viewMenu ); + connect( whatsnext_action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showWhatsNextView() ) ); + +#if 0 + action = new QAction( "view_timespan", "Time Span", 0, this ); + action->addTo( viewMenu ); + connect( action, SIGNAL( activated() ), + mView->viewManager(), SLOT( showTimeSpanView() ) ); +#endif + + mNewSubTodoAction = new QAction( "new_subtodo", i18n("New Sub-Todo..."), 0, + this ); + mNewSubTodoAction->addTo( actionMenu ); + connect( mNewSubTodoAction, SIGNAL( activated() ), + mView, SLOT( newSubTodo() ) ); + + actionMenu->insertSeparator(); + + mShowAction = new QAction( "show_incidence", i18n("Show..."), 0, this ); + mShowAction->addTo( actionMenu ); + connect( mShowAction, SIGNAL( activated() ), + mView, SLOT( showIncidence() ) ); + + mEditAction = new QAction( "edit_incidence", i18n("Edit..."), 0, this ); + mEditAction->addTo( actionMenu ); + connect( mEditAction, SIGNAL( activated() ), + mView, SLOT( editIncidence() ) ); + + mDeleteAction = new QAction( "delete_incidence", i18n("Delete..."), 0, this ); + mDeleteAction->addTo( actionMenu ); + connect( mDeleteAction, SIGNAL( activated() ), + mView, SLOT( deleteIncidence() ) ); + + actionMenu->insertSeparator(); + + action = new QAction( "purge_completed", i18n("Purge Completed"), 0, + this ); + action->addTo( actionMenu ); + connect( action, SIGNAL( activated() ), mView, SLOT( purgeCompleted() ) ); + + icon = loadPixmap( pathString + "search" ); + QAction* search_action = new QAction( i18n("Search"), icon, i18n("Search..."), 0, this ); + configureToolBarMenu->insertItem(icon, i18n("Search"), 120 , 4); + search_action->addTo( actionMenu ); + connect( search_action, SIGNAL( activated() ), + mView->dialogManager(), SLOT( showSearchDialog() ) ); + + icon = loadPixmap( pathString + "today" ); + configureToolBarMenu->insertItem(icon, i18n("Go to Today"), 130); + QAction* today_action = new QAction( i18n("Go to Today"), icon, i18n("Go to Today"), 0, this ); + today_action->addTo( actionMenu ); + connect( today_action, SIGNAL( activated() ), + mView, SLOT( goToday() ) ); + + if ( KOPrefs::instance()->mShowFullMenu ) { + actionMenu->insertSeparator(); + actionMenu->insertItem( i18n("Configure Toolbar"),configureToolBarMenu ); + + } + // actionMenu->insertSeparator(); + action = new QAction( "import_qtopia", i18n("Import (*.ics/*.vcs) file"), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( importIcal() ) ); + action = new QAction( "import_quick", i18n("Import last file"), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( quickImportIcal() ) ); + importMenu->insertSeparator(); + action = new QAction( "import_bday", i18n("Import Birthdays (KA/Pi)"), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( importBday() ) ); +#ifndef DESKTOP_VERSION + importMenu->insertSeparator(); + action = new QAction( "import_qtopia", i18n("Import Opie/Qtopia Cal."), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( importQtopia() ) ); +#endif + + importMenu->insertSeparator(); + action = new QAction( "load_cal", i18n("Load Calendar Backup"), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( loadCalendar() ) ); + + action = new QAction( "save_cal", i18n("Save Calendar Backup"), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), SLOT( saveCalendar() ) ); + + importMenu->insertSeparator(); + action = new QAction( "import_qtopia", i18n("Export VCalendar"), 0, + this ); + action->addTo( importMenu ); connect( action, SIGNAL( activated() ), SLOT( exportVCalendar() ) ); + importMenu->insertSeparator(); + action = new QAction( "manage cat", i18n("Manage new categories..."), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), mView, SLOT( manageCategories() ) ); +#ifndef DESKTOP_VERSION + importMenu->insertSeparator(); + action = new QAction( "beam all", i18n("Beam complete calendar..."), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), mView, SLOT( beamCalendar() ) ); + + action = new QAction( "beam all", i18n("Beam filtered calendar..."), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), mView, SLOT( beamFilteredCalendar()) ); +#else + importMenu->insertSeparator(); + icon = loadPixmap( pathString + "print" ); + action = new QAction( i18n("Print calendar..."),icon,i18n("Print calendar..."), 0, this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), + this, SLOT( printCal() ) ); + + icon = loadPixmap( pathString + "print" ); + action = new QAction( i18n("Print agenda selection..."),icon,i18n("Print agenda selection..."), 0, this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), + this, SLOT( printSel() ) ); +#endif + importMenu->insertSeparator(); + action = new QAction( "beam all", i18n("Save"), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), this, SLOT( save() ) ); + action = new QAction( "beam all", i18n("Exit (+save)"), 0, + this ); + action->addTo( importMenu ); + connect( action, SIGNAL( activated() ), this, SLOT( close() ) ); + + //menuBar->insertItem( "Configure",configureMenu ); + //configureMenu->insertItem( "Toolbar",configureToolBarMenu ); + icon = loadPixmap( "korganizer/korganizer" ); + action = new QAction( "Keys + Colors", i18n("Keys + Colors..."), 0, this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( keyBindings() ) ); + action = new QAction( "featureHowto", i18n("Features + hints..."), 0,this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( features() ) ); + action = new QAction( "Auto saving", i18n("Auto saving..."), 0, this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( aboutAutoSaving() ) ); + action = new QAction( "Problemd", i18n("Known Problems..."), 0,this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( aboutKnownBugs() ) ); + action = new QAction( "Translate Howto", i18n("User translation..."), 0,this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( usertrans() ) ); + action = new QAction( "Sync Howto", i18n("Sync HowTo..."), 0,this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( synchowto() ) ); + action = new QAction( "Whats New", i18n("What's new?"), 0,this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( whatsNew() ) ); + action = new QAction( "Frequently asked questions", i18n("FAQ..."), 0,this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( faq() ) ); + + + action = new QAction( "about", i18n("About..."), 0, this ); + action->addTo( helpMenu ); + connect( action, SIGNAL( activated() ), + SLOT( about() ) ); + //menuBar->insertSeparator(); + + // ****************************************************** + // menubar icons + + + iconToolBar->setHorizontalStretchable (true ); + //menuBar->insertItem( iconToolBar ); + //xdays_action + if (p-> mShowIconNewEvent) + ne_action->addTo( iconToolBar ); + if (p->mShowIconNewTodo ) + nt_action->addTo( iconToolBar ); + if (p-> mShowIconSearch) + search_action->addTo( iconToolBar ); + if (p-> mShowIconNext) + whatsnext_action->addTo( iconToolBar ); + if (p-> mShowIconNextDays) + xdays_action->addTo( iconToolBar ); + if (p-> mShowIconList) + showlist_action->addTo( iconToolBar ); + if (p-> mShowIconDay1) + day1_action->addTo( iconToolBar ); + if (p-> mShowIconDay5) + day5_action->addTo( iconToolBar ); + if (p-> mShowIconDay7) + day7_action->addTo( iconToolBar ); + if (p-> mShowIconMonth) + month_action->addTo( iconToolBar ); + if (p-> mShowIconTodoview) + todoview_action->addTo( iconToolBar ); + if (p-> mShowIconJournal) + viewjournal_action->addTo( iconToolBar ); + icon = loadPixmap( pathString + "2leftarrowB" ); + configureToolBarMenu->insertItem(icon, i18n("Prev. month"), 200, 14); + if (p-> mShowIconBackFast) { + action = new QAction( i18n("Prev. month"), icon, i18n("Prev. month"),0 , this ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goPreviousMonth() ) ); + action->addTo( iconToolBar ); + } + icon = loadPixmap( pathString + "1leftarrowB" ); + configureToolBarMenu->insertItem(icon, i18n("Go backward"), 210,15); + if (p-> mShowIconBack) { + action = new QAction( i18n("Go backward"), icon, i18n("Go backward"),0 , this ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goPrevious() ) ); + action->addTo( iconToolBar ); + } + if (p-> mShowIconToday) + today_action->addTo( iconToolBar ); + icon = loadPixmap( pathString + "1rightarrowB" ); + configureToolBarMenu->insertItem(icon, i18n("Go forward"), 220); + if (p-> mShowIconForward) { + action = new QAction( i18n("Go forward"), icon, i18n("Go forward"),0 , this ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goNext() ) ); + action->addTo( iconToolBar ); + } + icon = loadPixmap( pathString + "2rightarrowB" ); + configureToolBarMenu->insertItem(icon, i18n("Next month"), 230); + if (p-> mShowIconForwardFast) { + action = new QAction( i18n("Next month"), icon, i18n("Next month"),0 , this ); + connect( action, SIGNAL( activated() ), + mView, SLOT( goNextMonth() ) ); + action->addTo( iconToolBar ); + } + + + configureToolBarMenu->insertItem(i18n("What's This?"), 300); + + if (p-> mShowIconNewEvent) + configureToolBarMenu->setItemChecked( 10, true ); + if (p->mShowIconNewTodo ) + configureToolBarMenu->setItemChecked( 20, true ); + if (p-> mShowIconSearch) + configureToolBarMenu->setItemChecked( 120, true ); + if (p-> mShowIconList) + configureToolBarMenu->setItemChecked( 30, true ); + if (p-> mShowIconDay1) + configureToolBarMenu->setItemChecked( 40, true ); + if (p-> mShowIconDay5) + configureToolBarMenu->setItemChecked( 50, true ); + if (p-> mShowIconDay7) + configureToolBarMenu->setItemChecked( 60, true ); + if (p-> mShowIconMonth) + configureToolBarMenu->setItemChecked( 70, true ); + if (p-> mShowIconTodoview) + configureToolBarMenu->setItemChecked( 80, true ); + if (p-> mShowIconBackFast) + configureToolBarMenu->setItemChecked( 200, true ); + if (p-> mShowIconBack) + configureToolBarMenu->setItemChecked( 210, true ); + if (p-> mShowIconToday) + configureToolBarMenu->setItemChecked( 130, true ); + if (p-> mShowIconForward) + configureToolBarMenu->setItemChecked( 220, true ); + if (p-> mShowIconForwardFast) + configureToolBarMenu->setItemChecked( 230, true ); + if (p-> mShowIconNextDays) + configureToolBarMenu->setItemChecked( 100, true ); + if (p-> mShowIconNext) + configureToolBarMenu->setItemChecked( 110, true ); + if (p-> mShowIconJournal) + configureToolBarMenu->setItemChecked( 90, true ); + if (p-> mShowIconWhatsThis) + configureToolBarMenu->setItemChecked( 300, true ); + + QLabel* dummy = new QLabel( iconToolBar ); + dummy->setBackgroundColor( iconToolBar->backgroundColor() ); + if (!p-> mShowIconStretch) + iconToolBar->setStretchableWidget ( dummy ) ; + else + configureToolBarMenu->setItemChecked( 5, true ); + if (p-> mShowIconWhatsThis) + QWhatsThis::whatsThisButton ( iconToolBar ); + connect( configureToolBarMenu, SIGNAL( activated( int ) ),this, SLOT(configureToolBar( int ) ) ); + configureAgenda( p->mHourSize ); + connect( configureAgendaMenu, SIGNAL( activated( int ) ),this, SLOT(configureAgenda( int ) ) ); +} +void MainWindow::fillSyncMenu() +{ + syncMenu->clear(); + syncMenu->insertItem( i18n("Configure..."), 0 ); + syncMenu->insertSeparator(); + syncMenu->insertItem( i18n("Multiple sync"), 1 ); + syncMenu->insertSeparator(); + + QStringList prof = KOPrefs::instance()->mSyncProfileNames; + + if ( prof.count() < 3 ) { + KConfig *config = KOGlobals::config(); + prof.clear(); + prof << i18n("Sharp-DTM"); + prof << i18n("Local file"); + prof << i18n("Last file"); + KSyncProfile* temp = new KSyncProfile (); + temp->setName( prof[0] ); + temp->writeConfig(config); + temp->setName( prof[1] ); + temp->writeConfig(config); + temp->setName( prof[2] ); + temp->writeConfig(config); + config->sync(); + delete temp; + KOPrefs::instance()->mSyncProfileNames = prof; + } + + int i; + for ( i = 0; i < prof.count(); ++i ) { + + syncMenu->insertItem( prof[i], 1000+i ); + if ( i == 2 ) + syncMenu->insertSeparator(); + } + QDir app_dir; + if ( !app_dir.exists(QDir::homeDirPath()+"/Applications/dtm" ) ) { + syncMenu->setItemEnabled( false , 1000 ); + } +} + +int MainWindow::ringSync() +{ + int syncedProfiles = 0; + int i; + QTime timer; + KConfig *config = KOGlobals::config(); + QStringList syncProfileNames = KOPrefs::instance()->mSyncProfileNames; + KSyncProfile* temp = new KSyncProfile (); + KOPrefs::instance()->mAskForPreferences = false; + for ( i = 0; i < syncProfileNames.count(); ++i ) { + mCurrentSyncProfile = i; + temp->setName(syncProfileNames[mCurrentSyncProfile]); + temp->readConfig(config); + if ( temp->getIncludeInRingSync() && ( i < 1 || i > 2 )) { + setCaption(i18n("Profile ")+syncProfileNames[mCurrentSyncProfile]+ i18n(" is synced ... ")); + ++syncedProfiles; + // KOPrefs::instance()->mAskForPreferences = temp->getAskForPreferences(); + KOPrefs::instance()->mWriteBackFile = temp->getWriteBackFile(); + KOPrefs::instance()->mWriteBackExistingOnly = temp->getWriteBackExisting(); + KOPrefs::instance()->mShowSyncSummary = false; + mView->setSyncDevice(syncProfileNames[i] ); + mView->setSyncName( KOPrefs::instance()->mLocalMachineName ); + if ( i == 0 ) { + syncSharp(); + } else { + if ( temp->getIsLocalFileSync() ) { + if ( syncWithFile( temp->getRemoteFileName( ), true ) ) + KOPrefs::instance()->mLastSyncedLocalFile = temp->getRemoteFileName(); + } else { + syncRemote( temp, false ); + + } + } + timer.start(); + setCaption(i18n("Multiple sync in progress ... please wait!") ); + while ( timer.elapsed () < 2000 ) { + qApp->processEvents(); +#ifndef _WIN32_ + sleep (1); +#endif + } + + } + + } + delete temp; + return syncedProfiles; +} + +void MainWindow::multiSync( bool askforPrefs ) +{ + if (mBlockSaveFlag) + return; + mBlockSaveFlag = true; + QString question = i18n("Do you really want\nto multiple sync\nwith all checked profiles?\nSyncing takes some\ntime - all profiles\nare synced twice!"); + if ( QMessageBox::information( this, i18n("KO/Pi Sync"), + question, + i18n("Yes"), i18n("No"), + 0, 0 ) != 0 ) { + mBlockSaveFlag = false; + setCaption(i18n("Aborted! Nothing synced!")); + return; + } + mView->setSyncDevice(i18n("Multiple profiles") ); + KOPrefs::instance()->mSyncAlgoPrefs = KOPrefs::instance()->mRingSyncAlgoPrefs; + if ( askforPrefs ) { + mView->edit_sync_options(); + KOPrefs::instance()->mRingSyncAlgoPrefs = KOPrefs::instance()->mSyncAlgoPrefs; + } + setCaption(i18n("Multiple sync started.") ); + qApp->processEvents(); + int num = ringSync() ; + if ( num > 1 ) + ringSync(); + mBlockSaveFlag = false; + if ( num ) + save(); + if ( num ) + setCaption(i18n("%1 profiles synced. Multiple sync completed!").arg(num) ); + else + setCaption(i18n("Nothing synced! No profiles defined for multisync!")); + return; +} +void MainWindow::slotSyncMenu( int action ) +{ + //qDebug("syncaction %d ", action); + if ( action == 0 ) { + confSync(); + return; + } + if ( action == 1 ) { + multiSync( true ); + return; + } + + if (mBlockSaveFlag) + return; + mBlockSaveFlag = true; + mCurrentSyncProfile = action - 1000 ; + mView->setSyncDevice(KOPrefs::instance()->mSyncProfileNames[mCurrentSyncProfile] ); + mView->setSyncName( KOPrefs::instance()->mLocalMachineName ); + KConfig *config = KOGlobals::config(); + KSyncProfile* temp = new KSyncProfile (); + temp->setName(KOPrefs::instance()->mSyncProfileNames[mCurrentSyncProfile]); + temp->readConfig(config); + KOPrefs::instance()->mAskForPreferences = temp->getAskForPreferences(); + KOPrefs::instance()->mSyncAlgoPrefs = temp->getSyncPrefs(); + KOPrefs::instance()->mWriteBackFile = temp->getWriteBackFile(); + KOPrefs::instance()->mWriteBackExistingOnly = temp->getWriteBackExisting(); + KOPrefs::instance()->mShowSyncSummary = temp->getShowSummaryAfterSync(); + if ( action == 1000 ) { + syncSharp(); + + } else if ( action == 1001 ) { + syncLocalFile(); + + } else if ( action == 1002 ) { + quickSyncLocalFile(); + + } else if ( action >= 1003 ) { + if ( temp->getIsLocalFileSync() ) { + if ( syncWithFile( temp->getRemoteFileName( ), false ) ) + KOPrefs::instance()->mLastSyncedLocalFile = temp->getRemoteFileName(); + } else { + syncRemote( temp ); + + } + } + delete temp; + mBlockSaveFlag = false; +} +void MainWindow::setDefaultPreferences() +{ + KOPrefs *p = KOPrefs::instance(); + + p->mCompactDialogs = true; + p->mConfirm = true; + // p->mEnableQuickTodo = false; +} + +QString MainWindow::resourcePath() +{ + return KGlobal::iconLoader()->iconPath(); +} + +void MainWindow::displayText( QString text ,QString cap ) +{ + QDialog dia( this, "name", true ); ; + dia.setCaption( cap ); + QVBoxLayout* lay = new QVBoxLayout( &dia ); + lay->setSpacing( 3 ); + lay->setMargin( 3 ); + QTextBrowser tb ( &dia ); + lay->addWidget( &tb ); + tb.setText( text ); +#ifdef DESKTOP_VERSION + dia.resize( 640, 480); +#else + dia.showMaximized(); +#endif + dia.exec(); +} +void MainWindow::displayFile( QString fn, QString cap ) +{ + QString fileName = resourcePath() + fn; + QString text; + QFile file( fileName ); + if (!file.open( IO_ReadOnly ) ) { + return ; + + } + QTextStream ts( &file ); + text = ts.read(); + file.close(); + displayText( text, cap); +} +void MainWindow::features() +{ + + displayFile( "featuresKOPI.txt",i18n("KO/Pi Features and hints") ); +} + +void MainWindow::usertrans() +{ + + displayFile( "usertranslationHOWTO.txt",i18n("KO/Pi User translation HowTo") ); +} +void MainWindow::synchowto() +{ + + displayFile( "howtoSYNC.txt",i18n("KO/Pi Synchronization HowTo") ); +} +void MainWindow::faq() +{ + displayFile( "kopiFAQ.txt",i18n("KO/Pi FAQ") ); + +} +void MainWindow::whatsNew() +{ + displayFile( "kopiWhatsNew.txt",i18n("KO/Pi Version Info") ); + +} +void MainWindow::about() +{ + QString version; +#include <../version> + QMessageBox::about( this, i18n("About KOrganizer/Pi"), + i18n("KOrganizer/Platform-independent\n") + + "(KO/Pi) " + version + " - " + + +#ifdef DESKTOP_VERSION + i18n("Desktop Edition\n") + +#else + i18n("PDA-Edition\nfor: Zaurus 5x00 / 7x0 / 8x0\n") + +#endif + i18n("(c) 2004 Lutz Rogowski\nEmail:lutz@pi-sync.net\nKO/Pi is based on KOrganizer\n(c) 2002,2003 Cornelius Schumacher\nEmail: schumacher@kde.org\nKOrganizer/Pi is licensed\nunder the GPL.\nKO/Pi can be compiled for\nLinux, Zaurus-PDA and Windows\nwww.korganizer.org\nwww.pi-sync.net\n") ); +} +void MainWindow::keyBindings() +{ + QString cap = i18n("Key bindings KOrganizer/Pi"); + QString text = i18n("<p><h2>KO/Pi key shortcuts:</h2></p>\n") + + i18n("<p><b>H</b>: This help dialog | <b>S</b>: Search dialog</p>\n")+ + i18n("<p><b>I</b>: Show info for selected event/todo</p>\n") + + i18n("<p><b>Space</b>: Toggle fullscreen | <b>P</b>: Date picker</p>\n")+ + i18n("<p><b>F</b>: Toggle filterview |<b>F+ctrl</b>: Edit filter </p>\n")+ + i18n("<p><b>O</b>: Filter On/Off | <b>J</b>: Journal view</p>\n")+ + i18n("<p><b>1-0</b> (+<b>ctrl</b>): Select filter 1-10 (11-20)</p>\n")+ + i18n("<p><b>N</b>: Next days view| <b>W</b>: What's next view\n ")+ + i18n("<p><b>V</b>: Todo view | <b>L</b>: Event list view</p>\n")+ + i18n("<p><b>Z,Y</b>: Work week view | <b>U</b>: Week view</p>\n")+ + i18n("<p><b>D</b>: One day view | <b>M</b>: Month view</p>\n")+ + i18n("<p><b>E</b>: Edit selected item |<b> E+ctrl</b>: New Event</p>\n")+ + i18n("<p><b>T</b>: Goto today | <b>T+ctrl</b>: New Todo</p>\n")+ + i18n("<p><b>S+ctrl</b>: Add sub-todo | <b>X</b>: Toggle datenavigator</p>\n")+ + i18n("<p><b>+,-</b> : Zoom in/out agenda | <b>A</b>: Toggle allday agenda height</p>\n")+ + i18n("<p><b>C</b>: Show current time in agenda view</p>\n")+ + i18n("<p><b>B</b>: Edit description (details) of selected item</p>\n")+ + i18n("<p><b>right</b>: Next week | <b>right+ctrl</b>: Next month</p>\n")+ + i18n("<p><b>left</b>: Prev. week | <b>left+ctrl</b>: Prev. month</p>\n")+ + i18n("<p><b>del,backspace</b>: Delete selected item</p>\n")+ + i18n("<p><h3>In agenda view:</h3></p>\n") + + i18n("<p><b>up/down</b>: Scroll agenda view</p>\n")+ + i18n("<p><b>ctrl+up/down</b>: Scroll small todo view</p>\n")+ + i18n("<p><h3>In todo view:</h3></p>\n") + + i18n("<p><b>Q</b>: Toggle quick todo line edit.</p>\n")+ + i18n("<p><b>I</b>: Show info of current item+one step down.</p>\n")+ + i18n("<p><b>return</b>: Mark item as completed+one step down.</p>\n")+ + i18n("<p><b>return+shift</b>: Mark item as not completed+one step down</p>\n")+ + i18n("<p><h3>In list view:</h3></p>\n") + + i18n("<p><b>I</b>: Show info of current item+one step down.</p>\n")+ + i18n("<p><b>return</b>: Select item+one step down</p>\n")+ + i18n("<p><b>return+shift</b>: Deselect item+one step down</p>\n")+ + i18n("<p><b>up/down</b>: Next/prev item</p>\n")+ + i18n("<p><b>ctrl+up/down</b>: Goto up/down by 20% of items</p>\n")+ + i18n("<p><b>shift+up/down</b>: Goto first/last item</p>\n")+ + i18n("<p><h3>In event/todo viewer:</h3></p>\n") + + i18n("<p><b>I,C</b>: Close dialog.</p>\n")+ + i18n("<p><b>A</b>: Show agenda view.</p>\n")+ + i18n("<p><b>E</b>: Edit item</p>\n") + + i18n("<p><h2>KO/Pi icon colors:</h2></p>\n") + + i18n("<p><b>(for square icons in agenda and month view)</b></p>\n") + + i18n("<p><b>Cross</b>: Item cancelled.([c] in Whats'Next view)</p>\n")+ + i18n("<p><b>Red</b>: Alarm set.([a] in Whats'Next view)</p>\n")+ + i18n("<p><b>Blue</b>: Recurrent event.([r] in Whats'Next view)</p>\n")+ + i18n("<p><b>Dark green</b>: Information(description) available.([i] in WN view)</p>\n")+ + i18n("<p><b>Black</b>: Event/todo with attendees. You are the organizer!</p>\n")+ + i18n("<p><b>Dark yellow</b>: Event/todo with attendees.</p>\n") + + i18n("<p><b>White</b>: Item readonly</p>\n"); + displayText( text, cap); + +} +void MainWindow::aboutAutoSaving() +{ + QMessageBox* msg; + msg = new QMessageBox( i18n("Auto Saving in KOrganizer/Pi"), + i18n("After changing something, the data is\nautomatically saved to the file\n~/Applications/korganizer/calendar/mycalendar.ics\nafter (configureable) three minutes.\nFor safety reasons there is one autosaving\nafter 10 minutes (of idle time) again. The \ndata is saved automatically when closing KO/Pi\nYou can create a backup file \nwith: File - Save Calendar Backup\n"), QMessageBox::NoIcon, + QMessageBox::Ok, + QMessageBox::NoButton, + QMessageBox::NoButton); + msg->exec(); + delete msg; + + +} +void MainWindow::aboutKnownBugs() +{ + QMessageBox* msg; + msg = new QMessageBox( i18n("Known Problems in KOrganizer/Pi"), + i18n("1) Importing *.vcs or *.ics files from\nother applications may not work properly,\nif there are events with properties\nKO/Pi does not support.\n")+ + i18n("2) Audio alarm daemon\nfor Zaurus is available!\nas an additional small application\n")+ + i18n("\nPlease report unexpected behaviour to\nlutz@pi-sync.net\n") + + i18n("\nor report them in the bugtracker on\n") + + i18n("\nhttp://sourceforge.net/projects/kdepimpi\n"), + QMessageBox::NoIcon, + QMessageBox::Ok, + QMessageBox::NoButton, + QMessageBox::NoButton); + msg->exec(); + delete msg; + +} + +QString MainWindow::defaultFileName() +{ + return locateLocal( "data", "korganizer/mycalendar.ics" ); +} + +void MainWindow::processIncidenceSelection( Incidence *incidence ) +{ + if ( !incidence ) { + enableIncidenceActions( false ); + + mNewSubTodoAction->setEnabled( false ); + setCaptionToDates(); + return; + + } + + //KGlobal::locale()->formatDateTime(nextA, true); + QString startString = ""; + if ( incidence->type() != "Todo" ) { + if ( incidence->dtStart().date() < incidence->dtEnd().date() ) { + if ( incidence->doesFloat() ) { + startString += ": "+incidence->dtStartDateStr( true ); + startString += " --- "+((Event*)incidence)->dtEndDateStr( true ); + + } else { + startString = ": "+incidence->dtStartStr(true); + startString += " --- "+((Event*)incidence)->dtEndStr(true); + + } + + } else { + if ( incidence->dtStart().time() != incidence->dtEnd().time() ) + startString = ": "+KGlobal::locale()->formatTime(incidence->dtStart().time())+ + "-"+KGlobal::locale()->formatTime(incidence->dtEnd().time()); + startString +=" "+KGlobal::locale()->formatDate( incidence->dtStart().date(), true); + } + + } + else + startString = i18n(": (Prio ") +QString::number( (( KCal::Todo*)incidence)->priority() ) +") "+QString::number( (( KCal::Todo*)incidence)->percentComplete() ) +i18n("\% completed"); + if ( !incidence->location().isEmpty() ) + startString += " (" +incidence->location()+")"; + setCaption( incidence->summary()+startString); + + enableIncidenceActions( true ); + + if ( incidence->type() == "Event" ) { + mShowAction->setText( i18n("Show Event...") ); + mEditAction->setText( i18n("Edit Event...") ); + mDeleteAction->setText( i18n("Delete Event...") ); + + mNewSubTodoAction->setEnabled( false ); + } else if ( incidence->type() == "Todo" ) { + mShowAction->setText( i18n("Show Todo...") ); + mEditAction->setText( i18n("Edit Todo...") ); + mDeleteAction->setText( i18n("Delete Todo...") ); + + mNewSubTodoAction->setEnabled( true ); + } else { + mShowAction->setText( i18n("Show...") ); + mShowAction->setText( i18n("Edit...") ); + mShowAction->setText( i18n("Delete...") ); + + mNewSubTodoAction->setEnabled( false ); + } +} + +void MainWindow::enableIncidenceActions( bool enabled ) +{ + mShowAction->setEnabled( enabled ); + mEditAction->setEnabled( enabled ); + mDeleteAction->setEnabled( enabled ); +} + +void MainWindow::importBday() +{ + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + i18n("When importing birthdays twice\nduplicated events will be ignored,\nif the event has not been\nchanged in KO/Pi!\n"), + i18n("Import!"), i18n("Cancel"), 0, + 0, 1 ); + if ( result == 0 ) { + mView->importBday(); + + } + + +} +void MainWindow::importQtopia() +{ +#ifndef DESKTOP_VERSION + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + i18n("When importing a calendar twice\nduplicated events will be ignored!\nYou can create a backup file with\nFile - Save Calendar Backup\nto revert importing"), + i18n("Import!"), i18n("Cancel"), 0, + 0, 1 ); + if ( result == 0 ) { + QString datebook = Global::applicationFileName( "datebook", "datebook.xml"); + QString todolist = Global::applicationFileName( "todolist", "todolist.xml"); + QString categories = QString( getenv( "HOME" ) ) + "/Settings/Categories.xml"; + mView->importQtopia( categories, datebook, todolist ); + } +#else + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + i18n("Not supported \non desktop!\n"), + i18n("Ok"), i18n("Cancel"), 0, + 0, 1 ); + +#endif +} + +void MainWindow::saveOnClose() +{ + KOPrefs *p = KOPrefs::instance(); + p->mToolBarHor = ( iconToolBar->orientation () == Qt:: Horizontal ); + p->mToolBarUp = iconToolBar->x() > width()/2 || + iconToolBar->y() > height()/2; + mView->writeSettings(); + if ( mCalendarModifiedFlag || mView->checkFileChanged( defaultFileName())) + save(); +} +void MainWindow::slotModifiedChanged( bool changed ) +{ + if ( mBlockAtStartup ) + return; + int msec; + // we store the changes after 1 minute, + // and for safety reasons after 10 minutes again + if ( !mBlockSaveFlag ) + msec = (1000 * 60*KOPrefs::instance()->mAutoSaveInterval) +1000; + else + msec = 1000 * 600; + mSaveTimer.start( msec, true ); // 1 minute + qDebug("KO: Saving File in %d secs!", msec/1000); + mCalendarModifiedFlag = true; +} +#include <qfileinfo.h> +void MainWindow::save() +{ + if ( mBlockSaveFlag ) + return; + bool store = mBlockSaveFlag; + mBlockSaveFlag = true; + if ( mView->checkFileVersion( defaultFileName()) ) { + + QTime neededSaveTime = QDateTime::currentDateTime().time(); + setCaption(i18n("KO/Pi:Saving Data to File ..." )); + qDebug("KO: Start saving data to file!"); + mView->saveCalendar( defaultFileName() ); + + int msNeeded = neededSaveTime.msecsTo( QDateTime::currentDateTime().time() ); + mView->setLoadedFileVersion(QDateTime::currentDateTime()); + qDebug("KO: Needed %d ms for saving.",msNeeded ); + QString savemes; + savemes.sprintf(i18n("KO/Pi:File Saved. Needed %d sec, %d ms"),(msNeeded/1000)%100,msNeeded%1000 ); + setCaption(savemes); + } else + setCaption(i18n("Saving cancelled!")); + mCalendarModifiedFlag = false; + mBlockSaveFlag = store; +} + +void MainWindow::keyReleaseEvent ( QKeyEvent * e) +{ + if ( !e->isAutoRepeat() ) { + mFlagKeyPressed = false; + } +} +void MainWindow::keyPressEvent ( QKeyEvent * e ) +{ + qApp->processEvents(); + if ( e->isAutoRepeat() && !mFlagKeyPressed ) { + e->ignore(); + // qDebug(" ignore %d",e->isAutoRepeat() ); + return; + } + if (! e->isAutoRepeat() ) + mFlagKeyPressed = true; + KOPrefs *p = KOPrefs::instance(); + bool showSelectedDates = false; + int size; + int pro = 0; + //qDebug("MainWindow::keyPressEvent "); + switch ( e->key() ) { + case Qt::Key_Right: + if ( e->state() == Qt::ControlButton || e->state() == Qt::ShiftButton) + mView->goNextMonth(); + else + mView->goNext(); + showSelectedDates = true; + break; + case Qt::Key_Left: + if ( e->state() == Qt::ControlButton|| e->state() == Qt::ShiftButton ) + mView->goPreviousMonth(); + else + mView->goPrevious(); + showSelectedDates = true; + break; + case Qt::Key_Down: + mView->viewManager()->agendaView()->scrollOneHourDown(); + break; + case Qt::Key_Up: + mView->viewManager()->agendaView()->scrollOneHourUp(); + break; + case Qt::Key_I: + mView->showIncidence(); + break; + case Qt::Key_Delete: + case Qt::Key_Backspace: + mView->deleteIncidence(); + break; + case Qt::Key_D: + mView->viewManager()->showDayView(); + showSelectedDates = true; + break; + case Qt::Key_O: + mView->toggleFilerEnabled( ); + break; + case Qt::Key_0: + case Qt::Key_1: + case Qt::Key_2: + case Qt::Key_3: + case Qt::Key_4: + case Qt::Key_5: + case Qt::Key_6: + case Qt::Key_7: + case Qt::Key_8: + case Qt::Key_9: + pro = e->key()-48; + if ( pro == 0 ) + pro = 10; + if ( e->state() == Qt::ControlButton) + pro += 10; + break; + case Qt::Key_M: + mView->viewManager()->showMonthView(); + showSelectedDates = true; + break; + case Qt::Key_Insert: + mView->newEvent(); + break; + case Qt::Key_S : + if ( e->state() == Qt::ControlButton || e->state() == Qt::ShiftButton) + mView->newSubTodo(); + else + mView->dialogManager()->showSearchDialog(); + break; + case Qt::Key_Y : + case Qt::Key_Z : + mView->viewManager()->showWorkWeekView(); + showSelectedDates = true; + break; + case Qt::Key_U : + mView->viewManager()->showWeekView(); + showSelectedDates = true; + break; + case Qt::Key_H : + keyBindings(); + break; + case Qt::Key_W: + mView->viewManager()->showWhatsNextView(); + break; + case Qt::Key_L: + mView->viewManager()->showListView(); + break; + case Qt::Key_N: + mView->viewManager()->showNextXView(); + showSelectedDates = true; + break; + case Qt::Key_V: + mView->viewManager()->showTodoView(); + break; + case Qt::Key_C: + mView->viewManager()->agendaView()->setStartHour( QTime::currentTime ().hour() ); + break; + case Qt::Key_P: + mView->showDatePicker( ); + break; + case Qt::Key_F: + if ( e->state() == Qt::ControlButton|| e->state() == Qt::ShiftButton ) + mView->editFilters(); + else + mView->toggleFilter(); + break; + case Qt::Key_X: + mView->toggleDateNavigatorWidget(); + break; + case Qt::Key_Space: + mView->toggleExpand(); + break; + case Qt::Key_A: + mView->toggleAllDaySize(); + break; + case Qt::Key_T: + if ( e->state() == Qt::ControlButton|| e->state() == Qt::ShiftButton ) + mView->newTodo(); + else { + mView->goToday(); + showSelectedDates = true; + } + break; + case Qt::Key_J: + mView->viewManager()->showJournalView(); + break; + case Qt::Key_B: + mView->editIncidenceDescription();; + break; + // case Qt::Key_Return: + case Qt::Key_E: + if ( e->state() == Qt::ControlButton|| e->state() == Qt::ShiftButton ) + mView->newEvent(); + else + mView->editIncidence(); + break; + case Qt::Key_Plus: + size = p->mHourSize +2; + if ( size <= 18 ) + configureAgenda( size ); + break; + case Qt::Key_Minus: + size = p->mHourSize - 2; + if ( size >= 4 ) + configureAgenda( size ); + break; + + + default: + e->ignore(); + } + if ( pro > 0 ) { + mView->selectFilter( pro-1 ); + } + if ( showSelectedDates ) { + ;// setCaptionToDates(); + } + +} + +void MainWindow::configureToolBar( int item ) +{ + + configureToolBarMenu->setItemChecked( item, !configureToolBarMenu-> isItemChecked ( item ) ); + KOPrefs *p = KOPrefs::instance(); + p-> mShowIconStretch= configureToolBarMenu->isItemChecked( 5 ); + p-> mShowIconNewEvent= configureToolBarMenu->isItemChecked( 10 ); + p->mShowIconNewTodo = configureToolBarMenu->isItemChecked( 20 ); + p-> mShowIconSearch= configureToolBarMenu->isItemChecked( 120 ); + p-> mShowIconList= configureToolBarMenu->isItemChecked( 30 ); + p-> mShowIconDay1= configureToolBarMenu->isItemChecked( 40 ); + p-> mShowIconDay5= configureToolBarMenu->isItemChecked( 50 ); + p-> mShowIconDay7= configureToolBarMenu->isItemChecked( 60 ); + p-> mShowIconMonth= configureToolBarMenu->isItemChecked( 70 ); + p-> mShowIconTodoview= configureToolBarMenu->isItemChecked( 80 ); + p-> mShowIconBackFast= configureToolBarMenu->isItemChecked( 200 ); + p-> mShowIconBack = configureToolBarMenu->isItemChecked( 210 ); + p-> mShowIconToday= configureToolBarMenu->isItemChecked( 130 ); + p-> mShowIconForward= configureToolBarMenu->isItemChecked( 220 ); + p-> mShowIconForwardFast= configureToolBarMenu->isItemChecked( 230 ); + p-> mShowIconNextDays= configureToolBarMenu->isItemChecked( 100 ); + p-> mShowIconNext= configureToolBarMenu->isItemChecked( 110 ); + p-> mShowIconJournal= configureToolBarMenu->isItemChecked( 90 ); + p-> mShowIconWhatsThis= configureToolBarMenu->isItemChecked( 300 ); + // initActions(); +} + +void MainWindow::setCaptionToDates() +{ + QString selDates; + selDates = KGlobal::locale()->formatDate(mView->startDate(), true); + if (mView->startDate() < mView->endDate() ) + selDates += " - " + KGlobal::locale()->formatDate(mView->endDate(), true); + setCaption( i18n("Dates: ") + selDates ); + +} +// parameter item == 0: reinit +void MainWindow::configureAgenda( int item ) +{ + + KOPrefs *p = KOPrefs::instance(); + + int i; + if ( item == 1 ) { + mView->toggleAllDaySize(); + return; + } + // do not allow 4 for widgets higher than 480 + // if ( QApplication::desktop()->height() > 480 ) { +// if ( item == 4 ) +// item = 6; +// } + for ( i = 4; i <= 18; i= i+2 ) + configureAgendaMenu->setItemChecked( i, false ); + configureAgendaMenu->setItemChecked( item, true ); + if ( p->mHourSize == item ) + return; + p->mHourSize=item; + mView->viewManager()->agendaView()->updateConfig(); +} + +void MainWindow::saveCalendar() +{ + QString fn = KOPrefs::instance()->mLastSaveFile; + fn = KFileDialog::getSaveFileName( fn, i18n("Save backup filename"), this ); + + if ( fn == "" ) + return; + QFileInfo info; + info.setFile( fn ); + QString mes; + bool createbup = true; + if ( info. exists() ) { + mes = i18n("Backup file\nalready exists!\nOld backup file from:\n%1\nOverwrite?\n").arg(KGlobal::locale()->formatDateTime(info.lastModified (), true, false )) ; + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),mes, + i18n("Overwrite!"), i18n("Cancel"), 0, + 0, 1 ); + if ( result != 0 ) { + createbup = false; + } + } + if ( createbup ) { + mView->saveCalendar( fn ); + mes = i18n("KO/Pi:Saved %1").arg(fn); + KOPrefs::instance()->mLastSaveFile = fn; + setCaption(mes); + } +} +void MainWindow::loadCalendar() +{ + + QString fn = KOPrefs::instance()->mLastLoadFile; + fn = KFileDialog::getOpenFileName( fn, i18n("Load backup filename"), this ); + + if ( fn == "" ) + return; + QFileInfo info; + info.setFile( fn ); + QString mess; + bool loadbup = true; + if ( info. exists() ) { + mess = i18n("Backup file from:\n%1\nLoading backup\nfile will delete\nyour current Data!\n").arg(KGlobal::locale()->formatDateTime(info.lastModified (), true, false )); + int result = QMessageBox::warning( this, "KO/Pi: Warning!", + mess, + i18n("Load!"), i18n("Cancel"), 0, + 0, 1 ); + if ( result != 0 ) { + loadbup = false; + } + } else { + QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + i18n("Backup file\ndoes not exist!\nNothing loaded!"), 0, 0, + 0, 1 ); + + return; + } + if ( loadbup ) { + mView->openCalendar( fn ); + KOPrefs::instance()->mLastLoadFile = fn; + mess = i18n("KO/Pi:Loaded %1").arg(fn) ; + setCaption(mess); + } + +} +void MainWindow::quickImportIcal() +{ + importFile( KOPrefs::instance()->mLastImportFile, false ); +} +void MainWindow::importFile( QString fn, bool quick ) +{ + QFileInfo info; + info.setFile( fn ); + QString mess; + bool loadbup = true; + if ( !info. exists() ) { + mess = i18n("Import file \n...%1\ndoes not exist!\nNothing imported!\n").arg(fn.right( 30)); + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + mess ); + return; + } + int result = 0; + if ( !quick ) { + mess = i18n( "Import file \n...%1\nfrom:\n%2\nDuplicated entries\nwill not be imported!\n").arg(fn.right( 25)).arg(KGlobal::locale()->formatDateTime(info.lastModified (), true, false )); + result = QMessageBox::warning( this, "KO/Pi: Warning!", + mess, + "Import", "Cancel", 0, + 0, 1 ); + } + if ( result == 0 ) { + if ( mView->openCalendar( fn, true )) { + KOPrefs::instance()->mLastImportFile = fn; + setCaption(i18n("Imported file successfully")); + } else { + setCaption(i18n("Error importing file")); + } + } +} + +void MainWindow::importIcal() +{ + + QString fn =KOPrefs::instance()->mLastImportFile; + + fn =KFileDialog:: getOpenFileName( fn, i18n("Import filename(*.ics/*.vcs)"), this ); + if ( fn == "" ) + return; + importFile( fn, true ); + +} + +void MainWindow::exportVCalendar() +{ + QString fn = KOPrefs::instance()->mLastVcalFile; + fn = KFileDialog::getSaveFileName( fn, i18n("Export vcal filename(*.vcs)"), this ); + if ( fn == "" ) + return; + QFileInfo info; + info.setFile( fn ); + QString mes; + bool createbup = true; + if ( info. exists() ) { + mes = i18n("Save file\nalready exists!\nOld save file from:\n%1\nOverwrite?\n").arg (KGlobal::locale()->formatDateTime(info.lastModified (), true, false ) ); + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"),mes, + i18n("Overwrite!"), i18n("Cancel"), 0, + 0, 1 ); + if ( result != 0 ) { + createbup = false; + } + } + if ( createbup ) { + if ( mView->exportVCalendar( fn ) ) { + KOPrefs::instance()->mLastVcalFile = fn; + if ( fn.length() > 20 ) + mes = i18n("KO/Pi:Exported to ...%1").arg(fn.right(20)) ; + else + mes = i18n("KO/Pi:Exported to %1").arg(fn ); + setCaption(mes); + } + } + +} +#include <qpushbutton.h> +QString MainWindow::getPassword( ) +{ + QString retfile = ""; + QDialog dia ( this, "input-dialog", true ); + QLineEdit lab ( &dia ); + lab.setEchoMode( QLineEdit::Password ); + QVBoxLayout lay( &dia ); + lay.setMargin(7); + lay.setSpacing(7); + lay.addWidget( &lab); + dia.setFixedSize( 230,50 ); + dia.setCaption( i18n("Enter password") ); + QPushButton pb ( "OK", &dia); + lay.addWidget( &pb ); + connect(&pb, SIGNAL( clicked() ), &dia, SLOT ( accept() ) ); + dia.show(); + int res = dia.exec(); + if ( res ) + retfile = lab.text(); + dia.hide(); + qApp->processEvents(); + return retfile; + +} + +void MainWindow::syncLocalFile() +{ + + QString fn =KOPrefs::instance()->mLastSyncedLocalFile; + + fn =KFileDialog:: getOpenFileName( fn, i18n("Sync filename(*.ics/*.vcs)"), this ); + if ( fn == "" ) + return; + //mView->setSyncDevice("local-file" ); + if ( syncWithFile( fn, false ) ) { + // Event* e = mView->getLastSyncEvent(); +// e->setReadOnly( false ); +// e->setLocation( i18n("Local file: ")+ KOPrefs::instance()->mLastSyncedLocalFile); +// e->setReadOnly( true ); + } + +} + +bool MainWindow::syncWithFile( QString fn , bool quick ) +{ + bool ret = false; + QFileInfo info; + info.setFile( fn ); + QString mess; + bool loadbup = true; + if ( !info. exists() ) { + mess = i18n( "Sync file \n...%1\ndoes not exist!\nNothing synced!\n").arg(fn.right( 30) ); + int result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + mess ); + return ret; + } + int result = 0; + if ( !quick ) { + mess = i18n("Sync with file \n...%1\nfrom:\n%2\n").arg(fn.right( 25)).arg(KGlobal::locale()->formatDateTime(info.lastModified (), true, false )); + result = QMessageBox::warning( this, i18n("KO/Pi: Warning!"), + mess, + i18n("Sync"), i18n("Cancel"), 0, + 0, 1 ); + if ( result ) + return false; + } + if ( KOPrefs::instance()->mAskForPreferences ) + mView->edit_sync_options(); + if ( result == 0 ) { + //qDebug("Now sycing ... "); + if ( ret = mView->syncCalendar( fn, KOPrefs::instance()->mSyncAlgoPrefs ) ) + setCaption( i18n("Synchronization successful") ); + else + setCaption( i18n("Sync cancelled or failed. Nothing synced.") ); + if ( ! quick ) + KOPrefs::instance()->mLastSyncedLocalFile = fn; + slotModifiedChanged( true ); + } + return ret; +} +void MainWindow::quickSyncLocalFile() +{ + //mView->setSyncDevice("local-file" ); + //qDebug("quickSyncLocalFile() "); + if ( syncWithFile( KOPrefs::instance()->mLastSyncedLocalFile, false ) ) { + // Event* e = mView->getLastSyncEvent(); +// e->setReadOnly( false ); +// e->setLocation( i18n("Quick with file: ")+ KOPrefs::instance()->mLastSyncedLocalFile); +// e->setReadOnly( true ); + + } +} + +void MainWindow::confSync() +{ + mView->confSync(); + fillSyncMenu(); + mView->writeSettings(); + + +} +void MainWindow::syncRemote( KSyncProfile* prof, bool ask) +{ + QString question; + if ( ask ) { + question = i18n("Do you really want\nto remote sync\nwith profile \n")+ prof->getName()+" ?\n"; + if ( QMessageBox::information( this, i18n("KO/Pi Sync"), + question, + i18n("Yes"), i18n("No"), + 0, 0 ) != 0 ) + return; + } + QString command = prof->getPreSyncCommand(); + int fi; + if ( (fi = command.find("$PWD$")) > 0 ) { + QString pwd = getPassword(); + command = command.left( fi )+ pwd + command.mid( fi+5 ); + + } + int maxlen = 30; + if ( QApplication::desktop()->width() > 320 ) + maxlen += 25; + setCaption ( i18n( "Copy remote file to local machine..." ) ); + int fileSize = 0; + int result = system ( command ); + // 0 : okay + // 256: no such file or dir + // + qDebug("KO: Remote copy result(0 = okay): %d ",result ); + if ( result != 0 ) { + int len = maxlen; + while ( len < command.length() ) { + command.insert( len , "\n" ); + len += maxlen +2; + } + question = i18n("Sorry, the copy command failed!\nCommand was:\n%1\n \nTry command on console to get more\ndetailed info about the reason.\n").arg (command) ; + QMessageBox::information( this, i18n("KO/Pi Sync - ERROR"), + question, + i18n("Okay!")) ; + setCaption ("KO/Pi"); + return; + } + setCaption ( i18n( "Copying succeed." ) ); + //qDebug(" file **%s** ",prof->getLocalTempFile().latin1() ); + if ( syncWithFile( prof->getLocalTempFile(), true ) ) { +// Event* e = mView->getLastSyncEvent(); +// e->setReadOnly( false ); +// e->setLocation( KOPrefs::instance()->mSyncProfileNames[mCurrentSyncProfile]); +// e->setReadOnly( true ); + if ( KOPrefs::instance()->mWriteBackFile ) { + command = prof->getPostSyncCommand(); + setCaption ( i18n( "Writing back file ..." ) ); + result = system ( command ); + qDebug("KO: Writing back file result: %d ", result); + if ( result != 0 ) { + setCaption ( i18n( "Writing back file result: " )+QString::number( result ) ); + return; + } else { + setCaption ( i18n( "Syncronization sucessfully completed" ) ); + } + } + } + return; +} +void MainWindow::syncSSH() +{ + // not used anymore + QTime timer; + timer.start(); + //qDebug("MainWindow::syncssh() "); + KOPrefs *p = KOPrefs::instance(); + QString localFile = p->mLocalTempFile; + QString remoteIP = p->mRemoteIP; + QString remoteUser = p->mRemoteUser; + QString remoteFile = p->mRemoteFile; + if ( p->mUsePassWd && p->mRemotePassWd.length() > 0 ) + remoteUser += ":" + p->mRemotePassWd; + + QString question = i18n("Do you really want\nto remote sync?\n \n") + + i18n("IP: " ) +remoteIP +"\n" + + i18n("User: " ) + remoteUser +"\n" ; + int maxlen = 30; + if ( QApplication::desktop()->width() > 320 ) + maxlen += 25; + if ( remoteFile.length() > maxlen ) + question += i18n("Remote file:\n..." ) + remoteFile.right(maxlen) +"\n"; + else + question += i18n("Remote file:\n " ) + remoteFile +"\n"; + if ( localFile.length() > maxlen ) + question += i18n("Local temp file:\n..." ) + localFile.right(maxlen) +"\n"; + else + question += i18n("Local temp file:\n " ) + localFile +"\n"; + + if ( QMessageBox::information( this, i18n("KO/Pi Sync"), + question, + i18n("Yes"), i18n("No"), + 0, 0 ) != 0 ) + return; + // if ( !p->mUsePassWd ) { + // QString pass = getPassword(); + // if ( pass.length() > 0 ) + // remoteUser += ":" + pass; + // } + QString command = "scp " + remoteUser + "@" + remoteIP +":" + remoteFile +" " +localFile; + setCaption ( i18n( "Copy remote file to local machine..." ) ); + int fileSize = 0; + int result = system ( command ); + // 0 : okay + // 256: no such file or dir + // + qDebug("KO: Remote copy result(0 = okay): %d ",result ); + if ( result != 0 ) { + int len = maxlen; + while ( len < command.length() ) { + command.insert( len , "\n" ); + len += maxlen +2; + } + question = i18n("Sorry, the copy command failed!\nCommand was:\n%1\n \nTry command on console to get more\ndetailed info about the reason.\n").arg (command) ; + QMessageBox::information( this, i18n("KO/Pi Sync - ERROR"), + question, + i18n("Okay!")) ; + setCaption ("KO/Pi"); + return; + } + + + setCaption ( i18n( "Copying succeed." ) ); + //mView->setSyncDevice("ssh-scp" ); + if ( syncWithFile(localFile , true ) ) { +// Event* e = mView->getLastSyncEvent(); +// e->setReadOnly( false ); +// e->setLocation( KOPrefs::instance()->mSyncProfileNames[mCurrentSyncProfile]); +// e->setReadOnly( true ); + if ( KOPrefs::instance()->mWriteBackFile ) { + command = "scp " + localFile +" " +remoteUser + "@" + remoteIP +":" + remoteFile ; + setCaption ( i18n( "Writing back file ..." ) ); + result = system ( command ); + if ( result != 0 ) { + int len = maxlen; + while ( len < command.length() ) { + command.insert( len , "\n" ); + len += maxlen +2; + } + question = i18n("Sorry, the copy back command failed!\nCommand was:\n%1\n \nTry command on console to get more\ndetailed info about the reason.\n").arg (command) ; + QMessageBox::information( this, i18n("KO/Pi Sync - ERROR"), + question, + i18n("Okay!")) ; + setCaption ("KO/Pi"); + return; + } else { + setCaption ( i18n( "Syncronization sucessfully completed" ) ); + } + } + } + return; +#if 0 + system ("scp zaurus@192.168.0.65:/home/zaurus/Applications/korganizer/mycalendar.ics /home/polo/Applications/korganizer/z_sync.ics"); + while ( timer.elapsed() < 5000 ) + qApp->processEvents(); + + qDebug("MainWindow::merging) "); + mView->syncCalendar( "/home/polo/Applications/korganizer/z_sync.ics", 0 ); + while ( mBlockSaveFlag ) + qApp->processEvents(); + save(); + system ("scp /home/polo/Applications/korganizer/mycalendar.ics zaurus@192.168.0.65:/home/zaurus/Applications/korganizer/mycalendar.ics"); +#endif + +} + + +void MainWindow::syncSharp() +{ + if ( mCalendarModifiedFlag ) + save(); + mView->syncSharp(); + slotModifiedChanged( true ); + +} + +void MainWindow::printSel( ) +{ + mView->viewManager()->agendaView()->agenda()->printSelection(); +} + +void MainWindow::printCal() +{ + mView->print();//mCp->showDialog(); +} diff --git a/korganizer/mainwindow.h b/korganizer/mainwindow.h new file mode 100644 index 0000000..ee4aaa6 --- a/dev/null +++ b/korganizer/mainwindow.h @@ -0,0 +1,115 @@ +#ifndef KORGE_MAINWINDOW_H +#define KORGE_MAINWINDOW_H + +#include <qmainwindow.h> +#include <qtimer.h> +#include <qdict.h> + +#include <libkcal/incidence.h> +#include "simplealarmclient.h" + +class QAction; +class CalendarView; +class KSyncProfile; +#ifdef DESKTOP_VERSION + +#define QPEToolBar QToolBar +#define QPEMenuBar QMenuBar +#endif +class QPEToolBar; + +namespace KCal { +class CalendarLocal; +} + +using namespace KCal; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + public: + MainWindow( QWidget *parent = 0, const char *name = 0, QString command = ""); + ~MainWindow(); + public slots: + void configureAgenda( int ); + void recieve( const QCString& msg, const QByteArray& data ); + static QString defaultFileName(); + static QString resourcePath(); + protected slots: + void setCaptionToDates(); + int ringSync(); + void multiSync( bool askforPrefs = false ); + void about(); + void faq(); + void usertrans(); + void features(); + void synchowto(); + void whatsNew(); + void keyBindings(); + void aboutAutoSaving();; + void aboutKnownBugs(); + + void processIncidenceSelection( Incidence * ); + + void importQtopia(); + void importBday(); + void importIcal(); + void importFile( QString, bool ); + void quickImportIcal(); + + void slotModifiedChanged( bool ); + + void save(); + void configureToolBar( int ); + void printSel(); + void printCal(); + void saveCalendar(); + void loadCalendar(); + void exportVCalendar(); + + void slotSyncMenu( int ); + void syncSSH(); + void confSync(); + void syncSharp(); + void syncLocalFile(); + bool syncWithFile( QString, bool ); + void quickSyncLocalFile(); + + + protected: + void displayText( QString, QString); + void displayFile( QString, QString); + + void enableIncidenceActions( bool ); + + private: + void saveOnClose(); + int mCurrentSyncProfile; + void syncRemote( KSyncProfile* , bool ask = true); + void fillSyncMenu(); + bool mFlagKeyPressed; + bool mBlockAtStartup; + QPEToolBar *iconToolBar; + void initActions(); + void setDefaultPreferences(); + void keyPressEvent ( QKeyEvent * ) ; + void keyReleaseEvent ( QKeyEvent * ) ; + QPopupMenu *configureToolBarMenu; + QPopupMenu *configureAgendaMenu, *syncMenu; + CalendarLocal *mCalendar; + CalendarView *mView; + QString getPassword(); + QAction *mNewSubTodoAction; + + QAction *mShowAction; + QAction *mEditAction; + QAction *mDeleteAction; + void closeEvent( QCloseEvent* ce ); + SimpleAlarmClient mAlarmClient; + QTimer mSaveTimer; + bool mBlockSaveFlag; + bool mCalendarModifiedFlag; + QPixmap loadPixmap( QString ); +}; + +#endif diff --git a/korganizer/navigatorbar.cpp b/korganizer/navigatorbar.cpp new file mode 100644 index 0000000..1052a99 --- a/dev/null +++ b/korganizer/navigatorbar.cpp @@ -0,0 +1,199 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qstring.h> +#include <qtooltip.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qframe.h> +#include <qlabel.h> +#include <qapplication.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> +#include <kiconloader.h> +#include "libkdepim/kdatepicker.h" +#include <knotifyclient.h> +#include "kdatetbl.h" + +#include "koglobals.h" +#include "koprefs.h" +#ifndef KORG_NOPLUGINS +#include "kocore.h" +#endif + +#include <kcalendarsystem.h> + +#include "navigatorbar.h" + +NavigatorBar::NavigatorBar( const QDate & date, QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QBoxLayout *topLayout = new QHBoxLayout( this ); + + // Set up the control buttons and date label + mCtrlFrame = new QFrame( this ); + mCtrlFrame->setFrameStyle(QFrame::Panel|QFrame::Raised); + mCtrlFrame->setLineWidth(1); + + topLayout->addWidget( mCtrlFrame ); + + QFont tfont = font(); + if ( QApplication::desktop()->width() >= 480 ) + tfont.setPointSize(tfont.pointSize()+2); + tfont.setBold(true); + + bool isRTL = KOGlobals::self()->reverseLayout(); +#ifndef DESKTOP_VERSION + bool isDesktop = false; +#else + bool isDesktop = true; +#endif + if ( QString ( name ) == QString("useBigPixmaps") && QApplication::desktop()->width() > 320 ) + isDesktop = true; + // Create backward navigation buttons + mPrevYear = new QPushButton( mCtrlFrame ); + mPrevYear->setPixmap( SmallIcon( isDesktop ? "2leftarrowB" : "2leftarrow" ) ); + QToolTip::add( mPrevYear, i18n("Previous Year") ); + + mPrevMonth = new QPushButton( mCtrlFrame ); + mPrevMonth->setPixmap( SmallIcon( isDesktop ? "1leftarrowB" : "1leftarrow") ); + QToolTip::add( mPrevMonth, i18n("Previous Month") ); + + // Create forward navigation buttons + mNextMonth = new QPushButton( mCtrlFrame ); + mNextMonth->setPixmap( SmallIcon( isDesktop ? "1rightarrowB" : "1rightarrow") ); + QToolTip::add( mNextMonth, i18n("Next Month") ); + + mNextYear = new QPushButton( mCtrlFrame ); + mNextYear->setPixmap( SmallIcon( isDesktop ? "2rightarrowB": "2rightarrow") ); + QToolTip::add( mNextYear, i18n("Next Year") ); + mSelectMonth = new QPushButton( mCtrlFrame ); + // Create month name label + //selectMonth->setFont( tfont ); + // selectMonth->setAlignment( AlignCenter ); + //mDateLabel = new QLabel( selectMonth ); + //mDateLabel->setFont( tfont ); + //mDateLabel->setAlignment( AlignCenter ); + if ( QString ( name ) == QString("useBigPixmaps") ) { + mNextMonth->setFlat( true); + mNextYear->setFlat( true); + mSelectMonth->setFlat( true); + mPrevYear->setFlat( true); + mPrevMonth->setFlat( true); + } + mSelectMonth->setFont( tfont ); + // Set minimum width to width of widest month name label + int i; + int maxwidth = 0; + QFontMetrics fm ( mSelectMonth->font() ); + int width = fm.width("September '00" ); +// for( i = 1; i <= KOGlobals::self()->calendarSystem()->monthsInYear(date); +// ++i ) { +// //int width = fm.width( KOGlobals::self()->calendarSystem()->monthName(i, +// // KOGlobals::self()->calendarSystem()->year(date) ) + " 2000" ); +// int width = fm.width("September 2000" ); +// if ( width > maxwidth ) maxwidth = width; +// } + maxwidth = width+2; + int size = fm.height()+2; + if ( QApplication::desktop()->width() >= 480 ) { + size += 6; + maxwidth+= 6; + } + mSelectMonth->setFixedWidth( maxwidth ); + mSelectMonth->setFixedHeight( size ); + mPrevYear->setFixedHeight( size ); + mPrevMonth->setFixedHeight( size ); + mNextMonth->setFixedHeight( size ); + mNextYear->setFixedHeight ( size ); + // set up control frame layout + QBoxLayout *ctrlLayout = new QHBoxLayout( mCtrlFrame, 1 ); + ctrlLayout->addWidget( mPrevYear, 3 ); + ctrlLayout->addWidget( mPrevMonth, 3 ); + //ctrlLayout->addStretch( 1 ); + // ctrlLayout->addSpacing( 1 ); + // ctrlLayout->addWidget( mDateLabel ); + ctrlLayout->addWidget( mSelectMonth ); + // ctrlLayout->addSpacing( 1 ); + // ctrlLayout->addStretch( 1 ); + ctrlLayout->addWidget( mNextMonth, 3 ); + ctrlLayout->addWidget( mNextYear, 3 ); + + connect( mPrevYear, SIGNAL( clicked() ), SIGNAL( goPrevYear() ) ); + connect( mPrevMonth, SIGNAL( clicked() ), SIGNAL( goPrevMonth() ) ); + connect( mNextMonth, SIGNAL( clicked() ), SIGNAL( goNextMonth() ) ); + connect( mNextYear, SIGNAL( clicked() ), SIGNAL( goNextYear() ) ); + connect( mSelectMonth, SIGNAL( clicked() ),SLOT( selectMonth() ) ); + mPrevYear->setFocusPolicy(NoFocus); + mPrevMonth->setFocusPolicy(NoFocus); + mNextMonth->setFocusPolicy(NoFocus); + mNextYear->setFocusPolicy(NoFocus); + mSelectMonth->setFocusPolicy(NoFocus); +} + +NavigatorBar::~NavigatorBar() +{ +} + +void NavigatorBar::selectMonth() +{ + + int month; + KPopupFrame* popup = new KPopupFrame(this); + int size = 12; + if ( QApplication::desktop()->width() >= 480 ) + size = 18; + KDateInternalMonthPicker* picker = new KDateInternalMonthPicker(size, popup); + // ----- + picker->resize(picker->sizeHint()); + popup->setMainWidget(picker); + picker->setFocus(); + connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int))); + if(popup->exec(mSelectMonth->mapToGlobal(QPoint(0, mSelectMonth->height())))) + { + month = picker->getResult(); + emit monthSelected ( month ); + } else { + KNotifyClient::beep(); + } + delete popup; +} +void NavigatorBar::selectDates( const KCal::DateList &dateList ) +{ + if (dateList.count() > 0) { + QDate date = dateList.first(); + + const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); + + // compute the label at the top of the navigator + QString dtstr = i18n(calSys->monthName( date )) + " '" + + QString::number( calSys->year( date ) ).right(2); + + mSelectMonth->setText( dtstr ); + } +} + +#include "navigatorbar.moc" diff --git a/korganizer/navigatorbar.h b/korganizer/navigatorbar.h new file mode 100644 index 0000000..9c5c0cf --- a/dev/null +++ b/korganizer/navigatorbar.h @@ -0,0 +1,66 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef NAVIGATORBAR_H +#define NAVIGATORBAR_H + +#include <libkcal/incidencebase.h> + +#include <qwidget.h> + +class QPushButton; +class QFrame; +class QLabel; + +class NavigatorBar: public QWidget +{ + Q_OBJECT + public: + NavigatorBar( const QDate & date, QWidget *parent = 0, const char *name = 0 ); + ~NavigatorBar(); + + public slots: + void selectDates( const KCal::DateList & ); + void selectMonth(); + + signals: + void goNextMonth(); + void goPrevMonth(); + void goNextYear(); + void goPrevYear(); + void monthSelected( int ); + + + private: + QFrame *mCtrlFrame; + + QPushButton *mPrevYear; + QPushButton *mPrevMonth; + QPushButton *mNextMonth; + QPushButton *mNextYear; + QPushButton *mSelectMonth; + + //QLabel *mDateLabel; +}; + +#endif diff --git a/korganizer/navigatorbar.moc b/korganizer/navigatorbar.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/navigatorbar.moc diff --git a/korganizer/outgoingdialog.cpp b/korganizer/outgoingdialog.cpp new file mode 100644 index 0000000..4eb64f3 --- a/dev/null +++ b/korganizer/outgoingdialog.cpp @@ -0,0 +1,394 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> + +#include <qfile.h> +#include <qdir.h> +#include <qtextstream.h> + +#include <kglobal.h> +#include <klocale.h> +#include <ktempfile.h> +#include <kstandarddirs.h> + +#include <libkcal/event.h> +#include <libkcal/freebusy.h> +//#include <libkcal/imipscheduler.h> +#include <libkcal/dummyscheduler.h> +#include <libkcal/icalformat.h> +#include <libkcal/calendar.h> + +#ifndef KORG_NOMAIL +#include "mailscheduler.h" +#endif + +#include "koprefs.h" +#include "outgoingdialog.h" +#include "koeventviewerdialog.h" +#include "docprefs.h" + +ScheduleItemOut::ScheduleItemOut(QListView *parent,IncidenceBase *ev, + Scheduler::Method method, + const QString &recipients) + : QListViewItem(parent) +{ + mIncidence = ev; + mMethod = method; + mRecipients = recipients; + +// kdDebug() << "ScheduleItemOut: setting the summary" << endl; + //Set the summary + if(ev->type() != "FreeBusy") { + Incidence *incidence = static_cast<Incidence *>(ev); + setText(0,incidence->summary()); + } else { + setText(0,i18n("Free Busy Object")); + } + +// kdDebug() << "ScheduleItemOut: checking if the object is an event" << endl; + //If the object is an event + if(ev->type()=="Event") { + Event *event = static_cast<Event *>(ev); + + setText(1,event->dtStartDateStr()); + if (event->doesFloat()) { //If the event floats set the start and end times to no time + setText(2,i18n("no time")); + setText(4,i18n("no time")); + } else { //If it does not float + setText(2,event->dtStartTimeStr()); + if (event->hasDuration()) { + setText(4,event->dtEndTimeStr()); + } else { + setText(4,i18n("no time")); + } + } + if (event->hasEndDate()) { + setText(3,event->dtEndDateStr()); + } + else { + setText(3,i18n("no time")); + } + } + + //If the object is an Todo + if(ev->type()=="Todo") { + Todo *event = static_cast<Todo *>(ev); + if (event->hasStartDate()) { + setText(1,event->dtStartDateStr()); + if (!event->doesFloat()) { + setText(2,event->dtStartTimeStr()); + } + } + if (event->hasDueDate()) { + setText(3,event->dtDueDateStr()); + if (!event->doesFloat()) { + setText(4,event->dtDueTimeStr()); + } + } + } + +// kdDebug() << "ScheduleItemOut: checking if the object is a FreeBusy object" << endl; + //If the object is a freebusy object + if(ev->type() == "FreeBusy") { + FreeBusy *freebusy = static_cast<FreeBusy *>(ev); + + setText(1,freebusy->dtStartDateStr()); + setText(2,freebusy->dtStartTimeStr()); + //Must try and get this to the users local settings + setText(3,KGlobal::locale()->formatDate( freebusy->dtEnd().date() ) ); + setText(4,KGlobal::locale()->formatTime( freebusy->dtEnd().time() ) ); + } + +// kdDebug() << "ScheduleItemOut: Setting the method" << endl; + //Set the Method + setText(5,Scheduler::translatedMethodName(mMethod)); +} + +OutgoingDialog::OutgoingDialog(Calendar *calendar,QWidget* parent, + const char* name,bool modal, + WFlags fl) + : OutgoingDialog_base(parent,name,modal,fl) +{ + mCalendar = calendar; + + mFormat = new ICalFormat; + + if (KOPrefs::instance()->mIMIPScheduler == KOPrefs::IMIPDummy ) { + mScheduler = new DummyScheduler(mCalendar); + } else { +#ifndef KORG_NOMAIL + mScheduler = new MailScheduler(mCalendar); +#else + mScheduler = new DummyScheduler(mCalendar); +#endif + } + mMessageListView->setColumnAlignment(1,AlignHCenter); + mMessageListView->setColumnAlignment(2,AlignHCenter); + mMessageListView->setColumnAlignment(3,AlignHCenter); + mMessageListView->setColumnAlignment(4,AlignHCenter); + QObject::connect(mMessageListView,SIGNAL(doubleClicked(QListViewItem *)), + this,SLOT(showEvent(QListViewItem *))); + mDocPrefs = new DocPrefs("groupschedule"); + loadMessages(); +} + +OutgoingDialog::~OutgoingDialog() +{ + delete mDocPrefs; + delete mFormat; +} + +bool OutgoingDialog::addMessage(IncidenceBase *incidence,Scheduler::Method method) +{ + kdDebug() << "Outgoing::addMessage" << "Method:" << method << endl; + if (method == Scheduler::Publish) return false; + if( mDocPrefs ) { + if (method != Scheduler::Cancel) { + mDocPrefs->writeEntry( incidence->uid()+"-scheduled", true ); + } else { + if (!mDocPrefs->readBoolEntry(incidence->uid()+"-scheduled") ) + return true; + } + } + + if (KOPrefs::instance()->mIMIPSend == KOPrefs::IMIPOutbox) { + new ScheduleItemOut(mMessageListView,incidence,method); + saveMessage(incidence,method); + emit numMessagesChanged(mMessageListView->childCount()); + } + else { + mScheduler->performTransaction(incidence,method); + } + return true; +} + +bool OutgoingDialog::addMessage(IncidenceBase *incidence,Scheduler::Method method, + const QString &recipients) +{ + //if (method != Scheduler::Publish) return false; + if( mDocPrefs ) { + if (method != Scheduler::Cancel) { + mDocPrefs->writeEntry( incidence->uid()+"-scheduled", true ); + } else { + if (!mDocPrefs->readBoolEntry(incidence->uid()+"-scheduled") ) + return true; + } + } + if (KOPrefs::instance()->mIMIPSend == KOPrefs::IMIPOutbox) { + new ScheduleItemOut(mMessageListView,incidence,method,recipients); + saveMessage(incidence,method,recipients); + emit numMessagesChanged(mMessageListView->childCount()); + } + else { + mScheduler->performTransaction(incidence,method,recipients); + } + return true; +} + +void OutgoingDialog::send() +{ + kdDebug() << "OutgoingDialog::send" << endl; + ScheduleItemOut *item = (ScheduleItemOut *)(mMessageListView->firstChild()); + while(item) { + bool success; + if (item->method() == Scheduler::Publish) { + success = mScheduler->publish(item->event(),item->recipients()); + } else { + success = mScheduler->performTransaction(item->event(),item->method()); + } + ScheduleItemOut *oldItem = item; + item = (ScheduleItemOut *)(item->nextSibling()); + if (success) { + deleteMessage(oldItem->event()); + delete (oldItem->event()); + delete oldItem; + } + } + + emit numMessagesChanged(mMessageListView->childCount()); +} + +void OutgoingDialog::deleteItem() +{ + ScheduleItemOut *item = (ScheduleItemOut *)(mMessageListView->selectedItem()); + if(!item) + return; + deleteMessage(item->event()); + delete(item->event()); + mMessageListView->takeItem(item); + emit numMessagesChanged(mMessageListView->childCount()); +} + +void OutgoingDialog::showEvent(QListViewItem *qitem) +{ + ScheduleItemOut *item = (ScheduleItemOut *)qitem; + Event *event = 0; + Todo *todo = 0; + if ( item->event()->type()=="Event" ) { + event = static_cast<Event *>(item->event()); + } + if ( item->event()->type()=="Todo" ) { + todo = static_cast<Todo *>(item->event()); + } + QString sendText; + if (event || todo) { + KOEventViewerDialog *eventViewer = new KOEventViewerDialog(this); + if (event) eventViewer->setEvent(event); + if (todo) eventViewer->setTodo(todo); + sendText = "<hr><h4>"+i18n("Event will be sent to:")+"</h4>"; + switch (item->method()) { + case Scheduler::Publish: { + sendText += item->recipients(); + break; } + case Scheduler::Request: { + sendText += i18n("All attendees"); + break; } + case Scheduler::Refresh: { + sendText += i18n("All attendees"); + break; } + case Scheduler::Cancel: { + sendText += i18n("All attendees"); + break; } + case Scheduler::Add: { + sendText += i18n("All attendees"); + break; } + case Scheduler::Reply: { + sendText += i18n("The organizer %1").arg(item->event()->organizer()); + break; } + case Scheduler::Counter: { + sendText += i18n("The organizer %1").arg(item->event()->organizer()); + break; } + case Scheduler::Declinecounter: { + sendText += i18n("All attendees"); + break; } + case Scheduler::NoMethod: { + sendText += ""; + break; } + default: + sendText = ""; + } + eventViewer->addText(sendText); + eventViewer->show(); + } +} + +bool OutgoingDialog::saveMessage(IncidenceBase *incidence,Scheduler::Method method, + const QString &recipients) +{ + KTempFile ktfile(locateLocal("data","korganizer/outgoing/"),"ics"); + QString messageText = mFormat->createScheduleMessage(incidence,method); + QTextStream *qts = ktfile.textStream(); + *qts << messageText; + *qts << "METHOD-BEGIN:" << endl << method << endl << ":METHOD-END" << endl; + *qts << "RECIPIENTS-BEGIN:" << endl << recipients << endl << ":RECIPIENTS-END" << endl; + mMessageMap[incidence]=ktfile.name(); + + return true; +} + +bool OutgoingDialog::deleteMessage(IncidenceBase *incidence) +{ + QFile f( mMessageMap[incidence] ); + mMessageMap.remove(incidence); + if ( !f.exists() ) return false; + else + return f.remove(); +} + +void OutgoingDialog::loadMessages() +{ + Scheduler::Method method; + QString recipients; + + QString outgoingDirName = locateLocal("data","korganizer/outgoing"); + QDir outgoingDir(outgoingDirName); + QStringList outgoing = outgoingDir.entryList(QDir::Files); + QStringList::ConstIterator it; + for(it = outgoing.begin(); it != outgoing.end(); ++it) { + kdDebug() << "-- File: " << (*it) << endl; + QFile f(outgoingDirName + "/" + (*it)); + bool inserted = false; + QMap<IncidenceBase*, QString>::Iterator iter; + for ( iter = mMessageMap.begin(); iter != mMessageMap.end(); ++iter ) { + if (iter.data() == outgoingDirName + "/" + (*it)) inserted = true; + } + if (!inserted) { + if (!f.open(IO_ReadOnly)) { + kdDebug() << "OutgoingDialog::loadMessage(): Can't open file'" + << (*it) << "'" << endl; + } else { + QTextStream t(&f); + QString messageString = t.read(); + ScheduleMessage *message = mFormat->parseScheduleMessage(mCalendar, + messageString); + int begin_pos = messageString.find("METHOD-BEGIN:"); + begin_pos = messageString.find('\n',begin_pos)+1; + QString meth = messageString.mid(begin_pos,1); + switch (meth.toInt()) { + case 0:method=Scheduler::Publish; break; + case 1:method=Scheduler::Request; break; + case 2:method=Scheduler::Refresh; break; + case 3:method=Scheduler::Cancel; break; + case 4:method=Scheduler::Add; break; + case 5:method=Scheduler::Reply; break; + case 6:method=Scheduler::Counter; break; + case 7:method=Scheduler::Declinecounter; break; + default :method=Scheduler::NoMethod; break; + } + begin_pos = messageString.find("RECIPIENTS-BEGIN:"); + begin_pos = messageString.find('\n',begin_pos)+1; + int end_pos = messageString.find(":RECIPIENTS-END",begin_pos)-1; + recipients = messageString.mid(begin_pos, end_pos-begin_pos); + kdDebug() << "Outgoing::loadMessage(): Recipients: " << recipients << endl; + + if (message) { + bool inserted = false; + QMap<IncidenceBase*, QString>::Iterator iter; + for ( iter = mMessageMap.begin(); iter != mMessageMap.end(); ++iter ) { + if (iter.data() == outgoingDirName + "/" + (*it)) inserted = true; + } + if (!inserted) { + kdDebug() << "OutgoingDialog::loadMessage(): got message '" + << (*it) << "'" << endl; + IncidenceBase *inc = message->event(); + new ScheduleItemOut(mMessageListView,inc,method,recipients); + mMessageMap[message->event()]=outgoingDirName + "/" + (*it); + } + } else { + QString errorMessage; + if (mFormat->exception()) { + errorMessage = mFormat->exception()->message(); + } + kdDebug() << "OutgoingDialog::loadMessage(): Error parsing " + "message: " << errorMessage << endl; + } + f.close(); + } + } + } + emit numMessagesChanged(mMessageListView->childCount()); +} + +void OutgoingDialog::setDocumentId( const QString &id ) +{ + mDocPrefs->setDoc( id ); +} + +#include "outgoingdialog.moc" diff --git a/korganizer/outgoingdialog.h b/korganizer/outgoingdialog.h new file mode 100644 index 0000000..a3d561a --- a/dev/null +++ b/korganizer/outgoingdialog.h @@ -0,0 +1,88 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef OUTGOINGDIALOG_H +#define OUTGOINGDIALOG_H + +#include <qlistview.h> +#include <qmap.h> +#include <qstring.h> + +#include <libkcal/scheduler.h> + +#include "docprefs.h" +#include "outgoingdialog_base.h" + +using namespace KCal; + +class ScheduleItemOut : public QListViewItem +{ + public: + ScheduleItemOut(QListView *parent,IncidenceBase *ev, + Scheduler::Method method, const QString &recipients=QString::null); + virtual ~ScheduleItemOut() {} + + IncidenceBase *event() { return mIncidence; } + Scheduler::Method method() { return mMethod; } + QString recipients() { return mRecipients; } + + private: + IncidenceBase *mIncidence; + Scheduler::Method mMethod; + QString mRecipients; +}; + +class OutgoingDialog : public OutgoingDialog_base +{ + Q_OBJECT + public: + OutgoingDialog(Calendar *,QWidget* parent=0,const char* name=0, + bool modal=false,WFlags fl=0); + ~OutgoingDialog(); + + bool addMessage(IncidenceBase *,Scheduler::Method); + bool addMessage(IncidenceBase *,Scheduler::Method,const QString &recipients); + void setDocumentId( const QString &id ); + + public slots: + void loadMessages(); + + signals: + void numMessagesChanged(int); + + protected slots: + void send(); + void deleteItem(); + void showEvent(QListViewItem *); + + private: + bool saveMessage(IncidenceBase *,Scheduler::Method,const QString &recipients=0); + bool deleteMessage(IncidenceBase *); + + Calendar *mCalendar; + ICalFormat *mFormat; + Scheduler *mScheduler; + QMap<IncidenceBase*, QString> mMessageMap; + DocPrefs *mDocPrefs; +}; + +#endif // OUTGOINGDIALOG_H diff --git a/korganizer/outgoingdialog.moc b/korganizer/outgoingdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/outgoingdialog.moc diff --git a/korganizer/outgoingdialog_base.cpp b/korganizer/outgoingdialog_base.cpp new file mode 100644 index 0000000..e5b913a --- a/dev/null +++ b/korganizer/outgoingdialog_base.cpp @@ -0,0 +1,109 @@ +#include <klocale.h> +/**************************************************************************** +** Form implementation generated from reading ui file '/build/kde/cvs/korge/kdepim/korganizer/outgoingdialog_base.ui' +** +** Created: Sat Mar 29 22:31:21 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#include "outgoingdialog_base.h" + +#include <qvariant.h> +#include <qheader.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a OutgoingDialog_base as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +OutgoingDialog_base::OutgoingDialog_base( QWidget* parent, const char* name, bool modal, WFlags fl ) + : QDialog( parent, name, modal, fl ) + +{ + if ( !name ) + setName( "OutgoingDialog_base" ); + OutgoingDialog_baseLayout = new QGridLayout( this, 1, 1, 11, 6, "OutgoingDialog_baseLayout"); + + mMessageListView = new QListView( this, "mMessageListView" ); + mMessageListView->addColumn( tr2i18n( "Summary" ) ); + mMessageListView->addColumn( tr2i18n( "Start Date" ) ); + mMessageListView->addColumn( tr2i18n( "Start Time" ) ); + mMessageListView->addColumn( tr2i18n( "End Date" ) ); + mMessageListView->addColumn( tr2i18n( "End Time" ) ); + mMessageListView->addColumn( tr2i18n( "Method" ) ); + mMessageListView->setFrameShape( QListView::StyledPanel ); + mMessageListView->setFrameShadow( QListView::Sunken ); + mMessageListView->setAllColumnsShowFocus( TRUE ); + + OutgoingDialog_baseLayout->addMultiCellWidget( mMessageListView, 0, 3, 0, 0 ); + + PushButton5 = new QPushButton( this, "PushButton5" ); + PushButton5->setDefault( FALSE ); + + OutgoingDialog_baseLayout->addWidget( PushButton5, 0, 1 ); + + PushButton7 = new QPushButton( this, "PushButton7" ); + + OutgoingDialog_baseLayout->addWidget( PushButton7, 1, 1 ); + + PushButton6 = new QPushButton( this, "PushButton6" ); + PushButton6->setDefault( TRUE ); + + OutgoingDialog_baseLayout->addWidget( PushButton6, 3, 1 ); + QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding ); + OutgoingDialog_baseLayout->addItem( spacer, 2, 1 ); + languageChange(); + resize( QSize(582, 274).expandedTo(minimumSizeHint()) ); + + // signals and slots connections + connect( PushButton6, SIGNAL( clicked() ), this, SLOT( accept() ) ); + connect( PushButton5, SIGNAL( clicked() ), this, SLOT( send() ) ); + connect( PushButton7, SIGNAL( clicked() ), this, SLOT( deleteItem() ) ); +} + +/* + * Destroys the object and frees any allocated resources + */ +OutgoingDialog_base::~OutgoingDialog_base() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void OutgoingDialog_base::languageChange() +{ + setCaption( tr2i18n( "Scheduler - Outgoing Messages" ) ); + mMessageListView->header()->setLabel( 0, tr2i18n( "Summary" ) ); + mMessageListView->header()->setLabel( 1, tr2i18n( "Start Date" ) ); + mMessageListView->header()->setLabel( 2, tr2i18n( "Start Time" ) ); + mMessageListView->header()->setLabel( 3, tr2i18n( "End Date" ) ); + mMessageListView->header()->setLabel( 4, tr2i18n( "End Time" ) ); + mMessageListView->header()->setLabel( 5, tr2i18n( "Method" ) ); + PushButton5->setText( tr2i18n( "&Send Messages" ) ); + PushButton7->setText( tr2i18n( "&Remove" ) ); + PushButton6->setText( tr2i18n( "&Close" ) ); +} + +void OutgoingDialog_base::send() +{ + qWarning( "OutgoingDialog_base::send(): Not implemented yet" ); +} + +void OutgoingDialog_base::deleteItem() +{ + qWarning( "OutgoingDialog_base::deleteItem(): Not implemented yet" ); +} + +#include "outgoingdialog_base.moc" diff --git a/korganizer/outgoingdialog_base.h b/korganizer/outgoingdialog_base.h new file mode 100644 index 0000000..af71bb1 --- a/dev/null +++ b/korganizer/outgoingdialog_base.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** Form interface generated from reading ui file '/build/kde/cvs/korge/kdepim/korganizer/outgoingdialog_base.ui' +** +** Created: Sat Mar 29 22:24:26 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#ifndef OUTGOINGDIALOG_BASE_H +#define OUTGOINGDIALOG_BASE_H + +#include <qvariant.h> +#include <qdialog.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QListView; +class QListViewItem; +class QPushButton; + +class OutgoingDialog_base : public QDialog +{ + Q_OBJECT + +public: + OutgoingDialog_base( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~OutgoingDialog_base(); + + QListView* mMessageListView; + QPushButton* PushButton5; + QPushButton* PushButton7; + QPushButton* PushButton6; + +protected: + QGridLayout* OutgoingDialog_baseLayout; + +protected slots: + virtual void languageChange(); + + virtual void send(); + virtual void deleteItem(); + +}; + +#endif // OUTGOINGDIALOG_BASE_H diff --git a/korganizer/outgoingdialog_base.moc b/korganizer/outgoingdialog_base.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/outgoingdialog_base.moc diff --git a/korganizer/publishdialog.cpp b/korganizer/publishdialog.cpp new file mode 100644 index 0000000..176595a --- a/dev/null +++ b/korganizer/publishdialog.cpp @@ -0,0 +1,152 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlineedit.h> +#include <kdebug.h> + +#include <kglobal.h> +#include <klocale.h> +#ifndef KORG_NOKABC +#include <kabc/addresseedialog.h> +#endif + +#include "koprefs.h" +#include "publishdialog.h" + +PublishDialog::PublishDialog(QWidget* parent, const char* name, + bool modal, WFlags fl) + : PublishDialog_base(parent,name,modal,fl) +{ + setCaption(i18n("Select Addresses")); + mNameLineEdit->setEnabled(false); + mEmailLineEdit->setEnabled(false); + connect(mAddressListView,SIGNAL(selectionChanged(QListViewItem *)), + SLOT(updateInput())); +} + +PublishDialog::~PublishDialog() +{ +} + +void PublishDialog::addAttendee(Attendee *attendee) +{ + mNameLineEdit->setEnabled(true); + mEmailLineEdit->setEnabled(true); + QListViewItem *item = new QListViewItem(mAddressListView); + item->setText(0,attendee->name()); + item->setText(1,attendee->email()); + mAddressListView->insertItem(item); +} + +QString PublishDialog::addresses() +{ + QString to = ""; + QListViewItem *item; + int i, count; + count = mAddressListView->childCount(); + for (i=0;i<count;i++) { + item = mAddressListView->firstChild(); + mAddressListView->takeItem(item); + to += item->text(1); + if (i<count-1) { + to += ", "; + } + } + return to; +} + +void PublishDialog::addItem() +{ + mNameLineEdit->setEnabled(true); + mEmailLineEdit->setEnabled(true); + QListViewItem *item = new QListViewItem(mAddressListView); + mAddressListView->insertItem(item); + mAddressListView->setSelected(item,true); + mNameLineEdit->setText(i18n("(EmptyName)")); + mEmailLineEdit->setText(i18n("(EmptyEmail)")); +} + +void PublishDialog::removeItem() +{ + QListViewItem *item; + item = mAddressListView->selectedItem(); + if (!item) return; + mAddressListView->takeItem(item); + item = mAddressListView->selectedItem(); + if (!item) { + mNameLineEdit->setText(""); + mEmailLineEdit->setText(""); + mNameLineEdit->setEnabled(false); + mEmailLineEdit->setEnabled(false); + } + if (mAddressListView->childCount() == 0) { + mNameLineEdit->setEnabled(false); + mEmailLineEdit->setEnabled(false); + } +} + +void PublishDialog::openAddressbook() +{ +#ifndef KORG_NOKABC + KABC::Addressee::List addressList; + addressList = KABC::AddresseeDialog::getAddressees(this); + //KABC::Addressee a = KABC::AddresseeDialog::getAddressee(this); + KABC::Addressee a = addressList.first(); + if (!a.isEmpty()) { + uint i; + for (i=0;i<addressList.count();i++) { + a = addressList[i]; + mNameLineEdit->setEnabled(true); + mEmailLineEdit->setEnabled(true); + QListViewItem *item = new QListViewItem(mAddressListView); + mAddressListView->setSelected(item,true); + mNameLineEdit->setText(a.realName()); + mEmailLineEdit->setText(a.preferredEmail()); + mAddressListView->insertItem(item); + } + } +#endif +} + +void PublishDialog::updateItem() +{ + QListViewItem *item; + item = mAddressListView->selectedItem(); + if (!item) return; + item->setText(0,mNameLineEdit->text()); + item->setText(1,mEmailLineEdit->text()); +} + +void PublishDialog::updateInput() +{ + QListViewItem *item; + item = mAddressListView->selectedItem(); + if (!item) return; + mNameLineEdit->setEnabled(true); + mEmailLineEdit->setEnabled(true); + QString mail = item->text(1); + mNameLineEdit->setText(item->text(0)); + mEmailLineEdit->setText(mail); +} + +#include "publishdialog.moc" diff --git a/korganizer/publishdialog.h b/korganizer/publishdialog.h new file mode 100644 index 0000000..338603c --- a/dev/null +++ b/korganizer/publishdialog.h @@ -0,0 +1,55 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef PUBLISHDIALOG_H +#define PUBLISHDIALOG_H + +#include <qlistview.h> +#include <libkcal/attendee.h> + +#include "publishdialog_base.h" + +using namespace KCal; + +class PublishDialog : public PublishDialog_base +{ + Q_OBJECT + public: + PublishDialog(QWidget* parent=0,const char* name=0, + bool modal=true,WFlags fl=0); + ~PublishDialog(); + + void addAttendee(Attendee *attendee); + QString addresses(); + + signals: + void numMessagesChanged(int); + + protected slots: + void addItem(); + void removeItem(); + void openAddressbook(); + void updateItem(); + void updateInput(); +}; + +#endif // OUTGOINGDIALOG_H diff --git a/korganizer/publishdialog.moc b/korganizer/publishdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/publishdialog.moc diff --git a/korganizer/publishdialog_base.cpp b/korganizer/publishdialog_base.cpp new file mode 100644 index 0000000..75e4746 --- a/dev/null +++ b/korganizer/publishdialog_base.cpp @@ -0,0 +1,162 @@ +#include <klocale.h> +/**************************************************************************** +** Form implementation generated from reading ui file '/build/kde/cvs/korge/kdepim/korganizer/publishdialog_base.ui' +** +** Created: Sat Mar 29 22:31:35 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#include "publishdialog_base.h" + +#include <qvariant.h> +#include <qframe.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a PublishDialog_base as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +PublishDialog_base::PublishDialog_base( QWidget* parent, const char* name, bool modal, WFlags fl ) + : QDialog( parent, name, modal, fl ) + +{ + if ( !name ) + setName( "PublishDialog_base" ); + PublishDialog_baseLayout = new QGridLayout( this, 1, 1, 11, 6, "PublishDialog_baseLayout"); + + mAddressListView = new QListView( this, "mAddressListView" ); + mAddressListView->addColumn( tr2i18n( "Name" ) ); + mAddressListView->addColumn( tr2i18n( "Email" ) ); + + PublishDialog_baseLayout->addMultiCellWidget( mAddressListView, 0, 3, 0, 1 ); + + TextLabel1 = new QLabel( this, "TextLabel1" ); + + PublishDialog_baseLayout->addWidget( TextLabel1, 4, 0 ); + + TextLabel2 = new QLabel( this, "TextLabel2" ); + + PublishDialog_baseLayout->addWidget( TextLabel2, 5, 0 ); + + mEmailLineEdit = new QLineEdit( this, "mEmailLineEdit" ); + + PublishDialog_baseLayout->addWidget( mEmailLineEdit, 5, 1 ); + + mNameLineEdit = new QLineEdit( this, "mNameLineEdit" ); + + PublishDialog_baseLayout->addWidget( mNameLineEdit, 4, 1 ); + + PushButton10 = new QPushButton( this, "PushButton10" ); + + PublishDialog_baseLayout->addWidget( PushButton10, 0, 2 ); + + PushButton12 = new QPushButton( this, "PushButton12" ); + + PublishDialog_baseLayout->addWidget( PushButton12, 2, 2 ); + + PushButton11 = new QPushButton( this, "PushButton11" ); + + PublishDialog_baseLayout->addWidget( PushButton11, 1, 2 ); + QSpacerItem* spacer = new QSpacerItem( 20, 241, QSizePolicy::Minimum, QSizePolicy::Expanding ); + PublishDialog_baseLayout->addMultiCell( spacer, 3, 5, 2, 2 ); + + Line2 = new QFrame( this, "Line2" ); + Line2->setFrameShape( QFrame::HLine ); + Line2->setFrameShadow( QFrame::Sunken ); + Line2->setFrameShape( QFrame::HLine ); + + PublishDialog_baseLayout->addMultiCellWidget( Line2, 6, 6, 0, 2 ); + + layout95 = new QHBoxLayout( 0, 0, 6, "layout95"); + QSpacerItem* spacer_2 = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + layout95->addItem( spacer_2 ); + + PushButton9 = new QPushButton( this, "PushButton9" ); + PushButton9->setDefault( TRUE ); + layout95->addWidget( PushButton9 ); + + PushButton8 = new QPushButton( this, "PushButton8" ); + layout95->addWidget( PushButton8 ); + + PublishDialog_baseLayout->addMultiCellLayout( layout95, 7, 7, 0, 2 ); + languageChange(); + resize( QSize(420, 379).expandedTo(minimumSizeHint()) ); + + // signals and slots connections + connect( PushButton10, SIGNAL( clicked() ), this, SLOT( addItem() ) ); + connect( PushButton11, SIGNAL( clicked() ), this, SLOT( removeItem() ) ); + connect( PushButton12, SIGNAL( clicked() ), this, SLOT( openAddressbook() ) ); + connect( PushButton9, SIGNAL( clicked() ), this, SLOT( accept() ) ); + connect( mNameLineEdit, SIGNAL( textChanged(const QString&) ), this, SLOT( updateItem() ) ); + connect( mEmailLineEdit, SIGNAL( textChanged(const QString&) ), this, SLOT( updateItem() ) ); + connect( PushButton8, SIGNAL( clicked() ), this, SLOT( reject() ) ); + + // tab order + setTabOrder( mAddressListView, mNameLineEdit ); + setTabOrder( mNameLineEdit, mEmailLineEdit ); + setTabOrder( mEmailLineEdit, PushButton10 ); + setTabOrder( PushButton10, PushButton11 ); + setTabOrder( PushButton11, PushButton12 ); + setTabOrder( PushButton12, PushButton9 ); + setTabOrder( PushButton9, PushButton8 ); +} + +/* + * Destroys the object and frees any allocated resources + */ +PublishDialog_base::~PublishDialog_base() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void PublishDialog_base::languageChange() +{ + setCaption( tr2i18n( "Form1" ) ); + mAddressListView->header()->setLabel( 0, tr2i18n( "Name" ) ); + mAddressListView->header()->setLabel( 1, tr2i18n( "Email" ) ); + TextLabel1->setText( tr2i18n( "Name:" ) ); + TextLabel2->setText( tr2i18n( "Email:" ) ); + PushButton10->setText( tr2i18n( "&New" ) ); + PushButton12->setText( tr2i18n( "&Addressbook" ) ); + PushButton11->setText( tr2i18n( "&Remove" ) ); + PushButton9->setText( tr2i18n( "&OK" ) ); + PushButton8->setText( tr2i18n( "&Cancel" ) ); +} + +void PublishDialog_base::addItem() +{ + qWarning( "PublishDialog_base::addItem(): Not implemented yet" ); +} + +void PublishDialog_base::removeItem() +{ + qWarning( "PublishDialog_base::removeItem(): Not implemented yet" ); +} + +void PublishDialog_base::openAddressbook() +{ + qWarning( "PublishDialog_base::openAddressbook(): Not implemented yet" ); +} + +void PublishDialog_base::updateItem() +{ + qWarning( "PublishDialog_base::updateItem(): Not implemented yet" ); +} + +#include "publishdialog_base.moc" diff --git a/korganizer/publishdialog_base.h b/korganizer/publishdialog_base.h new file mode 100644 index 0000000..932474e --- a/dev/null +++ b/korganizer/publishdialog_base.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** Form interface generated from reading ui file '/build/kde/cvs/korge/kdepim/korganizer/publishdialog_base.ui' +** +** Created: Sat Mar 29 22:24:27 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#ifndef PUBLISHDIALOG_BASE_H +#define PUBLISHDIALOG_BASE_H + +#include <qvariant.h> +#include <qdialog.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QFrame; +class QLabel; +class QLineEdit; +class QListView; +class QListViewItem; +class QPushButton; + +class PublishDialog_base : public QDialog +{ + Q_OBJECT + +public: + PublishDialog_base( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~PublishDialog_base(); + + QListView* mAddressListView; + QLabel* TextLabel1; + QLabel* TextLabel2; + QLineEdit* mEmailLineEdit; + QLineEdit* mNameLineEdit; + QPushButton* PushButton10; + QPushButton* PushButton12; + QPushButton* PushButton11; + QFrame* Line2; + QPushButton* PushButton9; + QPushButton* PushButton8; + +protected: + QGridLayout* PublishDialog_baseLayout; + QHBoxLayout* layout95; + +protected slots: + virtual void languageChange(); + + virtual void addItem(); + virtual void removeItem(); + virtual void openAddressbook(); + virtual void updateItem(); + +}; + +#endif // PUBLISHDIALOG_BASE_H diff --git a/korganizer/publishdialog_base.moc b/korganizer/publishdialog_base.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/publishdialog_base.moc diff --git a/korganizer/resourceview.h b/korganizer/resourceview.h new file mode 100644 index 0000000..0cac495 --- a/dev/null +++ b/korganizer/resourceview.h @@ -0,0 +1,8 @@ +#ifndef MICRO_KORG_RESOURCEVIEW_H +#define MICRO_KORG_RESOURCEVIEW_H + +class ResourceView +{ +}; + +#endif diff --git a/korganizer/savetemplatedialog.cpp b/korganizer/savetemplatedialog.cpp new file mode 100644 index 0000000..0da524f --- a/dev/null +++ b/korganizer/savetemplatedialog.cpp @@ -0,0 +1,76 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> + +#include <keditlistbox.h> +#include <klocale.h> + +#include "koprefs.h" + +#include "savetemplatedialog.h" +#include "savetemplatedialog.moc" + +SaveTemplateDialog::SaveTemplateDialog( IncidenceType type, QWidget *parent ) + : KDialogBase( Plain, i18n("Save Template"), Ok | Cancel, Ok, parent, 0, + true, false ), + mType( type ) +{ + QFrame *topFrame = plainPage(); + QVBoxLayout *topLayout = new QVBoxLayout( topFrame, 0, spacingHint() ); + + mEditListBox = new KEditListBox( i18n("Select Template Name"), topFrame, + 0, false, KEditListBox::Add | + KEditListBox::Remove ); + topLayout->addWidget( mEditListBox ); + connect( mEditListBox, SIGNAL( changed() ), SLOT( slotChanged() ) ); + + QStringList templates; + + if ( mType == EventType ) { + templates = KOPrefs::instance()->mEventTemplates; + } else if( mType == TodoType ) { + templates = KOPrefs::instance()->mTodoTemplates; + } + + mEditListBox->insertStringList( templates ); +} + +SaveTemplateDialog::~SaveTemplateDialog() +{ +} + +void SaveTemplateDialog::slotOk() +{ + emit templateSelected( mEditListBox->currentText() ); + accept(); +} + +void SaveTemplateDialog::slotChanged() +{ + if ( mType == EventType ) { + KOPrefs::instance()->mEventTemplates = mEditListBox->items(); + } else if( mType == TodoType ) { + KOPrefs::instance()->mTodoTemplates = mEditListBox->items(); + } +} diff --git a/korganizer/savetemplatedialog.h b/korganizer/savetemplatedialog.h new file mode 100644 index 0000000..7e54bee --- a/dev/null +++ b/korganizer/savetemplatedialog.h @@ -0,0 +1,53 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef SAVETEMPLATEDIALOG_H +#define SAVETEMPLATEDIALOG_H + +#include <kdialogbase.h> + +class KEditListBox; + +class SaveTemplateDialog : public KDialogBase +{ + Q_OBJECT + public: + enum IncidenceType { EventType, TodoType }; + + SaveTemplateDialog( IncidenceType type, QWidget *parent = 0 ); + virtual ~SaveTemplateDialog(); + + signals: + void templateSelected( const QString & ); + + protected slots: + void slotOk(); + + void slotChanged(); + + private: + IncidenceType mType; + + KEditListBox *mEditListBox; +}; + +#endif diff --git a/korganizer/savetemplatedialog.moc b/korganizer/savetemplatedialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/savetemplatedialog.moc diff --git a/korganizer/searchdialog.cpp b/korganizer/searchdialog.cpp new file mode 100644 index 0000000..74d48b9 --- a/dev/null +++ b/korganizer/searchdialog.cpp @@ -0,0 +1,396 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1998 Preston Brown + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlayout.h> +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qpushbutton.h> + +#include <klocale.h> +#include <kmessagebox.h> + +#include <libkdepim/kdateedit.h> + +#include "koglobals.h" +#include "koprefs.h" + +#include "calendarview.h" +#include "koviewmanager.h" +#include "searchdialog.h" +#include "searchdialog.moc" + +SearchDialog::SearchDialog(Calendar *calendar,CalendarView *parent) + : KDialogBase(Plain,i18n("KO/Pi Find "),User1|Close,User1,parent,0,false,false, + i18n("&Find")) +{ + mCalendar = calendar; + QFrame *topFrame = plainPage(); + QVBoxLayout *layout = new QVBoxLayout(topFrame,0,spacingHint()); + + // Search expression + QHBoxLayout *subLayout = new QHBoxLayout(); + layout->addLayout(subLayout); + + searchLabel = new QLabel(topFrame); + searchLabel->setText(i18n("Search for:")); + subLayout->addWidget(searchLabel); + + searchEdit = new QLineEdit(topFrame); + subLayout->addWidget(searchEdit); + searchEdit->setText("*"); // Find all events by default + searchEdit->setFocus(); + connect(searchEdit, SIGNAL(textChanged ( const QString & )),this,SLOT(searchTextChanged( const QString & ))); + connect(searchEdit, SIGNAL( returnPressed () ),this,SLOT(doSearch())); + // Subjects to search + // QGroupBox *subjectGroup = new QGroupBox(1,Vertical,i18n("Search In"), + // topFrame); + + + + QHBox *incidenceGroup = new QHBox( topFrame ); + layout->addWidget(incidenceGroup); + + mSearchEvent = new QCheckBox(i18n("Events"),incidenceGroup); + mSearchEvent->setChecked(true); + mSearchTodo = new QCheckBox(i18n("Todos"),incidenceGroup); + mSearchJournal = new QCheckBox(i18n("Journals"),incidenceGroup); + + QHBox *subjectGroup = new QHBox( topFrame ); + layout->addWidget(subjectGroup); + + mSummaryCheck = new QCheckBox(i18n("Summaries"),subjectGroup); + mSummaryCheck->setChecked(true); + mDescriptionCheck = new QCheckBox(i18n("Descriptions"),subjectGroup); + mCategoryCheck = new QCheckBox(i18n("Categories"),subjectGroup); + + QHBox *attendeeGroup = new QHBox( topFrame ); + layout->addWidget(attendeeGroup ); + new QLabel( i18n("Attendee:"),attendeeGroup ); + mSearchAName = new QCheckBox(i18n("Name"),attendeeGroup ); + mSearchAEmail = new QCheckBox(i18n("Email"), attendeeGroup ); + // Date range + // QGroupBox *rangeGroup = new QGroupBox(1,Horizontal,i18n("Date Range"), + // topFrame); + // layout->addWidget(rangeGroup); + + QWidget *rangeWidget = new QWidget(topFrame); + QHBoxLayout *rangeLayout = new QHBoxLayout(rangeWidget,0,spacingHint()); + + rangeLayout->addWidget(new QLabel(i18n("From:"),rangeWidget)); + mStartDate = new KDateEdit(rangeWidget); + rangeLayout->addWidget(mStartDate); + rangeLayout->addWidget(new QLabel(i18n("To:"),rangeWidget)); + mEndDate = new KDateEdit(rangeWidget); + mEndDate->setDate(QDate::currentDate().addDays(365)); + rangeLayout->addWidget(mEndDate); + + // mInclusiveCheck = new QCheckBox(i18n("Events have to be completely included"), topFrame); + //mInclusiveCheck->setChecked(false); + layout->addWidget(rangeWidget); + //layout->addWidget(mInclusiveCheck); + // Subjects to search + + + // Results list view + listView = new KOListView(mCalendar,topFrame); + //listView->showDates(); + + + layout->addWidget(listView); + + // if ( KOPrefs::instance()->mCompactDialogs ) { + // KOGlobals::fitDialogToScreen( this, true ); + // } + + listView->readSettings(KOGlobals::config(),"SearchListView Layout"); + connect(this,SIGNAL(user1Clicked()),SLOT(doSearch())); + QPushButton *CloseButton = findButton( Close ); + //connect(CloseButton,SIGNAL(clicked()),listView, SLOT(clear())); + +#ifndef DESKTOP_VERSION + setCaption(i18n("Click OK to search ->")); + hideButtons(); +#endif +} + +SearchDialog::~SearchDialog() +{ + +} +void SearchDialog::accept() +{ + doSearch(); +} +void SearchDialog::updateList() +{ + //listView->updateList(); + if ( isVisible() ) { + updateView(); + //qDebug("SearchDialog::updated "); + } + else { + listView->clear(); + //qDebug("SearchDialog::cleared "); + + } +} +void SearchDialog::searchTextChanged( const QString &_text ) +{ + enableButton( KDialogBase::User1, !_text.isEmpty() ); +} + +void SearchDialog::doSearch() +{ + QRegExp re; + + re.setWildcard(true); // most people understand these better. + re.setCaseSensitive(false); + re.setPattern(searchEdit->text()); + if (!re.isValid() ) { + KMessageBox::sorry(this, + i18n("Invalid search expression,\ncannot perform " + "the search.\nPlease enter a search expression\n" + "using the wildcard characters\n '*' and '?'" + "where needed.")); + return; + } + + search(re); + + listView->setStartDate( mStartDate->date() ); + listView->showEvents(mMatchedEvents); + listView->addTodos(mMatchedTodos); + listView->addJournals(mMatchedJournals); + + if (mMatchedEvents.count() + mMatchedJournals.count() + mMatchedTodos.count() == 0) { + KMessageBox::information(this, + i18n("No event/todo were found matching\nyour search expression.\nUse the wildcard characters\n ' * ' and ' ? ' where needed.")); +#ifndef DESKTOP_VERSION + setCaption(i18n("Click OK to search ->")); +#else + setCaption(i18n("KO/Pi Find ")); +#endif + } else { + QString mess; + mess = mess.sprintf( i18n("%d item(s) found."), mMatchedEvents.count()+ mMatchedJournals.count() + mMatchedTodos.count() ); + setCaption( i18n("KO/Pi Find: ") + mess); + + } +} +void SearchDialog::updateConfig() +{ + listView->updateConfig(); +} +void SearchDialog::updateView() +{ + + QRegExp re; + re.setWildcard(true); // most people understand these better. + re.setCaseSensitive(false); + re.setPattern(searchEdit->text()); + if (re.isValid()) { + search(re); + } else { + mMatchedEvents.clear(); + mMatchedTodos.clear(); + mMatchedJournals.clear(); + } + listView->setStartDate( mStartDate->date() ); + listView->showEvents(mMatchedEvents); + listView->addTodos(mMatchedTodos); + listView->addJournals(mMatchedJournals); +} + +void SearchDialog::search(const QRegExp &re) +{ + QPtrList<Event> events = mCalendar->events( mStartDate->date(), + mEndDate->date(), + false /*mInclusiveCheck->isChecked()*/ ); + + mMatchedEvents.clear(); + if ( mSearchEvent->isChecked() ) { + Event *ev; + for(ev=events.first();ev;ev=events.next()) { + if (mSummaryCheck->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(ev->summary()) != -1) +#else + if (re.match(ev->summary()) != -1) +#endif + { + mMatchedEvents.append(ev); + continue; + } + } + if (mDescriptionCheck->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(ev->description()) != -1) +#else + if (re.match(ev->description()) != -1) +#endif + { + mMatchedEvents.append(ev); + continue; + } + } + if (mCategoryCheck->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(ev->categoriesStr()) != -1) +#else + if (re.match(ev->categoriesStr()) != -1) +#endif + { + mMatchedEvents.append(ev); + continue; + } + } + if ( mSearchAName->isChecked() || mSearchAEmail->isChecked() ) { + QPtrList<Attendee> tmpAList = ev->attendees(); + Attendee *a; + for (a = tmpAList.first(); a; a = tmpAList.next()) { + if (mSearchAName->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(a->name()) != -1) +#else + if (re.match(a->name()) != -1) +#endif + { + mMatchedEvents.append(ev); + break; + } + } + if (mSearchAEmail->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(a->email()) != -1) +#else + if (re.match(a->email()) != -1) +#endif + { + mMatchedEvents.append(ev); + break; + } + } + } + } + } + } + QPtrList<Todo> todos = mCalendar->todos( ); + mMatchedTodos.clear(); + if ( mSearchTodo->isChecked() ) { + Todo *tod; + for(tod=todos.first();tod;tod=todos.next()) { + if (mSummaryCheck->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(tod->summary()) != -1) +#else + if (re.match(tod->summary()) != -1) +#endif + { + mMatchedTodos.append(tod); + continue; + } + } + if (mDescriptionCheck->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(tod->description()) != -1) +#else + if (re.match(tod->description()) != -1) +#endif + { + mMatchedTodos.append(tod); + continue; + } + } + if (mCategoryCheck->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(tod->categoriesStr()) != -1) +#else + if (re.match(tod->categoriesStr()) != -1) +#endif + { + mMatchedTodos.append(tod); + continue; + } + } + if ( mSearchAName->isChecked() || mSearchAEmail->isChecked() ) { + QPtrList<Attendee> tmpAList = tod->attendees(); + Attendee *a; + for (a = tmpAList.first(); a; a = tmpAList.next()) { + if (mSearchAName->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(a->name()) != -1) +#else + if (re.match(a->name()) != -1) +#endif + { + mMatchedTodos.append(tod); + break; + } + } + if (mSearchAEmail->isChecked()) { +#if QT_VERSION >= 300 + if (re.search(a->email()) != -1) +#else + if (re.match(a->email()) != -1) +#endif + { + mMatchedTodos.append(tod); + break; + } + } + } + } + } + } + mMatchedJournals.clear(); + if (mSearchJournal->isChecked() ) { + QPtrList<Journal> journals = mCalendar->journals( ); + Journal* journ; + + for(journ=journals.first();journ;journ=journals.next()) { + if ( journ->dtStart().date() <= mEndDate->date() + &&journ->dtStart().date() >= mStartDate->date()) { +#if QT_VERSION >= 300 + if (re.search(journ->description()) != -1) +#else + if (re.match(journ->description()) != -1) +#endif + { + mMatchedJournals.append(journ); + continue; + } + } + } + } + +} +void SearchDialog::keyPressEvent ( QKeyEvent *e) +{ + + e->ignore(); + +} +//mMatchedJournals; diff --git a/korganizer/searchdialog.h b/korganizer/searchdialog.h new file mode 100644 index 0000000..a03c586 --- a/dev/null +++ b/korganizer/searchdialog.h @@ -0,0 +1,93 @@ +/* + This file is part of KOrganizer. + Copyright (c) 1998 Preston Brown + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef SEARCHDIALOG_H +#define SEARCHDIALOG_H + +#include <qregexp.h> + +#include <kdialogbase.h> + +#include <libkcal/calendar.h> + +#include "kolistview.h" + +class KDateEdit; +class QCheckBox; +class QLineEdit; +class QLabel; +class CalendarView; + +using namespace KCal; + +class SearchDialog : public KDialogBase +{ + Q_OBJECT + public: + SearchDialog(Calendar *calendar,CalendarView *parent=0); + virtual ~SearchDialog(); + KOListView *listview(){ return listView;} + void updateView(); + + public slots: + void changeEventDisplay(Event *, int) { updateView(); } + void updateConfig(); + void updateList(); + protected slots: + void accept(); + void doSearch(); + void searchTextChanged( const QString &_text ); + + signals: + void showEventSignal(Event *); + void editEventSignal(Event *); + void deleteEventSignal(Event *); + + private: + void search(const QRegExp &); + + Calendar *mCalendar; + + QPtrList<Event> mMatchedEvents; + QPtrList<Todo> mMatchedTodos; + QPtrList<Journal> mMatchedJournals; + + QLabel *searchLabel; + QLineEdit *searchEdit; + KOListView *listView; + + KDateEdit *mStartDate; + KDateEdit *mEndDate; + // QCheckBox *mInclusiveCheck; + QCheckBox *mSummaryCheck; + QCheckBox *mDescriptionCheck; + QCheckBox *mCategoryCheck; + QCheckBox *mSearchEvent; + QCheckBox *mSearchTodo; + QCheckBox *mSearchJournal; + QCheckBox *mSearchAName; + QCheckBox *mSearchAEmail; + void keyPressEvent ( QKeyEvent *e) ; +}; + +#endif diff --git a/korganizer/searchdialog.moc b/korganizer/searchdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/searchdialog.moc diff --git a/korganizer/simplealarmclient.cpp b/korganizer/simplealarmclient.cpp new file mode 100644 index 0000000..4882a27 --- a/dev/null +++ b/korganizer/simplealarmclient.cpp @@ -0,0 +1,111 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002,2003 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "simplealarmclient.h" + +#include <kprocess.h> +#include <kdebug.h> +#include <kstandarddirs.h> + +#include <qfile.h> +#include <qtextstream.h> + +SimpleAlarmClient::SimpleAlarmClient() + : mProcess( 0 ) +{ + //mCalendarsFile = locateLocal( "data", "simplealarmdaemon/calendars" ); + + +} + +SimpleAlarmClient::~SimpleAlarmClient() +{ + delete mProcess; +} + +void SimpleAlarmClient::startDaemon() +{ + + qDebug("SimpleAlarmClient::startDaemon() "); + if ( !mProcess ) { + mProcess = new KProcess; + *mProcess << "simplealarmdaemon"; + if ( !mProcess->start() ) { + kdDebug() << "Failed to start process." << endl; + } + } +} + +bool SimpleAlarmClient::setCalendars( const QStringList &calendars ) +{ + + + QFile f( mCalendarsFile ); + if ( !f.open( IO_WriteOnly ) ) { + kdDebug() << "Unable to open file '" << mCalendarsFile << "'" << endl; + return false; + } + QTextStream ts( &f ); + QStringList::ConstIterator it; + for ( it = calendars.begin(); it != calendars.end(); ++it ) { + kdDebug() << "CAL: " << *it << endl; + ts << *it << "\n"; + } + f.close(); + + return true; +} + +bool SimpleAlarmClient::addCalendar( const QString &calendar ) +{ + QFile f( mCalendarsFile ); + if ( !f.open( IO_WriteOnly | IO_Append ) ) return false; + QTextStream ts( &f ); + ts << calendar << "\n"; + f.close(); + + return true; +} + +bool SimpleAlarmClient::removeCalendar( const QString &calendar ) +{ + QStringList calendars; + + QFile f( mCalendarsFile ); + if ( !f.open( IO_ReadOnly ) ) return false; + QTextStream ts( &f ); + bool found = false; + QString line; + while ( !( line = ts.readLine() ).isNull() ) { + if ( line != calendar ) calendars.append( line ); + else found = true; + } + + if ( found ) return setCalendars( calendars ); + else return true; +} + +bool SimpleAlarmClient::reloadCalendar( const QString & ) +{ + return true; +} diff --git a/korganizer/simplealarmclient.h b/korganizer/simplealarmclient.h new file mode 100644 index 0000000..6ad8d52 --- a/dev/null +++ b/korganizer/simplealarmclient.h @@ -0,0 +1,57 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef SIMPLEALARMCLIENT_H +#define SIMPLEALARMCLIENT_H + +#include "alarmclient.h" + +class KProcess; + +/** + This class implements the client interface for the SimpleAlarmDaemon. +*/ +class SimpleAlarmClient : public AlarmClient +{ + public: + SimpleAlarmClient(); + virtual ~SimpleAlarmClient(); + + /** + Start alarm daemon. + */ + void startDaemon(); + + bool setCalendars( const QStringList & ); + + bool addCalendar( const QString & ); + + bool removeCalendar( const QString & ); + + bool reloadCalendar( const QString & ); + + private: + QString mCalendarsFile; + KProcess *mProcess; +}; + +#endif diff --git a/korganizer/statusdialog.cpp b/korganizer/statusdialog.cpp new file mode 100644 index 0000000..78efeb0 --- a/dev/null +++ b/korganizer/statusdialog.cpp @@ -0,0 +1,67 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <qlabel.h> +#include <qpushbutton.h> +#include <qstringlist.h> +#include <qlayout.h> + +#include <kdebug.h> +#include <klocale.h> + +#include "statusdialog.h" +#include "statusdialog.moc" + +StatusDialog::StatusDialog(QWidget* parent, const char* name) : + KDialog(parent,name,true) +{ + setCaption(i18n("Set Your Status")); + + QBoxLayout *topLayout = new QVBoxLayout( this ); + topLayout->setSpacing( spacingHint() ); + topLayout->setMargin( marginHint() ); + + QBoxLayout *statusLayout = new QHBoxLayout( topLayout ); + + QLabel *text = new QLabel(i18n("Set your status"),this); + statusLayout->addWidget( text ); + + mStatus = new QComboBox(false,this); + mStatus->insertStringList(Attendee::statusList()); + statusLayout->addWidget( mStatus ); + + QBoxLayout *buttonLayout = new QHBoxLayout( topLayout ); + + QPushButton *ok = new QPushButton(i18n("&OK"), this); + connect ( ok,SIGNAL(clicked()), this,SLOT(accept()) ); + buttonLayout->addWidget( ok ); + + QPushButton *cancel = new QPushButton(i18n("&Cancel"), this); + connect ( cancel,SIGNAL(clicked()), this,SLOT(reject()) ); + buttonLayout->addWidget( cancel ); +} + +StatusDialog::~StatusDialog() +{ +} + +Attendee::PartStat StatusDialog::status() +{ + return Attendee::PartStat( mStatus->currentItem() ) ; +} diff --git a/korganizer/statusdialog.h b/korganizer/statusdialog.h new file mode 100644 index 0000000..be6b5e8 --- a/dev/null +++ b/korganizer/statusdialog.h @@ -0,0 +1,43 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef STATUSDIALOG_H +#define STATUSDIALOG_H + +#include <qcombobox.h> + +#include <kdialog.h> + +#include <libkcal/attendee.h> + +using namespace KCal; + +class StatusDialog : public KDialog +{ + Q_OBJECT + public: + StatusDialog(QWidget* parent=0,const char* name=0); + ~StatusDialog(); + + Attendee::PartStat status(); + + private: + QComboBox *mStatus; +}; + +#endif diff --git a/korganizer/statusdialog.moc b/korganizer/statusdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/statusdialog.moc diff --git a/korganizer/timeline.cpp b/korganizer/timeline.cpp new file mode 100644 index 0000000..6f9c8dd --- a/dev/null +++ b/korganizer/timeline.cpp @@ -0,0 +1,63 @@ +#include <qpainter.h> + +#include <kdebug.h> + +#include "timeline.h" +#include "timeline.moc" + +TimeLine::TimeLine( QWidget *parent, const char *name ) : + QScrollView( parent, name ) +{ + mPixelWidth = 1000; + + resizeContents( mPixelWidth, 20 ); + + viewport()->setBackgroundMode( PaletteBackground ); + + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); +} + +TimeLine::~TimeLine() +{ +} + +void TimeLine::drawContents(QPainter* p, int cx, int cy, int cw, int ch) +{ + int spacingX = mDaySpacing; + int offsetX = mDayOffset; + + // Draw vertical lines of grid +// kdDebug() << "drawContents cx: " << cx << " cy: " << cy << " cw: " << cw << " ch: " << ch << endl; + int cell = int( (cx - ( spacingX - offsetX ) ) / spacingX ); + int x = cell * spacingX + ( spacingX - offsetX ); +// kdDebug() << " x: " << x << endl; + while (x < cx + cw) { +// kdDebug() << " x: " << x << endl; + p->drawLine(x,cy,x,cy+ch); + p->drawText( x + 5, 15, QString::number( mStartDate.addDays( cell + 1 ).date().day() ) ); + + x += spacingX; + cell++; + } +} + +void TimeLine::setDateRange( const QDateTime &start, const QDateTime &end ) +{ + mStartDate = start; + mEndDate = end; + + mSecsPerPixel = mStartDate.secsTo( mEndDate ) / mPixelWidth; + + mDaySpacing = 60 * 60 * 24 / mSecsPerPixel; + + mDayOffset = QDateTime( mStartDate.date() ).secsTo( mStartDate ) / mSecsPerPixel; + + kdDebug() << "TimeLines::setDateRange(): mDaySpacing: " << mDaySpacing << " mDayOffset: " + << mDayOffset << " mSecsPerPixel: " << mSecsPerPixel << endl; +} + +void TimeLine::setContentsPos( int pos ) +{ + QScrollView::setContentsPos ( pos, 0 ); +} diff --git a/korganizer/timeline.h b/korganizer/timeline.h new file mode 100644 index 0000000..ab3e5d3 --- a/dev/null +++ b/korganizer/timeline.h @@ -0,0 +1,33 @@ +#ifndef TIMELINE_H +#define TIMELINE_H + +#include <qscrollview.h> +#include <qdatetime.h> + +class TimeLine : public QScrollView +{ + Q_OBJECT + public: + TimeLine( QWidget *parent = 0, const char *name = 0 ); + virtual ~TimeLine(); + + void setDateRange( const QDateTime &start, const QDateTime &end ); + + public slots: + void setContentsPos( int pos ); + + protected: + void drawContents(QPainter* p, int cx, int cy, int cw, int ch); + + private: + QDateTime mStartDate; + QDateTime mEndDate; + + int mPixelWidth; + int mDaySpacing; + int mDayOffset; + int mSecsPerPixel; +}; + +#endif + diff --git a/korganizer/timeline.moc b/korganizer/timeline.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/timeline.moc diff --git a/korganizer/timespanview.cpp b/korganizer/timespanview.cpp new file mode 100644 index 0000000..f8314e7 --- a/dev/null +++ b/korganizer/timespanview.cpp @@ -0,0 +1,158 @@ + +#ifndef DESKTOP_VERSION +#include <qksplitter.h> +#else +#include <qsplitter.h> +#endif +#include <qlistview.h> +#include <qlayout.h> +#include <qheader.h> +#include <qpushbutton.h> + +#include <klocale.h> +#include <kdebug.h> + +#include "lineview.h" +#include "timeline.h" + +#include "timespanview.h" +#include "timespanview.moc" + + +TimeSpanView::TimeSpanView( QWidget *parent, const char *name ) : + QWidget( parent, name ) +{ + QBoxLayout *topLayout = new QVBoxLayout( this ); +#ifndef DESKTOP_VERSION + mSplitter = new QKSplitter( this ); +#else + mSplitter = new QSplitter( this ); +#endif + topLayout->addWidget( mSplitter ); + + mList = new QListView( mSplitter ); + mList->addColumn( i18n("Summary") ); + + QWidget *rightPane = new QWidget( mSplitter ); + QBoxLayout *rightPaneLayout = new QVBoxLayout( rightPane ); + + mTimeLine = new TimeLine( rightPane ); + mTimeLine->setFixedHeight( mList->header()->height() ); + rightPaneLayout->addWidget( mTimeLine ); + + mLineView = new LineView( rightPane ); + rightPaneLayout->addWidget( mLineView ); + + QBoxLayout *buttonLayout = new QHBoxLayout( rightPaneLayout ); + + QPushButton *zoomInButton = new QPushButton( i18n("Zoom In"), rightPane ); + connect( zoomInButton, SIGNAL( clicked() ), SLOT( zoomIn() ) ); + buttonLayout->addWidget( zoomInButton ); + + QPushButton *zoomOutButton = new QPushButton( i18n("Zoom Out"), rightPane ); + connect( zoomOutButton, SIGNAL( clicked() ), SLOT( zoomOut() ) ); + buttonLayout->addWidget( zoomOutButton ); + + QPushButton *centerButton = new QPushButton( i18n("Center View"), rightPane ); + connect( centerButton, SIGNAL( clicked() ), SLOT( centerView() ) ); + buttonLayout->addWidget( centerButton ); + + connect(mLineView->horizontalScrollBar(),SIGNAL(valueChanged(int)), + mTimeLine,SLOT(setContentsPos(int))); +} + +TimeSpanView::~TimeSpanView() +{ +} + +QValueList<int> TimeSpanView::splitterSizes() +{ + return mSplitter->sizes(); +} + +void TimeSpanView::setSplitterSizes( QValueList<int> sizes ) +{ + mSplitter->setSizes( sizes ); +} + +void TimeSpanView::addItem( KCal::Event *event ) +{ + new QListViewItem( mList, event->summary() ); + + QDateTime startDt = event->dtStart(); + QDateTime endDt = event->dtEnd(); + +// kdDebug() << "TimeSpanView::addItem(): start: " << startDt.toString() +// << " end: " << endDt.toString() << endl; + + int startSecs = mStartDate.secsTo( startDt ); + int durationSecs = startDt.secsTo( endDt ); + +// kdDebug() << "--- startSecs: " << startSecs << " dur: " << durationSecs << endl; + + int startX = mStartDate.secsTo( startDt ) / mSecsPerPixel; + int endX = startX + startDt.secsTo( endDt ) / mSecsPerPixel; + +// kdDebug() << "TimeSpanView::addItem(): s: " << startX << " e: " << endX << endl; + + mLineView->addLine( startX, endX ); +} + +void TimeSpanView::clear() +{ + mList->clear(); + mLineView->clear(); +} + +void TimeSpanView::updateView() +{ +#if QT_VERSION >= 300 + mLineView->updateContents(); + mTimeLine->updateContents(); +#else +#endif +} + +void TimeSpanView::setDateRange( const QDateTime &start, const QDateTime &end ) +{ + mStartDate = start; + mEndDate = end; + + mTimeLine->setDateRange( start, end ); + + mSecsPerPixel = mStartDate.secsTo( mEndDate ) / mLineView->pixelWidth(); +} + +QDateTime TimeSpanView::startDateTime() +{ + return mStartDate; +} + +QDateTime TimeSpanView::endDateTime() +{ + return mEndDate; +} + +void TimeSpanView::zoomIn() +{ + int span = mStartDate.daysTo( mEndDate ); + setDateRange( mStartDate.addDays( span / 4 ), mEndDate.addDays( span / -4 ) ); + + emit dateRangeChanged(); +} + +void TimeSpanView::zoomOut() +{ + int span = mStartDate.daysTo( mEndDate ); + setDateRange( mStartDate.addDays( span / -4 ), mEndDate.addDays( span / 4 ) ); + + emit dateRangeChanged(); +} + +void TimeSpanView::centerView() +{ + QScrollBar *scrollBar = mLineView->horizontalScrollBar(); + int min = scrollBar->minValue(); + int max = scrollBar->maxValue(); + scrollBar->setValue( min + (max-min) / 2 ); +} diff --git a/korganizer/timespanview.h b/korganizer/timespanview.h new file mode 100644 index 0000000..34cb1f7 --- a/dev/null +++ b/korganizer/timespanview.h @@ -0,0 +1,60 @@ +#ifndef TIMESPANVIEW_H +#define TIMESPANVIEW_H + +#include <qwidget.h> + +#include <libkcal/event.h> + +//class QSplitter; +#ifndef DESKTOP_VERSION +class QKSplitter; +#else +class QSplitter; +#define QKSplitter QSplitter +#endif +class QListView; +class LineView; +class TimeLine; + + +class TimeSpanView : public QWidget +{ + Q_OBJECT + public: + TimeSpanView( QWidget *parent=0, const char *name=0 ); + virtual ~TimeSpanView(); + + void addItem( KCal::Event * ); + + QValueList<int> splitterSizes(); + void setSplitterSizes( QValueList<int> ); + + void clear(); + + void setDateRange( const QDateTime &start, const QDateTime &end ); + + QDateTime startDateTime(); + QDateTime endDateTime(); + + public slots: + void updateView(); + + void zoomIn(); + void zoomOut(); + void centerView(); + + signals: + void dateRangeChanged(); + + private: + QKSplitter *mSplitter; + QListView *mList; + TimeLine *mTimeLine; + LineView *mLineView; + + QDateTime mStartDate; + QDateTime mEndDate; + int mSecsPerPixel; +}; + +#endif diff --git a/korganizer/timespanview.moc b/korganizer/timespanview.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/korganizer/timespanview.moc diff --git a/korganizer/version.h b/korganizer/version.h new file mode 100644 index 0000000..2f47c90 --- a/dev/null +++ b/korganizer/version.h @@ -0,0 +1,29 @@ +#ifndef KORG_VERSION_H +#define KORG_VERSION_H + +/* + Version scheme: "x.y.z build". + + "x.y.z" follow the kdelibs version KOrganizer is released with. + + If "z" is 0, it the version is "x.y" + + "build" is empty for final versions. For developer version "build" is + something like "alpha1", "alpha2", "beta1", "beta2", "rc1", "rc2". + + Examples in chronological order: + + 3.0 + 3.0.1 + 3.1 alpha1 + 3.1 beta1 + 3.1 beta2 + 3.1 rc1 + 3.1 + 3.1.1 + 3.2 alpha1 +*/ + +static const char *korgVersion = "3.1"; + +#endif diff --git a/korganizer/wordsgerman.h b/korganizer/wordsgerman.h new file mode 100644 index 0000000..4b53ecb --- a/dev/null +++ b/korganizer/wordsgerman.h @@ -0,0 +1,840 @@ +{ "10 minutes","10 Minuten", }, +{ "10th","10." }, +{ "11th","11." }, +{ "12 pm Format","12 AM/PM Format" }, +{ "12th","12." }, +{ "13th","13." }, +{ "14th","14." }, +{ "15th","15." }, +{ "16th","16." }, +{ "17th","17." }, +{ "18th","18." }, +{ "19th","19." }, +{ "1 Day","1 Tag" }, +{ "1 h","1 Std" }, +{ "1 (high)","1 (hoch)" }, +{ "5 (low)","5" }, +{ "1st","1." }, +{ "20th","20." }, +{ "21st","21." }, +{ "22nd","22." }, +{ "23rd","23." }, +{ "24:00 Hour Format","24:00 Stunden Format" }, +{ "24th","24." }, +{ "25th","25." }, +{ "26th","26." }, +{ "27th","27." }, +{ "28th","28." }, +{ "29th","29." }, +{ "2nd","2." }, +{ "30 minutes","30 Minuten" }, +{ "30th","30." }, +{ "31st","31." }, +{ "3rd","3." }, +{ "4th","4." }, +{ "5 (lowest)","5 (Niedrigster)" }, +{ "5th","5." }, +{ "6th","6." }, +{ "7th","7." }, +{ "8th","8." }, +{ "9th","9." }, +{ "About...","Über..." }, +{ "&Accept","&Akzeptieren" }, +{ "Accept","Akzeptieren" }, +{ "Accept A&ll","A&lles Akzepieren" }, +{ "Access:","Zugriff:" }, +{ "A corresponding event is missing in your calendar!","Ein zugehöriger Termin fehlt in ihrem Kalender!" }, +{ "Actions","Aktionen" }, +{ "Add Filter","Filter Hinzufügen" }, +{ "&Add","Hinzufügen" }, +{ "Add","Hinzufügen" }, +{ "Additional email addresses:","Zusätzliche E-Mail Adressen:" }, +{ "Additional email address:","Zusätzliche E-Mail Adresse:" }, +{ "&Addressbook","&Adressbuch" }, +{ "Address &Book...","Adress&buch..." }, +{ "Agenda Size","Agende Größe" }, +{ "Agenda Size:","Größe der Agenda:" }, +{ "Agenda view:","Agenda Ansicht:" }, +{ "Agenda view background color:","Hintergrund der Agenda Ansicht:" }, +{ "All attendees","Alle Teilnehmer" }, +{ "AllDayAgenda Height:","Höhe Ganztages Agenda:" }, +{ "Allday","Ganztägig" }, +{ "Anonymous","Anonym" }, +{ "Apply","Anwenden" }, +{ "Apr","Apr" }, +{ "April","April" }, +{"Ask for every entry on conflict","Frage bei Konflikten nach"}, +{ "Ask for preferences before syncing","Vor dem Syncronisieren nachfragen" }, +{ "Ask for quit when closing KO/Pi","Vor dem Beenden von KO/Pi nachfragen" }, +{ "Attendees","Teilnehmer" }, +{ "Aug","Aug" }, +{ "August","August" }, +{ "Auto-Save","Automatisches Abspeichern" }, +{ "Auto save delay in minutes:","Verzög.autom.Speichern in Min" }, +{ "Auto saving...","Automatische Sicherung..." }, +{ "Begin on:","Starte mit:" }, +{ "Begins on: %1","Starte mit: %1" }, +{ "<b>From:</b> %1 <b>To:</b> %2","<b>Vom:</b> %1 <b>Zum:</b> %2" }, +{ "Bigger","Größer" }, +{ "Biggest","Riesig" }, +{ "Big","Groß" }, +{ "<b>On:</b> %1","<b>Am:</b> %1" }, +{ "<b>On:</b> %1 <b>From:S</b> %2 <b>To:</b> %3","<b>Am:</b> %1 <b>Vom:S</b> %2 <b>Zum:</b> %3" }, +{ "<b>Original event:</b><p>","<b>Original Termin:</b><p>" }, +{ " - both are modified after last sync"," - beide wurden nach der letzten Syncronisation verändert" }, +{ "Busy","Belegt" }, +{ "&Cancel","Abbre&chen" }, +{ "Cancel","Abbrechen" }, +{ "Cannot delete To-Do\nwhich has children.","Kann Todo nicht löschen,\n da noch Einträge vorhanden sind" }, +{ "Cannot delete To-Do which has children.","Kann Todo nicht löschen, da noch Einträge vorhanden sind" }, +{ "Can't generate mail:\nNo event selected.","Kann e-Mail nicht erstellen:\nKein Termin ausgewählt." }, +{ "Categories...","Kategorien..." }, +{ "Categories","Kategorien" }, +{ "Category","Kategorie" }, +{ "Center View","Zentriere Ansicht" }, +{ "Change","Ändere" }, +{ "Cinema","Kino" }, +{ "Click to add a new Todo","Hier klicken, um ein neues Todo anzulegen" }, +{ "Clone Item","Klone Eintrag" }, +{ "&Close","S&chließen" }, +{ "Close","Schließen" }, +{ "Close this dialog to abort deletion!","Zum Abbrechen des Löschvorganges Dialog schließen!" }, +{ "Colors","Farben" }, +{ "completed","erledigt" }, +{ "completed on %1","erledigt am %1" }, +{ "Complete","Erledigt" }, +{ "Confidential","Vertraulich" }, +{ "Configure...","Einstellungen..." }, +{ "Confirm &deletes","Löschvogang bestätigen" }, +{ "Couldn't load calendar\n '%1'.","Kann Kalender\n '%1' nicht laden." }, +{ "Counter-event Viewer","Terminzähler Ansicht" }, +{ "Daily ending hour:","Feierabend:" }, +{ "Daily starting hour:","Anfangszeit:" }, +{ "Daily","Täglich" }, +{ "Date Format","Datums Format" }, +{ "Date Format:","Datums Format:" }, +{ "DateNavigator:(nr)","Datums Navigator" }, +{ "Dates: ","Datum: " }, +{ "Date && Time","Datum && Zeit" }, +{ "Day begins at:","Der Tag beginnt um:" }, +{ "Days in Next-X-Days:","Tage in Nächste-X-Tage:" }, +{ "Days in What's Next:","Tage in What's Next:" }, +{ "day(s)","Tag(e)" }, +{ "Days to show in Next-X-Days view:","Welche Tage in Nächste-X-Tagen anzeigen:" }, +{ "day","Tag" }, +{ "Dec","Dez" }, +{ "December","Dezember" }, +{ "Default alarm time:","Standard Alarmzeit:" }, +{ "Default appointment time:","Standard Termin Startzeit:" }, +{ "Default event color:","Standard Terminfarbe:" }, +{ "Default","Standard" }, +{ "Def. duration of new app.:","Standard Termin Länge:" }, +{ "Delete all completed To-Dos?","Alle bereits erledigten Todos löschen?" }, +{ "Delete All","Lösche alles" }, +{ "Delete all selected","Lösche alle Selektierten" }, +{ "Delete Current","Aktuellen löschen" }, +{ "Delete Event...","Lösche Termin..." }, +{ "Delete Event","Lösche Termin" }, +{ "&Delete","Löschen" }, +{ "Delete...","Löschen..." }, +{ "Delete","Löschen" }, +{ "Delete Todo...","Lösche Todo..." }, +{ "Delete To-Do","Lösche Todo" }, +{ "Deleting item %d ...","Lösche Eintrag %d..." }, +{ "Descriptions","Beschreibungen" }, +{ "Deselect All","Deselektiere Alle" }, +{ "Details","Details" }, +{ "Dinner","Abendessen" }, +{ "Do you really want\nto close KO/Pi?","Möchten Sie wirklich\nKO/PI verlassen?" }, +{ "Due Date","Fällig am" }, +{ "Due: ","Fällig: "}, +{ "Due Time","Fällig um" }, +{ "Due:","Fällig:"}, +{ "Duration: ","Dauer: " }, +{ "Edit...","Bearbeite..." }, +{ "Edit","Bearbeite" }, +{ "Edit Event...","Bearbeite Termin..." }, +{ "Edit Event","Bearbeite Termin" }, +{ "Edit exceptions","Bearbeite Ausnahmen" }, +{ "EditorBox:","Editor Fenster:" }, +{ "Edit Recurrence Range","Bearbeite Wiederholung" }, +{ "Edit Todo...","Berabeite Todo..." }, +{ "Edit To-Do","Todo bearbeiten" }, +{ "E&mail address:","E&mail Adresse:" }, +{ "(EmptyEmail)","(KeineEmail)" }, +{ "(EmptyName)","(KeinName)" }, +{ "Enable Recurrence","Wiederholender Termin" }, +{ "End after","Endet nach"}, +{ "End by:","Endet am"}, +{ "End Date","End Datum" }, +{ "End:","Ende:" }, +{ "End Time","End Zeit" }, +{ "English","Englisch" }, +{ "Event","Termin" }, +{ "Event list","Termin Liste" }, +{ "Events","Termine" }, +{ "Event Viewer:","Termin Übersicht:" }, +{ "every","jede" }, +{ "Exceptions...","Ausnahmen..." }, +{ "Exceptions","Ausnahmen" }, +{ "Exclude holidays","Ohne freie Tage" }, +{ "Exclude Saturdays","Ohne Samstage" }, +{ "Feb","Feb" }, +{ "February","Februar" }, +{ "&Find","Suche!" }, +{ "Fonts","Schriftart" }, +{ "Force take local entry always","Erzwinge:Nimm immer lokalen Eintrag" }, +{ "Force take remote entry always","Erzwinge:Nimm immer fernen Eintrag"}, +{ "Free","Frei" }, +{ "Friday","Freitag" }, +{ "Fri","Fr" }, +{ "From:","Vom:" }, +{ "Full &name:","Vor- und &Nachname:" }, +{ "General","Allgemein" }, +{ "German","Deutsch" }, +{ "Gifts","Geschenke" }, +{ "Go to Today","Heute anzeigen" }, +{ "Help","Hilfe" }, +{ "Hide Dates","Daten ausblenden" }, +{ "Highlight color:","Markierungen:" }, +{ "Holiday color:","Freie Tage:" }, +{ "hour(s)","Stunde(n)" }, +{ "In %1 days: ","In %1 Tagen: " }, +{ "Incomplete Todo:","Unerledigte Aufgaben:" }, +{ "Information","Information" }, +{ "Invalid search expression,\ncannot perform ","Kann Suche nicht ausführen" }, +{ "Jan","Jan" }, +{ "January","Januar" }, +{ "JournalView:","Journal Ansicht:" }, +{ "Journals","Journale" }, +{ "Jul","Jul" }, +{ "July","Juli" }, +{ "Jump to date","Springe zum Datum" }, +{ "June","Juni" }, +{ "Jun","Jun" }, +{ "Key Bindings...","Tastenzuordnung..." }, +{ "Kids","Kinder" }, +{ "Known Problems...","Bekannte Probleme..." }, +{ "KO/Pi Find ","KO/Pi Suchdialog " }, +{ "KO/Pi Find: ","KO/Pi Suchen: " }, +{ "KO/Pi is starting ... "," KO/Pi startet ... \n... Zeit für eine Kaffeepause ..." }, +{ "Language:(needs restart)","Sprache (Neustart!)" }, +{ "Language:","Sprache" }, +{ "Large","Etwas mehr" }, +{ "List View:","Listenansicht:" }, +{ "List View","Listenansicht" }, +{ "Load/Save","Laden/Speichern" }, +{ "Load Template","Lade Vorlage" }, +{ "Locale","Localisation" }, +{ "Local temp file:","Lokale temp. Datei:" }, +{ "Location: ","Ort: " }, +{ "Location:","Ort:" }, +{ "Mail client","Mail Programm" }, +{ "Mail Client","Mail Programm" }, +{ "March","März" }, +{ "Mar","Mär" }, +{ "May","Mai" }, +{ "M. Bains line:","M. Bains Linie:" }, +{ "Medium","Medium" }, +{ "Method","Methode" }, +{ "minute(s)","Minute(n)" }, +{ "Monday","Montag" }, +{ "Mon","Mo" }, +{ "Monthly","Monatlich" }, +{ "Month not long enough","Monat ist nicht lang genug" }, +{ "month(s)","Monat(e)" }, +{ "Month view:","Monatsansicht:" }, +{ "Month view uses category colors","Monatsansicht zeigt Kategorie Farben" }, +{ "Todo view uses category colors","To-Do Ansicht zeigt Kategorie Farben" }, +{ "Move &Down","Nach unten verschieben" }, +{ "Move &Up","Nach oben verschieben" }, +{ "Name:","Name:" }, +{ "Name","Name" }, +{ "\nAre you sure you want\nto delete this event?","\nSind Sie sicher, dass Sie\nden Termin löschen möchten?" }, +{ "%n Days","%n Tage" }, +{ "Never","Nie" }, +{ "New event...","Neuer Termin..." }, +{ "New event","Neuer Termin" }, +{ "New Event...","Neuer Termin..." }, +{ "New Events/Todos should","Neue Termine/Todos sollten" }, +{ "&New","&Neu" }, +{ "New","Neu", }, +{ "New Sub-Todo...","Neues Sub-Todo..." }, +{ "New Todo...","Neues Todo..." }, +{ "Next Alarm: ","Nächster Alarm: ", }, +{ "&Next Day","&Nächster Tag", }, +{ "Next days view uses full window","Nächste-X-Tage nutzt Vollbild" }, +{ "Next month","Nächster Monat" }, +{ "&Next Week","&Nächste Woche" }, +{ "Next year","Nächstes Jahr" }, +{ "Next Year","Nächstes Jahr" }, +{ "%n h","%n Std" }, +{ "No ending date","Kein End-Datum", }, +{ "No event, nothing to do.","Kein Termin, nichts zu tun.", }, +{ "No event selected.","Kein Termin selektiert" }, +{ "No","Nein" }, +{ "No program set","Kein Programm ausgewählt", }, +{ "Normal","Normal" }, +{ "[No selection]","Keine Selektion", }, +{ "No sound set","Kein Sound ausgewählt", }, +{ "no time ","keine Zeit ", }, +{ "no time","keine Zeit", }, +{ "No Time","Keine Zeit" }, +{ "November","November" }, +{ "Nov","Nov", }, +{ "\nThis event recurs\nover multiple dates.\n","\nDieser Termin wiederholt sich an mehreren Tagen.\n" }, +{ "occurrence(s)","Vorkommen" }, +{ "October","Oktober" }, +{ "Oct","Okt", }, +{ "O-due!","Ü-fällig! " }, +{ "&OK","&OK" }, +{ "Ok+Show!","Ok+Anzeigen" }, +{ "Organizer: %1","Organisator %1" }, +{ "Organizer","Organisator" }, +{ "Owner: ","Besitzer: " }, +{ "Owner:","Besitzer:" }, +{ "<p><b>Priority:</b> %2</p>","<p><b>Priorität:</b> %2</p>" }, +{ "Pick a date to display","Wähle einen Tag zum anzeigen aus" }, +{ "Please specify a valid due date.","Bitte gültiges Fälligkeitsdatum angeben."}, +{ "Please specify a valid end date, for example '%1'.","Bitte gültiges Enddatum angeben, z.B.'%1'." }, +{ "Please specify a valid start date.","Bitte gültiges Startdatum angeben." }, +{ "Please specify a valid start date, for example '%1'.","Bitte gültiges Startdatum angeben, z.B. '%1'." }, +{ "Please specify a valid start time.","Bitte gültige Startzeit angeben."}, +{ "Please specify a valid start time, for example '%1'.","Bitte gültige Startzeit angeben, z.B. '%1'." }, +{ "Preferences - some settings need a restart (nr)","Einstellungen - teilweise Neustart erforderlich (bn)" }, +{ "&Previous Day","Vorheriger Tag" }, +{ "Previous month","Vorheriger Monat" }, +{ "Previous Month","Vorheriger Monat" }, +{ "&Previous Week","Vorherige Woche" }, +{ "Previous year","Vorheriges Jahr" }, +{ "Previous Year","Vorheriges Jahr" }, +{ "Printing","Drucken" }, +{ "Priority:","Priorität:" }, +{ "Private","Privat" }, +{ "Proceed","Weiter" }, +{ "Public","Öffentlich" }, +{ "Purge","Entferne" }, +{ "Purge Completed","Entferne erledigte ToDos" }, +{ "Purge To-Dos","Todos bereinigen" }, +{ "read-only","schreibgeschützt" }, +{ "Recur every","Wiederh. alle" }, +{ "Recur in the month of","Wiederh. im Monat" }, +{ "Recur on the","Wiederh. am" }, +{ "Recur on this day","Wiederh. am diesen Tag" }, +{ "Recurrence Range...","Wiederholungs Zeitraum..." }, +{ "Recurrence Range","Wiederholungs Zeitraum" }, +{ "Recurrence Rule","Wiederholungs Regel" }, +{ "Recurrence","Wiederholung" }, +{ "Recurs","Wiederholung" }, +{"&Reject","Abweisen"}, +{ "Reminder:","Alarm:" }, +{ "Rem.:","Alarm:" }, +{ "Rem.","Alarm:" }, +{ "Remote file:","Remote Datei:"}, +{ "Remote IP:","Remote (ferne) IP:" }, +{ "Remote syncing (via ssh/scp) network settings ","Remote Sync (via ssh/scp) Netzwerk Einstellungen " }, +{ "Remote user:","Remote Benutzer"}, +{ "&Remove","Entfe&rnen" }, +{ "Remove","Entfernen" }, +{ "Request response","Bemerkung anfordern" }, +{ "Role:","Rolle:" }, +{ "Role","Rolle" }, +{ "Sat","Sa" }, +{ "Saturday","Samstag" }, +{ "Search for:","Suche nach:" }, +{ "Search In","Suche in" }, +{ "Search...","Suche..." }, +{ "Search","Suche" }, +{ "Select Addresses","Wähle Adressen" }, +{ "Select all","Selektiere Alle" }, +{ "Select a month","Wähle Monat" }, +{ "Select a week","Wähle Woche" }, +{ "Select a year","Wähle Jahr" }, +{ "Send directly","Sende direkt" }, +{ "&Send Messages","&Sende Nachrichten", }, +{ "Sep","Sep" }, +{ "September","September" }, +{ "Shopping","Einkaufen" }, +{ "Use short date in (WN/E) view","Kurzdatum in (WN/Termin) Ansicht" }, +{ "Show Dates","Zeige Daten" }, +{ "Show events that recur daily in date nav.","Zeige tägl.wiederh.Term.in Datums Nav." }, +{ "Show Event...","Zeige Termin..." }, +{ "Show ev. that recur weekly in date nav.","Zeige wöch.wiederh.Term.in Datums Nav." }, +{ "Show Marcus Bains line","Zeige Marcus Bains Linie" }, +{ "Show summary after syncing","Zeige Zusammenfassung nach Sync." }, +{ "Show time as:","Zeige Zeit als" }, +{ "Show Todo...","Zeige To-Do" }, +{ "Show topmost todo prios in What's N.:","Anz. höchster Prios in What's N.:"}, +{ "Show topmost todo prios in What's Next:","Anz. höchster Prios in What's Next:"}, +{ "Show vertical screen (Needs restart)","Vertikaler Bildschirm-Layout (Neustart!)" }, +{ "&Show","Zeige" }, +{ "Show...","Zeige..." }, +{ "Show","Zeige" }, +{ "Small","Klein" }, +{ "Sorry","Entschuldigung" }, +{"Sorry, the copy command failed!\nCommand was:\n","Der Kopierbefehl schlug fehl!\nBefehl war:\n"}, +{ "Start:","Start:" }, +{ "Start Date","Start Datum" }, +{ "Start date: %1","Start Datum: %1" }, +{ "Start Time","Start Zeit" }, +{ "Status:","Status:" }, +{ "Status","Status:" }, +{ "Summaries","Titel" }, +{ "Summary:","Titel:" }, +{ "Summary","Titel" }, +{ "Sunday","Sonntag" }, +{ "Sun","So" }, +{ "Sync preferences:","Sync Einstellungen" }, +{ "Sync Prefs","Sync Einstellungen" }, +{ "Syncronize","Daten abgleich" }, +{ "Take local entry on conflict","Nimm lokalen Eintrag beim Konflikt" }, +{ "Take newest entry on conflict","Nimm neuesten Eintrag beim Konflikt" }, +{ "Take remote entry on conflict","Nimm fernen Eintrag beim Konflikt" }, +{ "Template '%1' does not contain a valid Todo.","Template '%1' enthält kein gültiges To-Do" }, +{ "Template does not contain a valid Event.","Template '%1' enthält keinen gültigen Termin" }, +{ "Template...","Vorlage..." }, +{ "This day","Dieser Tag" }, +{ "This is an experimental feature. ","Dieses Feature ist experimentel" }, +{ "This item will be\npermanently deleted.","Dieser Eintrag wird\nkomplett gelöscht." }, +{ "This item will be permanently deleted.", "Dieser Eintrag wird komplett gelöscht." }, +{ "Thu","Do" }, +{ "Thursday","Donnerstag" }, +{ "Time associated","Mit Zeit" }, +{ "Time bar:","Uhrzeit Zeile:" }, +{ "Time && Date","Zeit und Datum" }, +{ "Time Format","Zeit Format" }, +{ "Time Format(nr):","Zeit Format(Neustart!)" }, +{ "Date Labels:","Datumsleiste:" }, +{ "Time: ","Zeit: " }, +{ "Timezone:","Zeitzone:" }, +{ "Tiny","Sehr klein" }, +{ "To: ","Bis: " }, +{ "To:","Bis:" }, +{ "Today: ","Heute: " }, +{ "Todo due today color:","Heute fällige To-Do's" }, +{ "To-do items:","To-Do items:" }, +{ "Todo overdue color:","Überfällige To-Do's" }, +{ "Todo","Todo" }, +{ "To-do view shows completed Todos","To-do Ansicht zeigt erledigte To-dos" }, +{ "ToDoView:","Todo Ansicht:" }, +{ "Toggle Alarm","Wechsle Alarm" }, +{ "Toggle Allday","Umschalten Ganztag" }, +{ "Tomorrow: ","Morgen: " }, +{ "Tue","Di" }, +{ "Tuesday","Dienstag" }, +{ "Two entries are in conflict, if: ","Zwei Einträge haben einen Konflikt, wenn:" }, +{ "Unable to find template '%1'.","Kann Vorlage '%1' nicht finden." }, +{ "Unknown","Unbekannt" }, +{ "Up","Hinauf" }, +{ "Use password (if not, ask when syncing)","Passwort: (sonst jedesmal anfragen)" }, +{ "User defined","Benutzerdefiniert" }, +{ "User long date:","Format langes Datum:" }, +{ "User short date:","Forma kurzes Datum:" }, +{ "View","Ansicht" }, +{ "View Fonts","Schriftarten Ansichten" }, +{ "Views","Ansichten" }, +{ "Wed","Mi" }, +{ "Wednesday","Mittwoch" }, +{ "Week %1","Woche %1" }, +{ "Weekly","Wöchentlich" }, +{ "Week starts on Sunday","Woche beginnt Sonntags" }, +{ "What's Next View:","What's Next Anz." }, +{ "What's next ?","Was kommt als nächstes?(What's Next)" }, +{ "Working Hours","Tägliche Arbeitszeit" }, +{ "Working hours color:","Arbeitszeit in der Agenda Ansicht:" }, +{ "Write back existing entries only","Nur exisitierende Einträge zurückschreiben" }, +{ "Write back synced file","Syncronisierte Datei zurückschreiben" }, +{ "Yearly","Jährlich" }, +{ "year(s)","Jahr(e)" }, +{ "Yes","Ja" }, +{ "You have %d item(s) selected.\n","Sie haben %d Einträge ausgewählt.\n" }, +{ "You have to restart KOrganizer for this setting to take effect.","Sie müssem Korganizer neu starten, damit diese Einstellung aktiviert wird." }, +{ "week(s) on:","Woche(n) am: " }, +{ "Full menu bar(nr)","Volle Menuleiste(bn)" }, +{ "Timezone has daylight saving","Zeitzone hat Sommerzeit" }, +{ "Actual start/end is the\nsunday before this date.","Tatsächlicher Beginn/Ende ist der Sonntag\nvor diesem Datum!" }, +{ "The year in the date is ignored.","Das Jahr vom Datum wird ignoriert." }, +{ "Daylight start:","Sommerzeit Beginn:" }, +{ "Daylight end:","Sommerzeit Ende:" }, +{ "Time Zone","Zeitzone" }, +{ "Monday 19 April 2004: %A %d %B %Y","Montag 19 April 2004: %A %d %B %Y" }, +{ "%A: Monday --- %a: Mon","%A: Montag --- %a: Mon" }, +{ "minutely","minütlich" }, +{ "hourly","stündlich" }, +{ "daily","täglich" }, +{ "weekly","wöchentlich" }, +{ "monthly","monatlich" }, +{ "day-monthly","tag-monatlich" }, +{ "month-yearly","monat-jährlich" }, +{ "day-yearly","tag-jährlich" }, +{ "position-yearly","pos-jährlich" }, +{ "Edit item on doubleclick (if not, show)","Editiere mit Doppelklick(wenn nicht, zeige)" }, +{ "Highlight current day in agenda","Hebe >>heute<< in Agenda hervor" }, +{ "Use light color for highlight current day","Helle Farbe für >>heute<< Hervorhebung" }, +{ "Highlight selection in Time Edit","Hebe Auswahl in Zeit Edit hervor" }, +{ "Hold fullscreen on view change","Behalte Vollbild bei Ansichswechsel" }, +{ "Hold non-fullscreen on view change","Behalte Nicht-Vollbild bei Ansichtsw." }, +{ "Event list view uses full window","Listenansicht nutzt Vollbild" }, +{ "Set agenda to DayBeginsAt on change","Setze Agenda auf TagBeginntUm bei Wechsel" }, +{ "Set agenda to current time on change","Setze Agenda auf gegenw.Zeit bei Wechsel" }, +{ "Listview uses monthly timespan","Listenansicht zeigt monatliche Zeitspanne" }, +{ "ViewChange","Ansichtswechsel" }, +{ "Default alarm *.wav file:","Standard Alarm *.wav Datei:" }, +{ "This setting is useless for 5500 user!","Diese Einst. ist nutzlos für 5500 Nutzer" }, +{ "File","Datei" }, +{ "Clone...","Dupliziere.." }, +{ "Move...","Bewege..." }, +{ "Beam...","Sende via IR..." }, +{ "&Clone...","Dupliziere.." }, +{ "&Move...","Bewege..." }, +{ "&Beam...","Sende via IR..." }, +{ "Show Completed","Zeige erledigte Todos" }, +{ "Show Quick Todo","Zeige Quick Todo" }, +{ "Unparent Todo","Un-sub Todo" }, +{ "Save selected to file...","Speichere Selektierte..." }, +{ "Add Categ. to selected...","Füge zu Selekt. Kateg. hinzu..." }, +{ "Set Categ. for selected...","Setze Kateg. für Selekt." }, +{ "Beam selected via IR","Sende Selekt. via IR..." }, +{ "Search","Suchen" }, +{ "Date Picker","Datum auswählen" }, +{ "Day View","Tagesansicht" }, +{ "Work Week","Arbeitswoche" }, +{ "Week","Wochenansicht" }, +{ "Month","Monatsansicht" }, +{ "Todo View","Todo Liste" }, +{ "Journal","Journal Ansicht" }, +{ "Next days","Nächste Tage" }, +{ "Print agenda selection...","Drucke Agendaselektion..." }, +{ "Toggle DateNavigator","Navigator umschalten" }, +{ "Toggle FilterView","Filteransicht umschalten" }, +{ "Prev. month","Vorheriger Monat" }, +{ "Go backward","Gehe zurück" }, +{ "Go forward","Gehe weiter" }, +{ "Synchronize","Synchronisieren" }, +{ "AgendaSize","Agendagröße" }, +{ "Import (*.ics/*.vcs) file","Importiere (*.ics/*.vcs) Datei" }, +{ "Import last file","Importiere letzte Datei" }, +{ "Import Opie/Qtopia Cal.","Importiere Opie/Qtopia Kal." }, +{ "Load Calendar Backup","Lade Kalender Backup" }, +{ "Save Calendar Backup","Speichere Kalender Backup" }, +{ "Export VCalendar","Exportiere VCalendar" }, +{ "Manage new categories...","Verwalte neue Kategorien..." }, +{ "Beam complete calendar...","Sende kompletten Kalender via IR" }, +{ "Beam filtered calendar...","Sende gefilterten Kalender via IR" }, +{ "Remote via ssh","Über Netzwerk via ssh" }, +{ "With local file","Mit lokaler Datei" }, +{ "With last file","Mit letzter Datei" }, +{ "KO/Pi: Ready for beaming","KO/Pi: Bereit zum Senden" }, +{ "KO/Pi:Beaming done","KO/Pi: Senden erfolgt" }, +{ "Save filename","Speichern: Dateinamen wählen" }, +{ "File already exists!\nOld file from:\n%1\nOverwrite?\n","Dateiname existiert bereits!\nAlte Datei vom:\n%1\nÜberschreiben?\n" }, +{ "KO/Pi: Warning!","KO/Pi: Warnung!" }, +{ "Overwrite!","Überschreibe!" }, +{ "KO/Pi:Saved %1","KO/Pi:Gespeichert %1" }, +{ "All selected items will be\npermanently deleted.\n(Deleting items will take\nsome time on a PDA)\n","Alle selektierten Einträge werden\nunwiederbringlich gelöscht.\n(Löschen kann auf dem\nPDA einige Zeit dauern)\n" }, +{ "KO/Pi Confirmation","KO/Pi Bestätigung" }, +{ "Close dialog to abort deletion!","Schließe Dialog um das Löschen abzubrechen!" }, +{ "Deleting item %d ...","Lösche Eintrag %d ..." }, +{ "%d items remaining in list.","%d Einträge sind in der Liste verblieben." }, +{ "Size","Größe" }, +{ "Date","Datum" }, +{ "Mime Type","Datei Typ" }, +{ "All Files","Alle Dateien" }, +{ "Files","Dateien" }, +{ "Documents","DoKumente" }, +{ "Select Categories","Selektiere Kategorien" }, +{ " &Deselect All "," Auswahl aufheben " }, +{ "A&dd","Hinzu" }, +{ "&Modify","Ändern" }, +{ "Edit Categories","Editiere Kategorien" }, +{ " &Edit Categories "," &Editiere Kategorien " }, +{ "Beam Options","Beam Einstellungen" }, +{ " With timezone "," Mit Zeitzone " }, +{ " Local time ", " Lokale Zeit " }, +{ "Manage new Categories","Verwalte neue Kategorien" }, +{ "Add to category list","Füge zur Kategorieliste hinzu" }, +{ "Remove from Events/Todos","Entferne von Terminen/Todos" }, +{ "After importing/loading/syncing\nthere may be new categories in\nevents or todos\nwhich are not in the category list.\nPlease choose what to do:\n ","Nach dem Importieren/Laden/Syncen\nkann es neue Kategorien in den \nTerminen oder Todos geben, die nicht\nin der Kategorieliste enthalten sind.\nBitte wählen Sie, was passieren soll:\n " }, +{ "New categories not in list:","Kategorien, die nicht in der Liste sind:" }, +{ "File format","Datei Format" }, +{ "Time format","Zeit Format" }, +{ "Delete all\ncompleted To-Dos?","Lösche alle\nerledigten To-Dos?" }, +{ "KO/Pi:Saving Data to File ...","KO/Pi: Speichere Kalender in Datei ..." }, +{ "KO/Pi:File Saved. Needed %d sec, %d ms","KO/Pi: Abgespeichert in %d sec, %d ms" }, +{ "h","Std" }, +{ "min","Min" }, +{ "hou","Std" }, +{ "day","Tag" }, +{ "French(nyi)","Französich (noch nicht implementiert)" }, +{ "Time","Zeit" }, +{ "Event Viewer","Termin Ansicht" }, +{ "Cancel Sync","Sync Abbrechen" }, +{ "Remote","Fern" }, +{ "Local","Lokal" }, +{ "Conflict! Please choose entry","Konflikt! Bitte Eintrag wählen" }, +{ "Local: ","Lokal: " }, +{ "Remote: ","Fern: " }, +{ "Last modified: ","Zuletzt geändert: " }, +{ "Location: ","Ort: " }, +{ "<p><b>From:</b> %1 </p><p><b>To:</b> %2</p>","<p><b>Von:</b> %1 </p><p><b>Bis:</b> %2</p>" }, +{ "<p><b>On:</b> %1</p>","<p><b>Am:</b> %1</p>" }, +{ "<p><b>From:</b> %1</p> ","<p><b>Von:</b> %1</p> " }, +{ "<p><b>To:</b> %1</p>","<p><b>Bis:</b> %1</p>" }, +{ "<p><b>On:</b> %1</p> ","<p><b>Am:</b> %1</p> " }, +{ "<p><b>From:</b> %1 <b>To:</b> %2</p>","<p><b>Von:</b> %1 <b>Bis:</b> %2</p>" }, +{ "This is a %1 recurring event.","Das ist ein %1 wiederholender Termin." }, +{ "<b>Next recurrence is on:</b>","<b>Nächste Wiederholung ist am:</b>" }, +{ "<b>Last recurrence was on:</b>","<b>Letzte Wiederholung war am:</b>" }, +{ "( %1 min before )","( %1 min vorher )" }, +{ "<b>Alarm on: ","<b>Alarm am: " }, +{ "<b>Details: </b>","<b>Details: </b>" }, +{ "<p><b>Priority:</b> %2</p>","<p><b>Priorität:</b> %2</p>" }, +{ "<p><i>%1 % completed</i></p>","<p><i>%1 % erledigt</i></p>" }, +{ "Organizer","Organisator" }, +{ "Save","Speichern" }, +{ "Exit (+save)","Beenden (+ speichern)" }, +{ "Home","Zuhause" }, +{ "Office","Büro" }, +{ "Libary","Bücherei" }, +{ "Doctor","Arzt" }, +{ "Beach","Strand" }, +{ "Conference room","Konferenzraum" }, +{ "Drive Home","Heimfahrt" }, +{ "Watch TV","Tv gucken" }, +{ "Phone call","Telefonanruf" }, +{ "Pay bill","Rechnung bezahlen" }, +{ "Read book","Buch lesen" }, +{ "Watering plants","Pflanzen giessen" }, +{"Appointment","Verabredung" }, +{"Birthday","Geburtstag" }, +{"Business","Geschäft" }, +{"Business Travel","Geschäftsreise" }, +{"Cinema","Kino" }, +{"Customer","Kunde" }, +{"Break","Pause" }, +{"Breakfast","Frühstück" }, +{"Competition","Wettkampf" }, +{"Dinner","Abendessen" }, +{"Education","Erziehung" }, +{"Family","Familie" }, +{"Favorites","Favoriten" }, +{"Festival","Festival" }, +{"Fishing","Angeln" }, +{"Flight","Flug" }, +{"Gifts","Geschenk" }, +{"Holiday","Feiertag" }, +{"Holiday Cards","Ansichtskarten" }, +{"Hot Contacts","Heisse Kontakte" }, +{"Hiking","Wandern" }, +{"Hunting","Jagen" }, +{"Key Customer","Wichtiger Kunde" }, +{"Kids","Kinder" }, +{"Lunch","Mittagessen" }, +{"Meeting","Treffen" }, +{"Miscellaneous","Verschiedenes" }, +{"Partner","Partner" }, +{"Party","Partie" }, +{"Personal","Privat" }, +{"Personal Travel","Privatreise"}, +{"PHB","PHB" }, +{"Phone Calls","Telefonanruf" }, +{"Projects","Projekt" }, +{"Recurring","Wiederholend" }, +{"School","Schule" }, +{"Shopping","Einkaufen" }, +{"Speach","Rede" }, +{"Special Occasion","Spez.Gelegenheit" }, +{"Sports","Sport" }, +{"Talk","Vortrag" }, +{"Travel","Reise" }, +{"TV","TV" }, +{"Germany","Deutschland" }, +{"Sweden","Schweden" }, +{"Forest","Wald" }, +{ "Desert","Wüste" }, +{ "Kitchen","Küche" }, +{ "Lake","See" }, +{"University","Universität"}, +{"Vacation","Urlaub" }, +{"VIP","VIP" }, +{ "Import Sharp Calendar","Importiere Sharp Kalender" }, +{ "This todo has been cancelled!","Dieses Todo wurde gecancelt!" }, +{ "This event has been cancelled!","Dieser Termin wurde gecancelt!" }, +{ "Cancelled","Gecancelt" }, +{ "Multiple sync","Mehrfach Sync" }, +{ "Local file","Lokale Datei" }, +{ "Last file","Letzte Datei" }, +{ "Keys + Colors...","Tasten + Farben..." }, +{ "Mini icons in toolbar(nr)","Mini Icons in ToolBar(bn)" }, +{ "Quick load/save (w/o Unicode)","Schnelles Laden/Speichern (o Unicode)" }, +{ "Choose...","Wähle..." }, +{ "Use colors for application:","Setze Farben für Programm:" }, +{ "Buttons, menus, etc.:","Knöpfe, Menu, etc.:" }, +{ "Frames, labels, etc.:","Rahmen, Label, etc.:" }, +{ "Show parent To-Do's in What's Next view","Zeige Ober-Todo in What's Next Anz." }, +{ "Show location in What's Next view","Zeige Ort in What's Next Anz." }, +{ "Show events that recur ","Zeige Termine, die sich wiederholen:" }, +{ "Show in every cell ","Zeige in jeder Zelle " }, +{ "short month","kurzen Monat" }, +{ "icons","Icons" }, +{ "Show Sat/Sun together","Zeige Sam/Son zusammen" }, +{ "Categorie colors are applied to text","Kategorie Farben färben Text" }, +{ "Month view uses day colors","Monatsansicht zeigt Tagesfarben" }, +{ "Day color odd months","Tagesfarbe ungerade Monate" }, +{ "Day color even months","Tagesfarbe gerade Monate" }, +{ "Color for Sundays + category \"Holiday\"","Farbe für Sonntag + Kateg.\" Feiertag\"" }, +{ "To-do view shows complete as 'xx %'","Zeige Prozent erledigt als 'xx %'" }, +{ "Small To-do view uses smaller font","Kleine To-do Ansicht nutzt kleineren Font" }, +{ "Colors are applied to text","Farben werden auf Text angewendet" }, +{ "Use internal alarm notification","Nutze interne Alarm Benachrichtigung" }, +{ "Note: KO/Pi must be running to notify you about an alarm. Recommended for use on Zaurus: Disable this option and install KO/Pi alarm applet.\n","Achtung: KO/Pi muß ausgeführt werden damit die Benachrichtigung funktioniert. Empfehlung für Zaurus: Diese Option nicht wählen und KO/Pi Alarm Applet installieren.\n" }, +{ "Play beeps count:","Anzahl der Alarmpiepse: " }, +{ "Beeps interval in sec:","Zeitintervall der Alarmpiepse: " }, +{ "Default suspend time in min:","Standard Supendierungs Zeit: " }, +{ "Auto suspend count:","Anzahl der auto Suspendierungen" }, +{ "Alarm *.wav file for newly created alarm:","Alarm *.wav Datei für neu angelegte Alarme:" }, +{ "New profile","Neues Profil" }, +{ "Clone profile","Klone Profil" }, +{ "Delete profile","Lösche Profil" }, +{ "Profile:","Profil:" }, +{ "Include in multiple sync","Beziehe Profil in mehrfach Sync mit ein" }, +{ "Force: Take local entry always","Erzwinge: Nimm immer lokalen Eintrag" }, +{ "Force: Take remote entry always","Erzwinge: Nimm immer fernen Eintrag" }, +{ "Show summary after sync","Zeige Zusammenfassung nach dem Synchronisieren" }, +{ "Write back file","Schreibe Datei zurück" }, +{ "Remote file (w down/upload command)","Entfernte Datei (via down/upload Kommando)" }, +{ "Pre sync (download) command:","Bevor Sync (download) Kommando:" }, +{ "Local device name:","Name dieses Gerätes:" }, +{ "Ask for preferences before sync","Frage nach Synchronisationseinstellungen vor dem Syncen" }, +{ "Sync preferences","Synchronisations Einstellungen" }, +{ "Profile kind","Profil Art" }, +{ "Local file","Lokale Datei" }, +{ "Local file:","Lokale Datei:" }, +{ "Post sync (upload) command:","Nach Sync (upload) Kommando:" }, +{ "Fill in default values for:","Setze Beispiel Werte ein für:" }, +{ "Hint: Use $PWD$ for placeholder of password!","Hinweis: Benutze $PWD$ als Platzhalter für ein Passwort!" }, +{ "Synchronization Preferences","Einstellungen der Synchronisationsprofile"}, +{ "Device","Gerät:" }, +{ "Sync with file \n...%1\nfrom:\n%2\n","Sync mit Datei \n...%1\nvom:\n%2\n" }, +{ "Synchronization summary:\n\n %d items added to local\n %d items added to remote\n %d items updated on local\n %d items updated on remote\n %d items deleted on local\n %d items deleted on remote\n","Synchronisationsübersicht:\n\n %d items lokal hinzugefügt\n %d items entfernt hinzugefügt\n %d items lokal geändert\n %d items entfernt geändert\n %d items lokal gelöscht\n %d items entfernt gelöscht\n" }, +{ "Synchronization successful","Synchronisation erfolgreich" }, +{ "Sync cancelled or failed. Nothing synced.","Sync abgebrochen oder fehlgeschlagen. Nichts wurde gesynced." }, +{ "Sync file \n...%1\ndoes not exist!\nNothing synced!\n","Sync Datei \n...%1\nexistiert nicht!\nNichts wurde gesynced!\n" }, +{ "Sync filename(*.ics/*.vcs)","Sync Dateiname(*.ics/*.vcs)" }, +{ "Enter password","Passwort eingeben" }, +{ "Do you really want\nto remote sync\nwith profile \n","Wollen Sie wirklich\nmit dem entfernten\nProfil syncen: \n" }, +{ "Copy remote file to local machine...","Kopiere entfernte Datei auf lokalen Rechner..." }, +{ "Sorry, the copy command failed!\nCommand was:\n%1\n \nTry command on console to get more\ndetailed info about the reason.\n","Sorry, das Kopierkommando schlug fehl!\nKommando war:\n%1\n \nVersuche Kommando von Kosole um\nDetails für das Fehlschlagen\nzu erfahren.\n" }, +{ "Writing back file result: ","Resultat des Dateizurückschreibens: " }, +{ "Syncronization sucessfully completed","Synchronisation erfolgreich abgeschlossen" }, +{ "Edit Calendar Filters","Editiere Kalendar Filter" }, +{ "Enter filter name:","Neuer Filter Name:" }, +{ "Add Filter","Filter hinzufügen" }, +{ "Question","Frage" }, +{ "Filter position: ","Filter Position: " }, +{ "Month View","Monatsansicht" }, +{ "This profil cannot be deleted!\n","Dieses Profil kann\nnicht gelöscht werden!" }, +{ "KO/Pi config error","KO/Pi Konfig. Fehler" }, +{ "Local device name undefined!\nPlease define device name!","Name dieses Gerätes undefiniert!\nBitte Namen angeben!" }, +{ "Multiple profiles with same name!\nPlease use unique profile names!","Mehrere Profile haben denselben Namen!\nBitte unterschiedliche Namen wählen!" }, +{ "Access: ","Zugriff: " }, +{ "Needs Action","Aktion notwendig" }, +{ "Accepted","Akzeptiert" }, +{ "Declined","Abgelehnt" }, +{ "Tentative","Vorläufig" }, +{ "Delegated","Beauftragt" }, +{ "Completed","Vollständig" }, +{ "In Process","In Bearbeitung" }, +{ "Participant","Teilnehmer" }, +{ "Optional Participant","Möglicher Teilnehmer" }, +{ "Observer","Beobachter" }, +{ "Chair","Vorsitzender" }, +{ "Not supported \non desktop!\n","" }, +{ "Nothing selected!\n\nThis prints the full width of the Agenda view as you see it!\n\nTo determine the vertical range of the printing, please select\na vertical range (with the left mouse button down) in one column. ","Es ist nichts selektiert!\nDieses druckt die volle Breite der Agenda View, so wie man sie sieht.\nUm die verticale Auswahl zum Drucken zu bestimmen,\nbitte einen verticalen Zeitraum (mit gedrückter linker Maustaste)\nin einer Spalte auswählen. " }, +{ "Date range: ","Datums Zeitspanne: " }, +{ "Not supported \non PDA!\n","Nicht verfügbar\nauf dem PDA. " }, +{ "Syncing - close to abort!","Syncing-schließe um abzubrechen." }, +{ "Add / remove events","Add./entferne Termine" }, +{ "File does not exist:\n '%1'.","Datei existiert nicht:\n '%1'." }, +{ "Couldn't load calendar\n '%1'.","Kann Kalender nicht laden:\n '%1'." }, +{ "\nThe file on disk has changed!\nFile size: %1 bytes.\nLast modified: %2\nDo you want to:\n\n - Save and overwrite file?\n - Sync with file, then save?\n - Cancel without saving? \n","\nDie gepeicherte Datei wurde verändert!\nDatei Grösse: %1 Bytes.\nZuletzt geändert: %2\nMöchten Sie:\n\n - Speichern und die Datei überschreiben?\n - Mit Datei Synchronisieren, dann speichern?\n - Abbrechen ohne zu speichern? \n" }, +{ "Overwrite","Überschreiben" }, +{ "Sync+save","Syncen+speichern" }, +{ "Default","Standard" }, +{ " Categories added to list! "," Kategorien zur Liste hinzugefügt! " }, +{ " %d items?"," %d Einträge?" }, +{ "\nThis event recurs\nover multiple dates.\nAre you sure you want\nto delete this event\nand all its recurrences?","\nDieses ist ein\nwiederholender Termin!.\nSind Sie sicher, dass Sie\ndiesen Termin und alle\nWiederholungen löschen möchten?" }, +{ " ?\n\nDelete:\n"," ?\n\nLösche:\n" }, +{ "Current","Aktuelle" }, +{ "\nThis event recurs\nover multiple dates.\nDo you want to delete\nall it's recurrences,\nor only the current one on:\n","\nDieses ist ein\nwiederholender Termin!\nMöchten sie alle Wiederholungen\nlöschen, oder nur die aktuelle am:\n" }, +{ "All","Alle" }, +{ "Data Loss Warning","Datenverlust Warnung" }, +{ "Proceed","Weitermachen" }, +{ "The journal entries can not be\nexported to a vCalendar file.","Die Journal Einträge können\nnicht in eine vCalendar\nDatei exportiert werden!" }, +{ "Filter disabled ","Filter abgeschaltet" }, +{ "Filter selected: ","Gewählter Filter: " }, +{ "Toggle Cancel","Gecancelt ändern" }, +{ "&Toggle Cancel","Gecancel&t ändern" }, +{ "Configure Toolbar","Konfiguriere Toolbar" }, +{ "Stretched TB","Gedehnte TB" }, +{ "Import file \n...%1\ndoes not exist!\nNothing imported!\n","Import Datei \n...%1\nexistiert nicht!\nNichts importiert!\n" }, +{ "Import filename(*.ics/*.vcs)","Import Dateiname(*.ics/*.vcs)" }, +{ "When importing a calendar twice\nduplicated events will be ignored!\nYou can create a backup file with\nFile - Save Calendar Backup\nto revert importing","Wenn ein Kalender doppelt importiert\nwird, werden doppelte Einträge ignoriert!\nSie können eine Backup Datei anlegen unter\nDatei - Speichere Kalender Backup\num den Import rückgängig machen zu können.\n" }, +{ "Not supported \non desktop!\n","Nur verfügbar auf PDA!" }, +{ "Imported file successfully","Datei erfolgreich importiert" }, +{ "Error importing file","Fehler beim Importieren der Datei" }, +{ "Export vcal filename(*.vcs)","Export vcal Dateiname(*.vcs)" }, +{ "Save file\nalready exists!\nOld save file from:\n%1\nOverwrite?\n","Zu speichernde Datei\existiert bereits!\nExist. Datei vom:\n%1\nÜberschreiben?\n" }, +{ "Overwrite!","Überschreiben!" }, +{ "Import file \n...%1\nfrom:\n%2\nDuplicated entries\nwill not be imported!\n","Import Datei \n...%1\nvom:\n%2\nDuplizierte Einträge\nwerden nicht importiert!\n" }, +{ "Load backup filename","Lade Backup Dateiname" }, +{ "Backup file\ndoes not exist!\nNothing loaded!","Backup Datei\nexistiert nicht!\nNichts geladen!" }, +{ "KO/Pi:Loaded %1","KO/Pi:Geladen %1" }, +{ "Save backup filename","Speichere Backup Dateiname" }, +{ "Backup file\nalready exists!\nOld backup file from:\n%1\nOverwrite?\n","Backup Datei\nexistiert bereits!\nAlte Backup Datei vom:\n%1\nÜberschreiben?\n" }, +{ "KO/Pi:Saved %1","KO/Pi:Gespeichert %1" }, +{ "Details of attendee","Teilnehmerdetails" }, +{ "Work phone:\n","Telefon Arbeit:\n" }, +{ "Work mobile phone:\n","Mobiltelefon Arbeit:\n" }, +{ "Home phone:\n","Telefon privat:\n" }, +{ "Mobile home phone:\n","Mobiltelefon privat:\n" }, +{ "Email:\n","Email:\n" }, +{ "Alarm disabled","Alarm deaktiviert" }, +{ "Audio.Al.: ","Audio Al.: " }, +{ "Proc.Al.: ","Proc.Al.: " }, +{ "No sound set","Kein Sound definiert" }, +{ "*.wav|Wav Files","*.wav|Wav Dateien" }, +{ "No program set","Kein Programm definiert" }, +{ "Running '%1'","Ausführen '%1'" }, +{ "Playing '%1'","Abspielen '%1'" }, +{ "Show Sync Events in WN/Agenda view","Zeige Sync Events in WN/Agenda Ansicht" }, +{ "User defined (usertranslation.txt)","Benutzerdefiniert (usertranslation.txt)" }, +{ "Load!","Laden!" }, +{ "Backup file from:\n%1\nLoading backup\nfile will delete\nyour current Data!\n","Backup Datei vom:\n%1\nDas Laden der Backup Datei\nlöscht die aktuellen Daten!\n" }, +{ "KO/Pi Features and hints","KO/Pi Eigenschaften und Tipps" }, +{ "KO/Pi User translation HowTo","KO/Pi Benutzer-Übersetzung HowTo" }, +{ "KO/Pi Synchronization HowTo","KO/Pi Synchronisation HowTo" }, +{ "Features + hints...","Eigenschaften + Tipps..." }, +{ "User translation...","Benutzer Übersetzung..." }, +{ "Sync HowTo...","Synchronisation HowTo..." }, +{ "Print calendar...","Drucke Kalender..." }, +{ "Anniversary","Jahrestag" }, +{ "When importing birthdays twice\nduplicated events will be ignored,\nif the event has not been\nchanged in KO/Pi!\n","Wenn Geburtstage mehrfach importiert\nwerden, werden doppelte Einträge ignoriert\nwenn sie nicht verändert wurden.\n" }, +{ "Import Birthdays (KA/Pi)","Importiere Geburtstage (KA/Pi)" }, +{ "Next recurrence is on: ","Nächste Wiederholung ist am:" }, +{ "<b>Alarm on: </b>","<b>Alarm am: </b>" }, +{ "<b>Access: </b>","<b>Zugriff: </b>" }, +{ "(%1 min before)","(%1 min vorher)" }, +{ "<b>Categories: </b>","<b>Kategorien: </b>" }, +{ "Save Journal/Description...","Speichere Journal/Details..." }, +{ "This saves the text/details of selected\nJournals and Events/Todos\nto a text file.","Das speichert den Text bzw.\ndie Details von selektierten\nJournalen und Events/Todos\nin eine Textdatei." }, +{ "Continue","Weitermachen" }, +{ " birthdays/anniversaries added!"," Geburts-/Jahrestage hinzugefügt" }, +{ "Attendee:","Teilnehmer:" }, +{ "Click OK to search ->","Klicke zum Suchen auf OK ->" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, +{ "","" }, diff --git a/libical/libical.pro b/libical/libical.pro new file mode 100644 index 0000000..6baecd4 --- a/dev/null +++ b/libical/libical.pro @@ -0,0 +1,4 @@ + + +TEMPLATE = subdirs +SUBDIRS = src diff --git a/libical/src/libical/config.h b/libical/src/libical/config.h new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libical/src/libical/config.h diff --git a/libical/src/libical/defines.h b/libical/src/libical/defines.h new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libical/src/libical/defines.h diff --git a/libical/src/libical/ical.h b/libical/src/libical/ical.h new file mode 100644 index 0000000..69a2c3a --- a/dev/null +++ b/libical/src/libical/ical.h @@ -0,0 +1,2996 @@ +#ifndef ICAL_VERSION_H +#define ICAL_VERSION_H + +#define ICAL_PACKAGE "libical" +#define ICAL_VERSION "0.23" + +#endif +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icaltime.h + CREATOR: eric 02 June 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALTIME_H +#define ICALTIME_H + +#include <time.h> + +/* icaltime_span is returned by icalcomponent_get_span() */ +struct icaltime_span { + time_t start; /* in UTC */ + time_t end; /* in UTC */ + int is_busy; /* 1->busy time, 0-> free time */ +}; + + +struct icaltimetype +{ + int year; + int month; + int day; + int hour; + int minute; + int second; + + int is_utc; /* 1-> time is in UTC timezone */ + + int is_date; /* 1 -> interpret this as date. */ + + const char* zone; /*Ptr to Olsen placename. Libical does not own mem*/ +}; + +/* Convert seconds past UNIX epoch to a timetype*/ +struct icaltimetype icaltime_from_timet(time_t v, int is_date); + +/* Return the time as seconds past the UNIX epoch */ +time_t icaltime_as_timet(struct icaltimetype); + +/* Return a string represention of the time, in RFC2445 format. The + string is owned by libical */ +char* icaltime_as_ical_string(struct icaltimetype tt); + +/* Like icaltime_from_timet(), except that the input may be in seconds + past the epoch in floating time. This routine is deprecated */ +struct icaltimetype icaltime_from_int(int v, int is_date, int is_utc); + +/* Like icaltime_as_timet, but in a floating epoch. This routine is deprecated */ +int icaltime_as_int(struct icaltimetype); + +/* create a time from an ISO format string */ +struct icaltimetype icaltime_from_string(const char* str); + +/* Routines for handling timezones */ +/* Return the offset of the named zone as seconds. tt is a time + indicating the date for which you want the offset */ +int icaltime_utc_offset(struct icaltimetype tt, const char* tzid); + +/* convert tt, of timezone tzid, into a utc time. Does nothing if the + time is already UTC. */ +struct icaltimetype icaltime_as_utc(struct icaltimetype tt, + const char* tzid); + +/* convert tt, a time in UTC, into a time in timezone tzid */ +struct icaltimetype icaltime_as_zone(struct icaltimetype tt, + const char* tzid); + +/* Return a null time, which indicates no time has been set. This time represent the beginning of the epoch */ +struct icaltimetype icaltime_null_time(void); + +/* Return true of the time is null. */ +int icaltime_is_null_time(struct icaltimetype t); + +/* Returns false if the time is clearly invalid, but is not null. This + is usually the result of creating a new time type buy not clearing + it, or setting one of the flags to an illegal value. */ +int icaltime_is_valid_time(struct icaltimetype t); + +/* Reset all of the time components to be in their normal ranges. For + instance, given a time with minutes=70, the minutes will be reduces + to 10, and the hour incremented. This allows the caller to do + arithmetic on times without worrying about overflow or + underflow. */ +struct icaltimetype icaltime_normalize(struct icaltimetype t); + +/* Return the day of the year of the given time */ +short icaltime_day_of_year(struct icaltimetype t); + +/* Create a new time, given a day of year and a year. */ +struct icaltimetype icaltime_from_day_of_year(short doy, short year); + +/* Return the day of the week of the given time. Sunday is 1 */ +short icaltime_day_of_week(struct icaltimetype t); + +/* Return the day of the year for the Sunday of the week that the + given time is within. */ +short icaltime_start_doy_of_week(struct icaltimetype t); + +/* Return a string with the time represented in the same format as ctime(). THe string is owned by libical */ +char* icaltime_as_ctime(struct icaltimetype); + +/* Return the week number for the week the given time is within */ +short icaltime_week_number(struct icaltimetype t); + +/* Create a new time from a weeknumber and a year. */ +struct icaltimetype icaltime_from_week_number(short week_number, short year); + +/* Return -1, 0, or 1 to indicate that a<b, a==b or a>b */ +int icaltime_compare(struct icaltimetype a,struct icaltimetype b); + +/* like icaltime_compare, but only use the date parts. */ +int icaltime_compare_date_only(struct icaltimetype a, struct icaltimetype b); + +/* Return the number of days in the given month */ +short icaltime_days_in_month(short month,short year); + + +#endif /* !ICALTIME_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalduration.h + CREATOR: eric 26 Jan 2001 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALDURATION_H +#define ICALDURATION_H + + +struct icaldurationtype +{ + int is_neg; + unsigned int days; + unsigned int weeks; + unsigned int hours; + unsigned int minutes; + unsigned int seconds; +}; + +struct icaldurationtype icaldurationtype_from_int(int t); +struct icaldurationtype icaldurationtype_from_string(const char*); +int icaldurationtype_as_int(struct icaldurationtype duration); +char* icaldurationtype_as_ical_string(struct icaldurationtype d); +struct icaldurationtype icaldurationtype_null_duration(); +int icaldurationtype_is_null_duration(struct icaldurationtype d); + +struct icaltimetype icaltime_add(struct icaltimetype t, + struct icaldurationtype d); + +struct icaldurationtype icaltime_subtract(struct icaltimetype t1, + struct icaltimetype t2); + +#endif /* !ICALDURATION_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalperiod.h + CREATOR: eric 26 Jan 2001 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALPERIOD_H +#define ICALPERIOD_H + + +struct icalperiodtype +{ + struct icaltimetype start; + struct icaltimetype end; + struct icaldurationtype duration; +}; + +struct icalperiodtype icalperiodtype_from_string (const char* str); + +const char* icalperiodtype_as_ical_string(struct icalperiodtype p); +struct icalperiodtype icalperiodtype_null_period(); +int icalperiodtype_is_null_period(struct icalperiodtype p); +int icalperiodtype_is_valid_period(struct icalperiodtype p); + + + + +#endif /* !ICALTIME_H */ + + + + +/* -*- Mode: C -*-*/ +/*====================================================================== + FILE: icalenums.h + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalenums.h + + Contributions from: + Graham Davison (g.m.davison@computer.org) + +======================================================================*/ + +#ifndef ICALENUMS_H +#define ICALENUMS_H + + + +/*********************************************************************** + * Component enumerations +**********************************************************************/ + +typedef enum icalcomponent_kind { + ICAL_NO_COMPONENT, + ICAL_ANY_COMPONENT, /* Used to select all components*/ + ICAL_XROOT_COMPONENT, + ICAL_XATTACH_COMPONENT, /* MIME attached data, returned by parser. */ + ICAL_VEVENT_COMPONENT, + ICAL_VTODO_COMPONENT, + ICAL_VJOURNAL_COMPONENT, + ICAL_VCALENDAR_COMPONENT, + ICAL_VFREEBUSY_COMPONENT, + ICAL_VALARM_COMPONENT, + ICAL_XAUDIOALARM_COMPONENT, + ICAL_XDISPLAYALARM_COMPONENT, + ICAL_XEMAILALARM_COMPONENT, + ICAL_XPROCEDUREALARM_COMPONENT, + ICAL_VTIMEZONE_COMPONENT, + ICAL_XSTANDARD_COMPONENT, + ICAL_XDAYLIGHT_COMPONENT, + ICAL_X_COMPONENT, + ICAL_VSCHEDULE_COMPONENT, + ICAL_VQUERY_COMPONENT, + ICAL_VCAR_COMPONENT, + ICAL_VCOMMAND_COMPONENT, + ICAL_XLICINVALID_COMPONENT, + ICAL_XLICMIMEPART_COMPONENT /* a non-stardard component that mirrors + structure of MIME data */ + +} icalcomponent_kind; + + + +/*********************************************************************** + * Request Status codes + **********************************************************************/ + +typedef enum icalrequeststatus { + ICAL_UNKNOWN_STATUS, + ICAL_2_0_SUCCESS_STATUS, + ICAL_2_1_FALLBACK_STATUS, + ICAL_2_2_IGPROP_STATUS, + ICAL_2_3_IGPARAM_STATUS, + ICAL_2_4_IGXPROP_STATUS, + ICAL_2_5_IGXPARAM_STATUS, + ICAL_2_6_IGCOMP_STATUS, + ICAL_2_7_FORWARD_STATUS, + ICAL_2_8_ONEEVENT_STATUS, + ICAL_2_9_TRUNC_STATUS, + ICAL_2_10_ONETODO_STATUS, + ICAL_2_11_TRUNCRRULE_STATUS, + ICAL_3_0_INVPROPNAME_STATUS, + ICAL_3_1_INVPROPVAL_STATUS, + ICAL_3_2_INVPARAM_STATUS, + ICAL_3_3_INVPARAMVAL_STATUS, + ICAL_3_4_INVCOMP_STATUS, + ICAL_3_5_INVTIME_STATUS, + ICAL_3_6_INVRULE_STATUS, + ICAL_3_7_INVCU_STATUS, + ICAL_3_8_NOAUTH_STATUS, + ICAL_3_9_BADVERSION_STATUS, + ICAL_3_10_TOOBIG_STATUS, + ICAL_3_11_MISSREQCOMP_STATUS, + ICAL_3_12_UNKCOMP_STATUS, + ICAL_3_13_BADCOMP_STATUS, + ICAL_3_14_NOCAP_STATUS, + ICAL_4_0_BUSY_STATUS, + ICAL_5_0_MAYBE_STATUS, + ICAL_5_1_UNAVAIL_STATUS, + ICAL_5_2_NOSERVICE_STATUS, + ICAL_5_3_NOSCHED_STATUS +} icalrequeststatus; + + +const char* icalenum_reqstat_desc(icalrequeststatus stat); +short icalenum_reqstat_major(icalrequeststatus stat); +short icalenum_reqstat_minor(icalrequeststatus stat); +icalrequeststatus icalenum_num_to_reqstat(short major, short minor); + +/*********************************************************************** + * Conversion functions +**********************************************************************/ + + +/* Thse routines used to be in icalenums.c, but were moved into the + icalproperty, icalparameter, icalvalue, or icalcomponent modules. */ + +/* const char* icalproperty_kind_to_string(icalproperty_kind kind);*/ +#define icalenum_property_kind_to_string(x) icalproperty_kind_to_string(x) + +/*icalproperty_kind icalproperty_string_to_kind(const char* string)*/ +#define icalenum_string_to_property_kind(x) icalproperty_string_to_kind(x) + +/*icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind);*/ +#define icalenum_property_kind_to_value_kind(x) icalproperty_kind_to_value_kind(x) + +/*const char* icalenum_method_to_string(icalproperty_method);*/ +#define icalenum_method_to_string(x) icalproperty_method_to_string(x) + +/*icalproperty_method icalenum_string_to_method(const char* string);*/ +#define icalenum_string_to_method(x) icalproperty_string_to_method(x) + +/*const char* icalenum_status_to_string(icalproperty_status);*/ +#define icalenum_status_to_string(x) icalproperty_status_to_string(x) + +/*icalproperty_status icalenum_string_to_status(const char* string);*/ +#define icalenum_string_to_status(x) icalproperty_string_to_status(x) + +/*icalvalue_kind icalenum_string_to_value_kind(const char* str);*/ +#define icalenum_string_to_value_kind(x) icalvalue_string_to_kind(x) + +/*const char* icalenum_value_kind_to_string(icalvalue_kind kind);*/ +#define icalenum_value_kind_to_string(x) icalvalue_kind_to_string(x) + +/*const char* icalenum_component_kind_to_string(icalcomponent_kind kind);*/ +#define icalenum_component_kind_to_string(x) icalcomponent_kind_to_string(x) + +/*icalcomponent_kind icalenum_string_to_component_kind(const char* string);*/ +#define icalenum_string_to_component_kind(x) icalcomponent_string_to_kind(x) + + +#endif /* !ICALENUMS_H */ + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icaltypes.h + CREATOR: eric 20 March 1999 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icaltypes.h + +======================================================================*/ + +#ifndef ICALTYPES_H +#define ICALTYPES_H + +#include <time.h> + + +/* This type type should probably be an opaque type... */ +struct icalattachtype +{ + void* binary; + int owns_binary; + + char* base64; + int owns_base64; + + char* url; + + int refcount; + +}; + +/* converts base64 to binary, fetches url and stores as binary, or + just returns data */ + +struct icalattachtype* icalattachtype_new(void); +void icalattachtype_add_reference(struct icalattachtype* v); +void icalattachtype_free(struct icalattachtype* v); + +void icalattachtype_set_url(struct icalattachtype* v, char* url); +char* icalattachtype_get_url(struct icalattachtype* v); + +void icalattachtype_set_base64(struct icalattachtype* v, char* base64, + int owns); +char* icalattachtype_get_base64(struct icalattachtype* v); + +void icalattachtype_set_binary(struct icalattachtype* v, char* binary, + int owns); +void* icalattachtype_get_binary(struct icalattachtype* v); + +struct icalgeotype +{ + float lat; + float lon; +}; + + +struct icaldatetimeperiodtype +{ + struct icaltimetype time; + struct icalperiodtype period; +}; + + +struct icaltriggertype +{ + struct icaltimetype time; + struct icaldurationtype duration; +}; + +struct icaltriggertype icaltriggertype_from_string(const char* str); + +int icaltriggertype_is_null_trigger(struct icaltriggertype tr); + +/* struct icalreqstattype. This struct contains two string pointers, +but don't try to free either of them. The "desc" string is a pointer +to a static table inside the library. Don't try to free it. The +"debug" string is a pointer into the string that the called passed +into to icalreqstattype_from_string. Don't try to free it either, and +don't use it after the original string has been freed. + +BTW, you would get that original string from +*icalproperty_get_requeststatus() or icalvalue_get_text(), when +operating on a the value of a request_status property. */ + +struct icalreqstattype { + + icalrequeststatus code; + const char* desc; + const char* debug; +}; + +struct icalreqstattype icalreqstattype_from_string(const char* str); +const char* icalreqstattype_as_string(struct icalreqstattype); + + + +struct icaltimezonephase { + const char* tzname; + int is_stdandard; /* 1 = standard tme, 0 = daylight savings time */ + struct icaltimetype dtstart; + int offsetto; + int tzoffsetfrom; + const char* comment; + struct icaldatetimeperiodtype rdate; + const char* rrule; +}; + + +struct icaltimezonetype { + const char* tzid; + struct icaltimetype last_mod; + const char* tzurl; + + /* Array of phases. The end of the array is a phase with tzname == 0 */ + struct icaltimezonephase *phases; +}; + +void icaltimezonetype_free(struct icaltimezonetype tzt); + + +#endif /* !ICALTYPES_H */ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalrecur.h + CREATOR: eric 20 March 2000 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + +How to use: + +1) Get a rule and a start time from a component + icalproperty rrule; + struct icalrecurrencetype recur; + struct icaltimetype dtstart; + + rrule = icalcomponent_get_first_property(comp,ICAL_RRULE_PROPERTY); + recur = icalproperty_get_rrule(rrule); + start = icalproperty_get_dtstart(dtstart); + +Or, just make them up: + recur = icalrecurrencetype_from_string("FREQ=YEARLY;BYDAY=SU,WE"); + dtstart = icaltime_from_string("19970101T123000") + +2) Create an iterator + icalrecur_iterator* ritr; + ritr = icalrecur_iterator_new(recur,start); + +3) Iterator over the occurrences + struct icaltimetype next; + while (next = icalrecur_iterator_next(ritr) + && !icaltime_is_null_time(next){ + Do something with next + } + +Note that that the time returned by icalrecur_iterator_next is in +whatever timezone that dtstart is in. + +======================================================================*/ + +#ifndef ICALRECUR_H +#define ICALRECUR_H + +#include <time.h> + +/*********************************************************************** + * Recurrance enumerations +**********************************************************************/ + +typedef enum icalrecurrencetype_frequency +{ + /* These enums are used to index an array, so don't change the + order or the integers */ + + ICAL_SECONDLY_RECURRENCE=0, + ICAL_MINUTELY_RECURRENCE=1, + ICAL_HOURLY_RECURRENCE=2, + ICAL_DAILY_RECURRENCE=3, + ICAL_WEEKLY_RECURRENCE=4, + ICAL_MONTHLY_RECURRENCE=5, + ICAL_YEARLY_RECURRENCE=6, + ICAL_NO_RECURRENCE=7 + +} icalrecurrencetype_frequency; + +typedef enum icalrecurrencetype_weekday +{ + ICAL_NO_WEEKDAY, + ICAL_SUNDAY_WEEKDAY, + ICAL_MONDAY_WEEKDAY, + ICAL_TUESDAY_WEEKDAY, + ICAL_WEDNESDAY_WEEKDAY, + ICAL_THURSDAY_WEEKDAY, + ICAL_FRIDAY_WEEKDAY, + ICAL_SATURDAY_WEEKDAY +} icalrecurrencetype_weekday; + +enum { + ICAL_RECURRENCE_ARRAY_MAX = 0x7f7f, + ICAL_RECURRENCE_ARRAY_MAX_BYTE = 0x7f +}; + + + +/********************** Recurrence type routines **************/ + +/* See RFC 2445 Section 4.3.10, RECUR Value, for an explaination of + the values and fields in struct icalrecurrencetype */ + +#define ICAL_BY_SECOND_SIZE 61 +#define ICAL_BY_MINUTE_SIZE 61 +#define ICAL_BY_HOUR_SIZE 25 +#define ICAL_BY_DAY_SIZE 364 /* 7 days * 52 weeks */ +#define ICAL_BY_MONTHDAY_SIZE 32 +#define ICAL_BY_YEARDAY_SIZE 367 +#define ICAL_BY_WEEKNO_SIZE 54 +#define ICAL_BY_MONTH_SIZE 13 +#define ICAL_BY_SETPOS_SIZE 367 + +/* Main struct for holding digested recurrence rules */ +struct icalrecurrencetype +{ + icalrecurrencetype_frequency freq; + + + /* until and count are mutually exclusive. */ + struct icaltimetype until; + int count; + + short interval; + + icalrecurrencetype_weekday week_start; + + /* The BY* parameters can each take a list of values. Here I + * assume that the list of values will not be larger than the + * range of the value -- that is, the client will not name a + * value more than once. + + * Each of the lists is terminated with the value + * ICAL_RECURRENCE_ARRAY_MAX unless the the list is full. + */ + + short by_second[ICAL_BY_SECOND_SIZE]; + short by_minute[ICAL_BY_MINUTE_SIZE]; + short by_hour[ICAL_BY_HOUR_SIZE]; + short by_day[ICAL_BY_DAY_SIZE]; /* Encoded value, see below */ + short by_month_day[ICAL_BY_MONTHDAY_SIZE]; + short by_year_day[ ICAL_BY_YEARDAY_SIZE]; + short by_week_no[ICAL_BY_WEEKNO_SIZE]; + short by_month[ICAL_BY_MONTH_SIZE]; + short by_set_pos[ICAL_BY_SETPOS_SIZE]; +}; + + +void icalrecurrencetype_clear(struct icalrecurrencetype *r); + +/* The 'day' element of the by_day array is encoded to allow +representation of both the day of the week ( Monday, Tueday), but also +the Nth day of the week ( First tuesday of the month, last thursday of +the year) These routines decode the day values */ + +/* 1 == Monday, etc. */ +enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day); + +/* 0 == any of day of week. 1 == first, 2 = second, -2 == second to last, etc */ +short icalrecurrencetype_day_position(short day); + + +/*********************************************************************** + * Recurrance rule parser +**********************************************************************/ + +/* Convert between strings ans recurrencetype structures. */ +struct icalrecurrencetype icalrecurrencetype_from_string(const char* str); +char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur); + + +/********** recurrence iteration routines ********************/ + +typedef void icalrecur_iterator; + +/* Create a new recurrence rule iterator */ +icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, + struct icaltimetype dtstart); + +/* Get the next occurrence from an iterator */ +struct icaltimetype icalrecur_iterator_next(icalrecur_iterator*); + +/* Free the iterator */ +void icalrecur_iterator_free(icalrecur_iterator*); + +/* Fills array up with at most 'count' time_t values, each + representing an occurrence time in seconds past the POSIX epoch */ +int icalrecur_expand_recurrence(char* rule, time_t start, + int count, time_t* array); + + +#endif +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalvalue.h + + ======================================================================*/ + +#ifndef ICALDERIVEDVALUE_H +#define ICALDERIVEDVALUE_H + + +typedef void icalvalue; + + + +void icalvalue_set_x(icalvalue* value, const char* v); +icalvalue* icalvalue_new_x(const char* v); +const char* icalvalue_get_x(icalvalue* value); + +icalvalue* icalvalue_new_attach (struct icalattachtype* v); +void icalvalue_set_attach(icalvalue* value, struct icalattachtype* v); +struct icalattachtype* icalvalue_get_attach(icalvalue* value); + +icalvalue* icalvalue_new_recur (struct icalrecurrencetype v); +void icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v); +struct icalrecurrencetype icalvalue_get_recur(icalvalue* value); + +icalvalue* icalvalue_new_trigger (struct icaltriggertype v); +void icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v); +struct icaltriggertype icalvalue_get_trigger(icalvalue* value); + +icalvalue* icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v); +void icalvalue_set_datetimeperiod(icalvalue* value, struct icaldatetimeperiodtype v); +struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(icalvalue* value); + +void icalvalue_reset_kind(icalvalue* value); + +/* Everything below this line is machine generated. Do not edit. */ +typedef enum icalvalue_kind { + ICAL_ANY_VALUE=5000, + ICAL_QUERY_VALUE=5001, + ICAL_TRIGGER_VALUE=5002, + ICAL_STATUS_VALUE=5003, + ICAL_TRANSP_VALUE=5004, + ICAL_CLASS_VALUE=5005, + ICAL_DATE_VALUE=5006, + ICAL_STRING_VALUE=5007, + ICAL_INTEGER_VALUE=5008, + ICAL_PERIOD_VALUE=5009, + ICAL_TEXT_VALUE=5010, + ICAL_DURATION_VALUE=5011, + ICAL_BOOLEAN_VALUE=5012, + ICAL_URI_VALUE=5013, + ICAL_DATETIMEPERIOD_VALUE=5014, + ICAL_GEO_VALUE=5015, + ICAL_DATETIME_VALUE=5016, + ICAL_UTCOFFSET_VALUE=5017, + ICAL_ATTACH_VALUE=5018, + ICAL_ACTION_VALUE=5019, + ICAL_CALADDRESS_VALUE=5020, + ICAL_X_VALUE=5021, + ICAL_FLOAT_VALUE=5022, + ICAL_REQUESTSTATUS_VALUE=5023, + ICAL_METHOD_VALUE=5024, + ICAL_BINARY_VALUE=5025, + ICAL_RECUR_VALUE=5026, + ICAL_NO_VALUE=5027 +} icalvalue_kind ; + +#define ICALPROPERTY_FIRST_ENUM 10000 + +typedef enum icalproperty_action { + ICAL_ACTION_X = 10000, + ICAL_ACTION_AUDIO = 10001, + ICAL_ACTION_DISPLAY = 10002, + ICAL_ACTION_EMAIL = 10003, + ICAL_ACTION_PROCEDURE = 10004, + ICAL_ACTION_NONE = 10005 +} icalproperty_action; + +typedef enum icalproperty_class { + ICAL_CLASS_X = 10006, + ICAL_CLASS_PUBLIC = 10007, + ICAL_CLASS_PRIVATE = 10008, + ICAL_CLASS_CONFIDENTIAL = 10009, + ICAL_CLASS_NONE = 10010 +} icalproperty_class; + +typedef enum icalproperty_method { + ICAL_METHOD_X = 10011, + ICAL_METHOD_PUBLISH = 10012, + ICAL_METHOD_REQUEST = 10013, + ICAL_METHOD_REPLY = 10014, + ICAL_METHOD_ADD = 10015, + ICAL_METHOD_CANCEL = 10016, + ICAL_METHOD_REFRESH = 10017, + ICAL_METHOD_COUNTER = 10018, + ICAL_METHOD_DECLINECOUNTER = 10019, + ICAL_METHOD_CREATE = 10020, + ICAL_METHOD_READ = 10021, + ICAL_METHOD_RESPONSE = 10022, + ICAL_METHOD_MOVE = 10023, + ICAL_METHOD_MODIFY = 10024, + ICAL_METHOD_GENERATEUID = 10025, + ICAL_METHOD_DELETE = 10026, + ICAL_METHOD_NONE = 10027 +} icalproperty_method; + +typedef enum icalproperty_status { + ICAL_STATUS_X = 10028, + ICAL_STATUS_TENTATIVE = 10029, + ICAL_STATUS_CONFIRMED = 10030, + ICAL_STATUS_COMPLETED = 10031, + ICAL_STATUS_NEEDSACTION = 10032, + ICAL_STATUS_CANCELLED = 10033, + ICAL_STATUS_INPROCESS = 10034, + ICAL_STATUS_DRAFT = 10035, + ICAL_STATUS_FINAL = 10036, + ICAL_STATUS_NONE = 10037 +} icalproperty_status; + +typedef enum icalproperty_transp { + ICAL_TRANSP_X = 10038, + ICAL_TRANSP_OPAQUE = 10039, + ICAL_TRANSP_TRANSPARENT = 10040, + ICAL_TRANSP_NONE = 10041 +} icalproperty_transp; + +#define ICALPROPERTY_LAST_ENUM 10042 + + + /* QUERY */ +icalvalue* icalvalue_new_query(const char* v); +const char* icalvalue_get_query(icalvalue* value); +void icalvalue_set_query(icalvalue* value, const char* v); + + + /* STATUS */ +icalvalue* icalvalue_new_status(enum icalproperty_status v); +enum icalproperty_status icalvalue_get_status(icalvalue* value); +void icalvalue_set_status(icalvalue* value, enum icalproperty_status v); + + + /* TRANSP */ +icalvalue* icalvalue_new_transp(enum icalproperty_transp v); +enum icalproperty_transp icalvalue_get_transp(icalvalue* value); +void icalvalue_set_transp(icalvalue* value, enum icalproperty_transp v); + + + /* CLASS */ +icalvalue* icalvalue_new_class(enum icalproperty_class v); +enum icalproperty_class icalvalue_get_class(icalvalue* value); +void icalvalue_set_class(icalvalue* value, enum icalproperty_class v); + + + /* DATE */ +icalvalue* icalvalue_new_date(struct icaltimetype v); +struct icaltimetype icalvalue_get_date(icalvalue* value); +void icalvalue_set_date(icalvalue* value, struct icaltimetype v); + + + /* STRING */ +icalvalue* icalvalue_new_string(const char* v); +const char* icalvalue_get_string(icalvalue* value); +void icalvalue_set_string(icalvalue* value, const char* v); + + + /* INTEGER */ +icalvalue* icalvalue_new_integer(int v); +int icalvalue_get_integer(icalvalue* value); +void icalvalue_set_integer(icalvalue* value, int v); + + + /* PERIOD */ +icalvalue* icalvalue_new_period(struct icalperiodtype v); +struct icalperiodtype icalvalue_get_period(icalvalue* value); +void icalvalue_set_period(icalvalue* value, struct icalperiodtype v); + + + /* TEXT */ +icalvalue* icalvalue_new_text(const char* v); +const char* icalvalue_get_text(icalvalue* value); +void icalvalue_set_text(icalvalue* value, const char* v); + + + /* DURATION */ +icalvalue* icalvalue_new_duration(struct icaldurationtype v); +struct icaldurationtype icalvalue_get_duration(icalvalue* value); +void icalvalue_set_duration(icalvalue* value, struct icaldurationtype v); + + + /* BOOLEAN */ +icalvalue* icalvalue_new_boolean(int v); +int icalvalue_get_boolean(icalvalue* value); +void icalvalue_set_boolean(icalvalue* value, int v); + + + /* URI */ +icalvalue* icalvalue_new_uri(const char* v); +const char* icalvalue_get_uri(icalvalue* value); +void icalvalue_set_uri(icalvalue* value, const char* v); + + + /* GEO */ +icalvalue* icalvalue_new_geo(struct icalgeotype v); +struct icalgeotype icalvalue_get_geo(icalvalue* value); +void icalvalue_set_geo(icalvalue* value, struct icalgeotype v); + + + /* DATE-TIME */ +icalvalue* icalvalue_new_datetime(struct icaltimetype v); +struct icaltimetype icalvalue_get_datetime(icalvalue* value); +void icalvalue_set_datetime(icalvalue* value, struct icaltimetype v); + + + /* UTC-OFFSET */ +icalvalue* icalvalue_new_utcoffset(int v); +int icalvalue_get_utcoffset(icalvalue* value); +void icalvalue_set_utcoffset(icalvalue* value, int v); + + + /* ACTION */ +icalvalue* icalvalue_new_action(enum icalproperty_action v); +enum icalproperty_action icalvalue_get_action(icalvalue* value); +void icalvalue_set_action(icalvalue* value, enum icalproperty_action v); + + + /* CAL-ADDRESS */ +icalvalue* icalvalue_new_caladdress(const char* v); +const char* icalvalue_get_caladdress(icalvalue* value); +void icalvalue_set_caladdress(icalvalue* value, const char* v); + + + /* FLOAT */ +icalvalue* icalvalue_new_float(float v); +float icalvalue_get_float(icalvalue* value); +void icalvalue_set_float(icalvalue* value, float v); + + + /* REQUEST-STATUS */ +icalvalue* icalvalue_new_requeststatus(struct icalreqstattype v); +struct icalreqstattype icalvalue_get_requeststatus(icalvalue* value); +void icalvalue_set_requeststatus(icalvalue* value, struct icalreqstattype v); + + + /* METHOD */ +icalvalue* icalvalue_new_method(enum icalproperty_method v); +enum icalproperty_method icalvalue_get_method(icalvalue* value); +void icalvalue_set_method(icalvalue* value, enum icalproperty_method v); + + + /* BINARY */ +icalvalue* icalvalue_new_binary(const char* v); +const char* icalvalue_get_binary(icalvalue* value); +void icalvalue_set_binary(icalvalue* value, const char* v); + +#endif /*ICALVALUE_H*/ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalparam.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalparam.h + + ======================================================================*/ + +#ifndef ICALDERIVEDPARAMETER_H +#define ICALDERIVEDPARAMETER_H + + +typedef void icalparameter; + +const char* icalparameter_enum_to_string(int e); +int icalparameter_string_to_enum(const char* str); + +/* Everything below this line is machine generated. Do not edit. */ +typedef enum icalparameter_kind { + ICAL_ANY_PARAMETER = 0, + ICAL_ALTREP_PARAMETER, + ICAL_CN_PARAMETER, + ICAL_CUTYPE_PARAMETER, + ICAL_DELEGATEDFROM_PARAMETER, + ICAL_DELEGATEDTO_PARAMETER, + ICAL_DIR_PARAMETER, + ICAL_ENCODING_PARAMETER, + ICAL_FBTYPE_PARAMETER, + ICAL_FMTTYPE_PARAMETER, + ICAL_LANGUAGE_PARAMETER, + ICAL_MEMBER_PARAMETER, + ICAL_PARTSTAT_PARAMETER, + ICAL_RANGE_PARAMETER, + ICAL_RELATED_PARAMETER, + ICAL_RELTYPE_PARAMETER, + ICAL_ROLE_PARAMETER, + ICAL_RSVP_PARAMETER, + ICAL_SENTBY_PARAMETER, + ICAL_TZID_PARAMETER, + ICAL_VALUE_PARAMETER, + ICAL_X_PARAMETER, + ICAL_XLICCOMPARETYPE_PARAMETER, + ICAL_XLICERRORTYPE_PARAMETER, + ICAL_NO_PARAMETER +} icalparameter_kind; + +#define ICALPARAMETER_FIRST_ENUM 20000 + +typedef enum icalparameter_cutype { + ICAL_CUTYPE_X = 20000, + ICAL_CUTYPE_INDIVIDUAL = 20001, + ICAL_CUTYPE_GROUP = 20002, + ICAL_CUTYPE_RESOURCE = 20003, + ICAL_CUTYPE_ROOM = 20004, + ICAL_CUTYPE_UNKNOWN = 20005, + ICAL_CUTYPE_NONE = 20006 +} icalparameter_cutype; + +typedef enum icalparameter_encoding { + ICAL_ENCODING_X = 20007, + ICAL_ENCODING_8BIT = 20008, + ICAL_ENCODING_BASE64 = 20009, + ICAL_ENCODING_NONE = 20010 +} icalparameter_encoding; + +typedef enum icalparameter_fbtype { + ICAL_FBTYPE_X = 20011, + ICAL_FBTYPE_FREE = 20012, + ICAL_FBTYPE_BUSY = 20013, + ICAL_FBTYPE_BUSYUNAVAILABLE = 20014, + ICAL_FBTYPE_BUSYTENTATIVE = 20015, + ICAL_FBTYPE_NONE = 20016 +} icalparameter_fbtype; + +typedef enum icalparameter_partstat { + ICAL_PARTSTAT_X = 20017, + ICAL_PARTSTAT_NEEDSACTION = 20018, + ICAL_PARTSTAT_ACCEPTED = 20019, + ICAL_PARTSTAT_DECLINED = 20020, + ICAL_PARTSTAT_TENTATIVE = 20021, + ICAL_PARTSTAT_DELEGATED = 20022, + ICAL_PARTSTAT_COMPLETED = 20023, + ICAL_PARTSTAT_INPROCESS = 20024, + ICAL_PARTSTAT_NONE = 20025 +} icalparameter_partstat; + +typedef enum icalparameter_range { + ICAL_RANGE_X = 20026, + ICAL_RANGE_THISANDPRIOR = 20027, + ICAL_RANGE_THISANDFUTURE = 20028, + ICAL_RANGE_NONE = 20029 +} icalparameter_range; + +typedef enum icalparameter_related { + ICAL_RELATED_X = 20030, + ICAL_RELATED_START = 20031, + ICAL_RELATED_END = 20032, + ICAL_RELATED_NONE = 20033 +} icalparameter_related; + +typedef enum icalparameter_reltype { + ICAL_RELTYPE_X = 20034, + ICAL_RELTYPE_PARENT = 20035, + ICAL_RELTYPE_CHILD = 20036, + ICAL_RELTYPE_SIBLING = 20037, + ICAL_RELTYPE_NONE = 20038 +} icalparameter_reltype; + +typedef enum icalparameter_role { + ICAL_ROLE_X = 20039, + ICAL_ROLE_CHAIR = 20040, + ICAL_ROLE_REQPARTICIPANT = 20041, + ICAL_ROLE_OPTPARTICIPANT = 20042, + ICAL_ROLE_NONPARTICIPANT = 20043, + ICAL_ROLE_NONE = 20044 +} icalparameter_role; + +typedef enum icalparameter_rsvp { + ICAL_RSVP_X = 20045, + ICAL_RSVP_TRUE = 20046, + ICAL_RSVP_FALSE = 20047, + ICAL_RSVP_NONE = 20048 +} icalparameter_rsvp; + +typedef enum icalparameter_value { + ICAL_VALUE_X = 20049, + ICAL_VALUE_BINARY = 20050, + ICAL_VALUE_BOOLEAN = 20051, + ICAL_VALUE_DATE = 20052, + ICAL_VALUE_DURATION = 20053, + ICAL_VALUE_FLOAT = 20054, + ICAL_VALUE_INTEGER = 20055, + ICAL_VALUE_PERIOD = 20056, + ICAL_VALUE_RECUR = 20057, + ICAL_VALUE_TEXT = 20058, + ICAL_VALUE_URI = 20059, + ICAL_VALUE_ERROR = 20060, + ICAL_VALUE_DATETIME = 20061, + ICAL_VALUE_UTCOFFSET = 20062, + ICAL_VALUE_CALADDRESS = 20063, + ICAL_VALUE_NONE = 20064 +} icalparameter_value; + +typedef enum icalparameter_xliccomparetype { + ICAL_XLICCOMPARETYPE_X = 20065, + ICAL_XLICCOMPARETYPE_EQUAL = 20066, + ICAL_XLICCOMPARETYPE_NOTEQUAL = 20067, + ICAL_XLICCOMPARETYPE_LESS = 20068, + ICAL_XLICCOMPARETYPE_GREATER = 20069, + ICAL_XLICCOMPARETYPE_LESSEQUAL = 20070, + ICAL_XLICCOMPARETYPE_GREATEREQUAL = 20071, + ICAL_XLICCOMPARETYPE_REGEX = 20072, + ICAL_XLICCOMPARETYPE_NONE = 20073 +} icalparameter_xliccomparetype; + +typedef enum icalparameter_xlicerrortype { + ICAL_XLICERRORTYPE_X = 20074, + ICAL_XLICERRORTYPE_COMPONENTPARSEERROR = 20075, + ICAL_XLICERRORTYPE_PROPERTYPARSEERROR = 20076, + ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR = 20077, + ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR = 20078, + ICAL_XLICERRORTYPE_VALUEPARSEERROR = 20079, + ICAL_XLICERRORTYPE_INVALIDITIP = 20080, + ICAL_XLICERRORTYPE_UNKNOWNVCALPROPERROR = 20081, + ICAL_XLICERRORTYPE_MIMEPARSEERROR = 20082, + ICAL_XLICERRORTYPE_NONE = 20083 +} icalparameter_xlicerrortype; + +#define ICALPARAMETER_LAST_ENUM 20084 + +/* DELEGATED-FROM */ +icalparameter* icalparameter_new_delegatedfrom(const char* v); +const char* icalparameter_get_delegatedfrom(icalparameter* value); +void icalparameter_set_delegatedfrom(icalparameter* value, const char* v); + +/* DELEGATED-TO */ +icalparameter* icalparameter_new_delegatedto(const char* v); +const char* icalparameter_get_delegatedto(icalparameter* value); +void icalparameter_set_delegatedto(icalparameter* value, const char* v); + +/* RANGE */ +icalparameter* icalparameter_new_range(icalparameter_range v); +icalparameter_range icalparameter_get_range(icalparameter* value); +void icalparameter_set_range(icalparameter* value, icalparameter_range v); + +/* ENCODING */ +icalparameter* icalparameter_new_encoding(icalparameter_encoding v); +icalparameter_encoding icalparameter_get_encoding(icalparameter* value); +void icalparameter_set_encoding(icalparameter* value, icalparameter_encoding v); + +/* RSVP */ +icalparameter* icalparameter_new_rsvp(icalparameter_rsvp v); +icalparameter_rsvp icalparameter_get_rsvp(icalparameter* value); +void icalparameter_set_rsvp(icalparameter* value, icalparameter_rsvp v); + +/* PARTSTAT */ +icalparameter* icalparameter_new_partstat(icalparameter_partstat v); +icalparameter_partstat icalparameter_get_partstat(icalparameter* value); +void icalparameter_set_partstat(icalparameter* value, icalparameter_partstat v); + +/* RELTYPE */ +icalparameter* icalparameter_new_reltype(icalparameter_reltype v); +icalparameter_reltype icalparameter_get_reltype(icalparameter* value); +void icalparameter_set_reltype(icalparameter* value, icalparameter_reltype v); + +/* CUTYPE */ +icalparameter* icalparameter_new_cutype(icalparameter_cutype v); +icalparameter_cutype icalparameter_get_cutype(icalparameter* value); +void icalparameter_set_cutype(icalparameter* value, icalparameter_cutype v); + +/* MEMBER */ +icalparameter* icalparameter_new_member(const char* v); +const char* icalparameter_get_member(icalparameter* value); +void icalparameter_set_member(icalparameter* value, const char* v); + +/* FMTTYPE */ +icalparameter* icalparameter_new_fmttype(const char* v); +const char* icalparameter_get_fmttype(icalparameter* value); +void icalparameter_set_fmttype(icalparameter* value, const char* v); + +/* SENT-BY */ +icalparameter* icalparameter_new_sentby(const char* v); +const char* icalparameter_get_sentby(icalparameter* value); +void icalparameter_set_sentby(icalparameter* value, const char* v); + +/* VALUE */ +icalparameter* icalparameter_new_value(icalparameter_value v); +icalparameter_value icalparameter_get_value(icalparameter* value); +void icalparameter_set_value(icalparameter* value, icalparameter_value v); + +/* ALTREP */ +icalparameter* icalparameter_new_altrep(const char* v); +const char* icalparameter_get_altrep(icalparameter* value); +void icalparameter_set_altrep(icalparameter* value, const char* v); + +/* DIR */ +icalparameter* icalparameter_new_dir(const char* v); +const char* icalparameter_get_dir(icalparameter* value); +void icalparameter_set_dir(icalparameter* value, const char* v); + +/* RELATED */ +icalparameter* icalparameter_new_related(icalparameter_related v); +icalparameter_related icalparameter_get_related(icalparameter* value); +void icalparameter_set_related(icalparameter* value, icalparameter_related v); + +/* CN */ +icalparameter* icalparameter_new_cn(const char* v); +const char* icalparameter_get_cn(icalparameter* value); +void icalparameter_set_cn(icalparameter* value, const char* v); + +/* X-LIC-ERRORTYPE */ +icalparameter* icalparameter_new_xlicerrortype(icalparameter_xlicerrortype v); +icalparameter_xlicerrortype icalparameter_get_xlicerrortype(icalparameter* value); +void icalparameter_set_xlicerrortype(icalparameter* value, icalparameter_xlicerrortype v); + +/* X */ +icalparameter* icalparameter_new_x(const char* v); +const char* icalparameter_get_x(icalparameter* value); +void icalparameter_set_x(icalparameter* value, const char* v); + +/* LANGUAGE */ +icalparameter* icalparameter_new_language(const char* v); +const char* icalparameter_get_language(icalparameter* value); +void icalparameter_set_language(icalparameter* value, const char* v); + +/* ROLE */ +icalparameter* icalparameter_new_role(icalparameter_role v); +icalparameter_role icalparameter_get_role(icalparameter* value); +void icalparameter_set_role(icalparameter* value, icalparameter_role v); + +/* X-LIC-COMPARETYPE */ +icalparameter* icalparameter_new_xliccomparetype(icalparameter_xliccomparetype v); +icalparameter_xliccomparetype icalparameter_get_xliccomparetype(icalparameter* value); +void icalparameter_set_xliccomparetype(icalparameter* value, icalparameter_xliccomparetype v); + +/* FBTYPE */ +icalparameter* icalparameter_new_fbtype(icalparameter_fbtype v); +icalparameter_fbtype icalparameter_get_fbtype(icalparameter* value); +void icalparameter_set_fbtype(icalparameter* value, icalparameter_fbtype v); + +/* TZID */ +icalparameter* icalparameter_new_tzid(const char* v); +const char* icalparameter_get_tzid(icalparameter* value); +void icalparameter_set_tzid(icalparameter* value, const char* v); + +#endif /*ICALPARAMETER_H*/ + +/* -*- Mode: C -*- + ====================================================================== + FILE: icalderivedproperties.{c,h} + CREATOR: eric 09 May 1999 + + $Id$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + ======================================================================*/ + + +#ifndef ICALDERIVEDPROPERTY_H +#define ICALDERIVEDPROPERTY_H + +#include <time.h> + +typedef void icalproperty; + + +/* Everything below this line is machine generated. Do not edit. */ +typedef enum icalproperty_kind { + ICAL_ANY_PROPERTY = 0, + ICAL_ACTION_PROPERTY, + ICAL_ATTACH_PROPERTY, + ICAL_ATTENDEE_PROPERTY, + ICAL_CALSCALE_PROPERTY, + ICAL_CATEGORIES_PROPERTY, + ICAL_CLASS_PROPERTY, + ICAL_COMMENT_PROPERTY, + ICAL_COMPLETED_PROPERTY, + ICAL_CONTACT_PROPERTY, + ICAL_CREATED_PROPERTY, + ICAL_DESCRIPTION_PROPERTY, + ICAL_DTEND_PROPERTY, + ICAL_DTSTAMP_PROPERTY, + ICAL_DTSTART_PROPERTY, + ICAL_DUE_PROPERTY, + ICAL_DURATION_PROPERTY, + ICAL_EXDATE_PROPERTY, + ICAL_EXRULE_PROPERTY, + ICAL_FREEBUSY_PROPERTY, + ICAL_GEO_PROPERTY, + ICAL_LASTMODIFIED_PROPERTY, + ICAL_LOCATION_PROPERTY, + ICAL_MAXRESULTS_PROPERTY, + ICAL_MAXRESULTSSIZE_PROPERTY, + ICAL_METHOD_PROPERTY, + ICAL_ORGANIZER_PROPERTY, + ICAL_PERCENTCOMPLETE_PROPERTY, + ICAL_PRIORITY_PROPERTY, + ICAL_PRODID_PROPERTY, + ICAL_QUERY_PROPERTY, + ICAL_QUERYNAME_PROPERTY, + ICAL_RDATE_PROPERTY, + ICAL_RECURRENCEID_PROPERTY, + ICAL_RELATEDTO_PROPERTY, + ICAL_REPEAT_PROPERTY, + ICAL_REQUESTSTATUS_PROPERTY, + ICAL_RESOURCES_PROPERTY, + ICAL_RRULE_PROPERTY, + ICAL_SCOPE_PROPERTY, + ICAL_SEQUENCE_PROPERTY, + ICAL_STATUS_PROPERTY, + ICAL_SUMMARY_PROPERTY, + ICAL_TARGET_PROPERTY, + ICAL_TRANSP_PROPERTY, + ICAL_TRIGGER_PROPERTY, + ICAL_TZID_PROPERTY, + ICAL_TZNAME_PROPERTY, + ICAL_TZOFFSETFROM_PROPERTY, + ICAL_TZOFFSETTO_PROPERTY, + ICAL_TZURL_PROPERTY, + ICAL_UID_PROPERTY, + ICAL_URL_PROPERTY, + ICAL_VERSION_PROPERTY, + ICAL_X_PROPERTY, + ICAL_XLICCLUSTERCOUNT_PROPERTY, + ICAL_XLICERROR_PROPERTY, + ICAL_XLICMIMECHARSET_PROPERTY, + ICAL_XLICMIMECID_PROPERTY, + ICAL_XLICMIMECONTENTTYPE_PROPERTY, + ICAL_XLICMIMEENCODING_PROPERTY, + ICAL_XLICMIMEFILENAME_PROPERTY, + ICAL_XLICMIMEOPTINFO_PROPERTY, + ICAL_NO_PROPERTY +} icalproperty_kind; + +icalproperty* icalproperty_vanew_action(enum icalproperty_action v, ...); + +/* ACTION */ +icalproperty* icalproperty_new_action(enum icalproperty_action v); +void icalproperty_set_action(icalproperty* prop, enum icalproperty_action v); +enum icalproperty_action icalproperty_get_action(icalproperty* prop);icalproperty* icalproperty_vanew_attach(struct icalattachtype* v, ...); + +/* ATTACH */ +icalproperty* icalproperty_new_attach(struct icalattachtype* v); +void icalproperty_set_attach(icalproperty* prop, struct icalattachtype* v); +struct icalattachtype* icalproperty_get_attach(icalproperty* prop);icalproperty* icalproperty_vanew_attendee(const char* v, ...); + +/* ATTENDEE */ +icalproperty* icalproperty_new_attendee(const char* v); +void icalproperty_set_attendee(icalproperty* prop, const char* v); +const char* icalproperty_get_attendee(icalproperty* prop);icalproperty* icalproperty_vanew_calscale(const char* v, ...); + +/* CALSCALE */ +icalproperty* icalproperty_new_calscale(const char* v); +void icalproperty_set_calscale(icalproperty* prop, const char* v); +const char* icalproperty_get_calscale(icalproperty* prop);icalproperty* icalproperty_vanew_categories(const char* v, ...); + +/* CATEGORIES */ +icalproperty* icalproperty_new_categories(const char* v); +void icalproperty_set_categories(icalproperty* prop, const char* v); +const char* icalproperty_get_categories(icalproperty* prop);icalproperty* icalproperty_vanew_class(const char* v, ...); + +/* CLASS */ +icalproperty* icalproperty_new_class(const char* v); +void icalproperty_set_class(icalproperty* prop, const char* v); +const char* icalproperty_get_class(icalproperty* prop);icalproperty* icalproperty_vanew_comment(const char* v, ...); + +/* COMMENT */ +icalproperty* icalproperty_new_comment(const char* v); +void icalproperty_set_comment(icalproperty* prop, const char* v); +const char* icalproperty_get_comment(icalproperty* prop);icalproperty* icalproperty_vanew_completed(struct icaltimetype v, ...); + +/* COMPLETED */ +icalproperty* icalproperty_new_completed(struct icaltimetype v); +void icalproperty_set_completed(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_completed(icalproperty* prop);icalproperty* icalproperty_vanew_contact(const char* v, ...); + +/* CONTACT */ +icalproperty* icalproperty_new_contact(const char* v); +void icalproperty_set_contact(icalproperty* prop, const char* v); +const char* icalproperty_get_contact(icalproperty* prop);icalproperty* icalproperty_vanew_created(struct icaltimetype v, ...); + +/* CREATED */ +icalproperty* icalproperty_new_created(struct icaltimetype v); +void icalproperty_set_created(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_created(icalproperty* prop);icalproperty* icalproperty_vanew_description(const char* v, ...); + +/* DESCRIPTION */ +icalproperty* icalproperty_new_description(const char* v); +void icalproperty_set_description(icalproperty* prop, const char* v); +const char* icalproperty_get_description(icalproperty* prop);icalproperty* icalproperty_vanew_dtend(struct icaltimetype v, ...); + +/* DTEND */ +icalproperty* icalproperty_new_dtend(struct icaltimetype v); +void icalproperty_set_dtend(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_dtend(icalproperty* prop);icalproperty* icalproperty_vanew_dtstamp(struct icaltimetype v, ...); + +/* DTSTAMP */ +icalproperty* icalproperty_new_dtstamp(struct icaltimetype v); +void icalproperty_set_dtstamp(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_dtstamp(icalproperty* prop);icalproperty* icalproperty_vanew_dtstart(struct icaltimetype v, ...); + +/* DTSTART */ +icalproperty* icalproperty_new_dtstart(struct icaltimetype v); +void icalproperty_set_dtstart(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_dtstart(icalproperty* prop);icalproperty* icalproperty_vanew_due(struct icaltimetype v, ...); + +/* DUE */ +icalproperty* icalproperty_new_due(struct icaltimetype v); +void icalproperty_set_due(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_due(icalproperty* prop);icalproperty* icalproperty_vanew_duration(struct icaldurationtype v, ...); + +/* DURATION */ +icalproperty* icalproperty_new_duration(struct icaldurationtype v); +void icalproperty_set_duration(icalproperty* prop, struct icaldurationtype v); +struct icaldurationtype icalproperty_get_duration(icalproperty* prop);icalproperty* icalproperty_vanew_exdate(struct icaltimetype v, ...); + +/* EXDATE */ +icalproperty* icalproperty_new_exdate(struct icaltimetype v); +void icalproperty_set_exdate(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_exdate(icalproperty* prop);icalproperty* icalproperty_vanew_exrule(struct icalrecurrencetype v, ...); + +/* EXRULE */ +icalproperty* icalproperty_new_exrule(struct icalrecurrencetype v); +void icalproperty_set_exrule(icalproperty* prop, struct icalrecurrencetype v); +struct icalrecurrencetype icalproperty_get_exrule(icalproperty* prop);icalproperty* icalproperty_vanew_freebusy(struct icalperiodtype v, ...); + +/* FREEBUSY */ +icalproperty* icalproperty_new_freebusy(struct icalperiodtype v); +void icalproperty_set_freebusy(icalproperty* prop, struct icalperiodtype v); +struct icalperiodtype icalproperty_get_freebusy(icalproperty* prop);icalproperty* icalproperty_vanew_geo(struct icalgeotype v, ...); + +/* GEO */ +icalproperty* icalproperty_new_geo(struct icalgeotype v); +void icalproperty_set_geo(icalproperty* prop, struct icalgeotype v); +struct icalgeotype icalproperty_get_geo(icalproperty* prop);icalproperty* icalproperty_vanew_lastmodified(struct icaltimetype v, ...); + +/* LAST-MODIFIED */ +icalproperty* icalproperty_new_lastmodified(struct icaltimetype v); +void icalproperty_set_lastmodified(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_lastmodified(icalproperty* prop);icalproperty* icalproperty_vanew_location(const char* v, ...); + +/* LOCATION */ +icalproperty* icalproperty_new_location(const char* v); +void icalproperty_set_location(icalproperty* prop, const char* v); +const char* icalproperty_get_location(icalproperty* prop);icalproperty* icalproperty_vanew_maxresults(int v, ...); + +/* MAXRESULTS */ +icalproperty* icalproperty_new_maxresults(int v); +void icalproperty_set_maxresults(icalproperty* prop, int v); +int icalproperty_get_maxresults(icalproperty* prop);icalproperty* icalproperty_vanew_maxresultssize(int v, ...); + +/* MAXRESULTSSIZE */ +icalproperty* icalproperty_new_maxresultssize(int v); +void icalproperty_set_maxresultssize(icalproperty* prop, int v); +int icalproperty_get_maxresultssize(icalproperty* prop);icalproperty* icalproperty_vanew_method(enum icalproperty_method v, ...); + +/* METHOD */ +icalproperty* icalproperty_new_method(enum icalproperty_method v); +void icalproperty_set_method(icalproperty* prop, enum icalproperty_method v); +enum icalproperty_method icalproperty_get_method(icalproperty* prop);icalproperty* icalproperty_vanew_organizer(const char* v, ...); + +/* ORGANIZER */ +icalproperty* icalproperty_new_organizer(const char* v); +void icalproperty_set_organizer(icalproperty* prop, const char* v); +const char* icalproperty_get_organizer(icalproperty* prop);icalproperty* icalproperty_vanew_percentcomplete(int v, ...); + +/* PERCENT-COMPLETE */ +icalproperty* icalproperty_new_percentcomplete(int v); +void icalproperty_set_percentcomplete(icalproperty* prop, int v); +int icalproperty_get_percentcomplete(icalproperty* prop);icalproperty* icalproperty_vanew_priority(int v, ...); + +/* PRIORITY */ +icalproperty* icalproperty_new_priority(int v); +void icalproperty_set_priority(icalproperty* prop, int v); +int icalproperty_get_priority(icalproperty* prop);icalproperty* icalproperty_vanew_prodid(const char* v, ...); + +/* PRODID */ +icalproperty* icalproperty_new_prodid(const char* v); +void icalproperty_set_prodid(icalproperty* prop, const char* v); +const char* icalproperty_get_prodid(icalproperty* prop);icalproperty* icalproperty_vanew_query(const char* v, ...); + +/* QUERY */ +icalproperty* icalproperty_new_query(const char* v); +void icalproperty_set_query(icalproperty* prop, const char* v); +const char* icalproperty_get_query(icalproperty* prop);icalproperty* icalproperty_vanew_queryname(const char* v, ...); + +/* QUERYNAME */ +icalproperty* icalproperty_new_queryname(const char* v); +void icalproperty_set_queryname(icalproperty* prop, const char* v); +const char* icalproperty_get_queryname(icalproperty* prop);icalproperty* icalproperty_vanew_rdate(struct icaldatetimeperiodtype v, ...); + +/* RDATE */ +icalproperty* icalproperty_new_rdate(struct icaldatetimeperiodtype v); +void icalproperty_set_rdate(icalproperty* prop, struct icaldatetimeperiodtype v); +struct icaldatetimeperiodtype icalproperty_get_rdate(icalproperty* prop);icalproperty* icalproperty_vanew_recurrenceid(struct icaltimetype v, ...); + +/* RECURRENCE-ID */ +icalproperty* icalproperty_new_recurrenceid(struct icaltimetype v); +void icalproperty_set_recurrenceid(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_recurrenceid(icalproperty* prop);icalproperty* icalproperty_vanew_relatedto(const char* v, ...); + +/* RELATED-TO */ +icalproperty* icalproperty_new_relatedto(const char* v); +void icalproperty_set_relatedto(icalproperty* prop, const char* v); +const char* icalproperty_get_relatedto(icalproperty* prop);icalproperty* icalproperty_vanew_repeat(int v, ...); + +/* REPEAT */ +icalproperty* icalproperty_new_repeat(int v); +void icalproperty_set_repeat(icalproperty* prop, int v); +int icalproperty_get_repeat(icalproperty* prop);icalproperty* icalproperty_vanew_requeststatus(struct icalreqstattype v, ...); + +/* REQUEST-STATUS */ +icalproperty* icalproperty_new_requeststatus(struct icalreqstattype v); +void icalproperty_set_requeststatus(icalproperty* prop, struct icalreqstattype v); +struct icalreqstattype icalproperty_get_requeststatus(icalproperty* prop);icalproperty* icalproperty_vanew_resources(const char* v, ...); + +/* RESOURCES */ +icalproperty* icalproperty_new_resources(const char* v); +void icalproperty_set_resources(icalproperty* prop, const char* v); +const char* icalproperty_get_resources(icalproperty* prop);icalproperty* icalproperty_vanew_rrule(struct icalrecurrencetype v, ...); + +/* RRULE */ +icalproperty* icalproperty_new_rrule(struct icalrecurrencetype v); +void icalproperty_set_rrule(icalproperty* prop, struct icalrecurrencetype v); +struct icalrecurrencetype icalproperty_get_rrule(icalproperty* prop);icalproperty* icalproperty_vanew_scope(const char* v, ...); + +/* SCOPE */ +icalproperty* icalproperty_new_scope(const char* v); +void icalproperty_set_scope(icalproperty* prop, const char* v); +const char* icalproperty_get_scope(icalproperty* prop);icalproperty* icalproperty_vanew_sequence(int v, ...); + +/* SEQUENCE */ +icalproperty* icalproperty_new_sequence(int v); +void icalproperty_set_sequence(icalproperty* prop, int v); +int icalproperty_get_sequence(icalproperty* prop);icalproperty* icalproperty_vanew_status(enum icalproperty_status v, ...); + +/* STATUS */ +icalproperty* icalproperty_new_status(enum icalproperty_status v); +void icalproperty_set_status(icalproperty* prop, enum icalproperty_status v); +enum icalproperty_status icalproperty_get_status(icalproperty* prop);icalproperty* icalproperty_vanew_summary(const char* v, ...); + +/* SUMMARY */ +icalproperty* icalproperty_new_summary(const char* v); +void icalproperty_set_summary(icalproperty* prop, const char* v); +const char* icalproperty_get_summary(icalproperty* prop);icalproperty* icalproperty_vanew_target(const char* v, ...); + +/* TARGET */ +icalproperty* icalproperty_new_target(const char* v); +void icalproperty_set_target(icalproperty* prop, const char* v); +const char* icalproperty_get_target(icalproperty* prop);icalproperty* icalproperty_vanew_transp(const char* v, ...); + +/* TRANSP */ +icalproperty* icalproperty_new_transp(const char* v); +void icalproperty_set_transp(icalproperty* prop, const char* v); +const char* icalproperty_get_transp(icalproperty* prop);icalproperty* icalproperty_vanew_trigger(struct icaltriggertype v, ...); + +/* TRIGGER */ +icalproperty* icalproperty_new_trigger(struct icaltriggertype v); +void icalproperty_set_trigger(icalproperty* prop, struct icaltriggertype v); +struct icaltriggertype icalproperty_get_trigger(icalproperty* prop);icalproperty* icalproperty_vanew_tzid(const char* v, ...); + +/* TZID */ +icalproperty* icalproperty_new_tzid(const char* v); +void icalproperty_set_tzid(icalproperty* prop, const char* v); +const char* icalproperty_get_tzid(icalproperty* prop);icalproperty* icalproperty_vanew_tzname(const char* v, ...); + +/* TZNAME */ +icalproperty* icalproperty_new_tzname(const char* v); +void icalproperty_set_tzname(icalproperty* prop, const char* v); +const char* icalproperty_get_tzname(icalproperty* prop);icalproperty* icalproperty_vanew_tzoffsetfrom(int v, ...); + +/* TZOFFSETFROM */ +icalproperty* icalproperty_new_tzoffsetfrom(int v); +void icalproperty_set_tzoffsetfrom(icalproperty* prop, int v); +int icalproperty_get_tzoffsetfrom(icalproperty* prop);icalproperty* icalproperty_vanew_tzoffsetto(int v, ...); + +/* TZOFFSETTO */ +icalproperty* icalproperty_new_tzoffsetto(int v); +void icalproperty_set_tzoffsetto(icalproperty* prop, int v); +int icalproperty_get_tzoffsetto(icalproperty* prop);icalproperty* icalproperty_vanew_tzurl(const char* v, ...); + +/* TZURL */ +icalproperty* icalproperty_new_tzurl(const char* v); +void icalproperty_set_tzurl(icalproperty* prop, const char* v); +const char* icalproperty_get_tzurl(icalproperty* prop);icalproperty* icalproperty_vanew_uid(const char* v, ...); + +/* UID */ +icalproperty* icalproperty_new_uid(const char* v); +void icalproperty_set_uid(icalproperty* prop, const char* v); +const char* icalproperty_get_uid(icalproperty* prop);icalproperty* icalproperty_vanew_url(const char* v, ...); + +/* URL */ +icalproperty* icalproperty_new_url(const char* v); +void icalproperty_set_url(icalproperty* prop, const char* v); +const char* icalproperty_get_url(icalproperty* prop);icalproperty* icalproperty_vanew_version(const char* v, ...); + +/* VERSION */ +icalproperty* icalproperty_new_version(const char* v); +void icalproperty_set_version(icalproperty* prop, const char* v); +const char* icalproperty_get_version(icalproperty* prop);icalproperty* icalproperty_vanew_x(const char* v, ...); + +/* X */ +icalproperty* icalproperty_new_x(const char* v); +void icalproperty_set_x(icalproperty* prop, const char* v); +const char* icalproperty_get_x(icalproperty* prop);icalproperty* icalproperty_vanew_xlicclustercount(const char* v, ...); + +/* X-LIC-CLUSTERCOUNT */ +icalproperty* icalproperty_new_xlicclustercount(const char* v); +void icalproperty_set_xlicclustercount(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicclustercount(icalproperty* prop);icalproperty* icalproperty_vanew_xlicerror(const char* v, ...); + +/* X-LIC-ERROR */ +icalproperty* icalproperty_new_xlicerror(const char* v); +void icalproperty_set_xlicerror(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicerror(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimecharset(const char* v, ...); + +/* X-LIC-MIMECHARSET */ +icalproperty* icalproperty_new_xlicmimecharset(const char* v); +void icalproperty_set_xlicmimecharset(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimecharset(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimecid(const char* v, ...); + +/* X-LIC-MIMECID */ +icalproperty* icalproperty_new_xlicmimecid(const char* v); +void icalproperty_set_xlicmimecid(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimecid(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimecontenttype(const char* v, ...); + +/* X-LIC-MIMECONTENTTYPE */ +icalproperty* icalproperty_new_xlicmimecontenttype(const char* v); +void icalproperty_set_xlicmimecontenttype(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimecontenttype(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimeencoding(const char* v, ...); + +/* X-LIC-MIMEENCODING */ +icalproperty* icalproperty_new_xlicmimeencoding(const char* v); +void icalproperty_set_xlicmimeencoding(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimeencoding(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimefilename(const char* v, ...); + +/* X-LIC-MIMEFILENAME */ +icalproperty* icalproperty_new_xlicmimefilename(const char* v); +void icalproperty_set_xlicmimefilename(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimefilename(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimeoptinfo(const char* v, ...); + +/* X-LIC-MIMEOPTINFO */ +icalproperty* icalproperty_new_xlicmimeoptinfo(const char* v); +void icalproperty_set_xlicmimeoptinfo(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimeoptinfo(icalproperty* prop); + +#endif /*ICALPROPERTY_H*/ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalvalue.h + + ======================================================================*/ + +#ifndef ICALVALUE_H +#define ICALVALUE_H + +#include <time.h> + +/* Defined in icalderivedvalue.h */ +/*typedef void icalvalue;*/ + +icalvalue* icalvalue_new(icalvalue_kind kind); + +icalvalue* icalvalue_new_clone(icalvalue* value); + +icalvalue* icalvalue_new_from_string(icalvalue_kind kind, const char* str); + +void icalvalue_free(icalvalue* value); + +int icalvalue_is_valid(icalvalue* value); + +const char* icalvalue_as_ical_string(icalvalue* value); + +icalvalue_kind icalvalue_isa(icalvalue* value); + +int icalvalue_isa_value(void*); + +icalparameter_xliccomparetype icalvalue_compare(icalvalue* a, icalvalue *b); + + +/* Special, non autogenerated value accessors */ + +icalvalue* icalvalue_new_recur (struct icalrecurrencetype v); +void icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v); +struct icalrecurrencetype icalvalue_get_recur(icalvalue* value); + +icalvalue* icalvalue_new_trigger (struct icaltriggertype v); +void icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v); +struct icaltriggertype icalvalue_get_trigger(icalvalue* value); + +icalvalue* icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v); +void icalvalue_set_datetimeperiod(icalvalue* value, + struct icaldatetimeperiodtype v); +struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(icalvalue* value); + +/* Convert enumerations */ + +icalvalue_kind icalvalue_string_to_kind(const char* str); +const char* icalvalue_kind_to_string(icalvalue_kind kind); + + +#endif /*ICALVALUE_H*/ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalparam.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalparam.h + + ======================================================================*/ + +#ifndef ICALPARAM_H +#define ICALPARAM_H + + +/* Declared in icalderivedparameter.h */ +/*typedef void icalparameter;*/ + +icalparameter* icalparameter_new(icalparameter_kind kind); +icalparameter* icalparameter_new_clone(icalparameter* p); + +/* Create from string of form "PARAMNAME=VALUE" */ +icalparameter* icalparameter_new_from_string(const char* value); + +/* Create from just the value, the part after the "=" */ +icalparameter* icalparameter_new_from_value_string(icalparameter_kind kind, const char* value); + +void icalparameter_free(icalparameter* parameter); + +char* icalparameter_as_ical_string(icalparameter* parameter); + +int icalparameter_is_valid(icalparameter* parameter); + +icalparameter_kind icalparameter_isa(icalparameter* parameter); + +int icalparameter_isa_parameter(void* param); + +/* Acess the name of an X parameer */ +void icalparameter_set_xname (icalparameter* param, const char* v); +const char* icalparameter_get_xname(icalparameter* param); +void icalparameter_set_xvalue (icalparameter* param, const char* v); +const char* icalparameter_get_xvalue(icalparameter* param); + +/* Convert enumerations */ + +const char* icalparameter_kind_to_string(icalparameter_kind kind); +icalparameter_kind icalparameter_string_to_kind(const char* string); + + + +#endif +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalproperty.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalparam.h + + ======================================================================*/ + + +#ifndef ICALPROPERTY_H +#define ICALPROPERTY_H + +#include <time.h> + + + + +/* Actually in icalderivedproperty.h: + typedef void icalproperty; */ + + +icalproperty* icalproperty_new(icalproperty_kind kind); + +icalproperty* icalproperty_new_clone(icalproperty * prop); + +icalproperty* icalproperty_new_from_string(const char* str); + +const char* icalproperty_as_ical_string(icalproperty* prop); + +void icalproperty_free(icalproperty* prop); + +icalproperty_kind icalproperty_isa(icalproperty* property); +int icalproperty_isa_property(void* property); + +void icalproperty_add_parameter(icalproperty* prop,icalparameter* parameter); +void icalproperty_set_parameter(icalproperty* prop,icalparameter* parameter); +void icalproperty_set_parameter_from_string(icalproperty* prop, + const char* name, const char* value); +const char* icalproperty_get_parameter_as_string(icalproperty* prop, + const char* name); + +void icalproperty_remove_parameter(icalproperty* prop, + icalparameter_kind kind); + +int icalproperty_count_parameters(icalproperty* prop); + +/* Iterate through the parameters */ +icalparameter* icalproperty_get_first_parameter(icalproperty* prop, + icalparameter_kind kind); +icalparameter* icalproperty_get_next_parameter(icalproperty* prop, + icalparameter_kind kind); +/* Access the value of the property */ +void icalproperty_set_value(icalproperty* prop, icalvalue* value); +void icalproperty_set_value_from_string(icalproperty* prop,const char* value, const char* kind); + +icalvalue* icalproperty_get_value(icalproperty* prop); +const char* icalproperty_get_value_as_string(icalproperty* prop); + +/* Deal with X properties */ + +void icalproperty_set_x_name(icalproperty* prop, const char* name); +const char* icalproperty_get_x_name(icalproperty* prop); + +/* Return the name of the property -- the type name converted to a + string, or the value of _get_x_name if the type is and X property */ +const char* icalproperty_get_name (icalproperty* prop); + +icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value); + +/* Convert kinds to string and get default value type */ + +icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind); +icalvalue_kind icalproperty_value_kind_to_kind(icalvalue_kind kind); +const char* icalproperty_kind_to_string(icalproperty_kind kind); +icalproperty_kind icalproperty_string_to_kind(const char* string); + +icalproperty_method icalproperty_string_to_method(const char* str); +const char* icalproperty_method_to_string(icalproperty_method method); + + +const char* icalproperty_enum_to_string(int e); +int icalproperty_string_to_enum(const char* str); + +const char* icalproperty_status_to_string(icalproperty_status); +icalproperty_status icalproperty_string_to_status(const char* string); + +int icalproperty_enum_belongs_to_property(icalproperty_kind kind, int e); + + + + +#endif /*ICALPROPERTY_H*/ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalattendee.h + CREATOR: eric 8 Mar 01 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icaltypes.h + +======================================================================*/ + +#ifndef ICALATTENDEE_H +#define ICALATTENDEE_H + +#include <time.h> + +struct icalorganizertype { + const char* value; + const char* common_name; + const char* dir; + const char* sentby; + const char* language; + +}; + +/* Create a copy of the given organizer. Libical will not own the + memory for the strings in the copy; the call must free them */ +struct icalorganizertype icalorganizertype_new_clone(struct icalorganizertype a); + + +struct icalattendeetype { + const char* cuid; /* Cal user id, contents of the property value */ + /*icalparameter_cutype cutype;*/ + const char* member; + /*icalparameter_role role;*/ + int rsvp; + const char* delto; + const char* delfrom; + const char* sentby; + const char* cn; + const char* dir; + const char* language; +}; + +/* Create a copy of the given attendee. Libical will not own the + memory for the strings in the copy; the call must free them */ +struct icalattendeetype icalattendeetype_new_clone(struct icalattendeetype a); + + +#endif /* !ICALATTENDEE_H */ +/*====================================================================== + FILE: pvl.h + CREATOR: eric November, 1995 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org +======================================================================*/ + + +#ifndef __PVL_H__ +#define __PVL_H__ + +typedef void* pvl_list; +typedef void* pvl_elem; + +/* + struct pvl_elem_t + + This type is private. Always use pvl_elem instead. The struct would + not even appear in this header except to make code in the USE_MACROS + blocks work + + */ +typedef struct pvl_elem_t +{ + int MAGIC; /* Magic Identifier */ + void *d; /* Pointer to data user is storing */ + struct pvl_elem_t *next; /* Next element */ + struct pvl_elem_t *prior; /* prior element */ +} pvl_elem_t; + + + +/* This global is incremented for each call to pvl_new_element(); it gives each + * list a unique identifer */ + +extern int pvl_elem_count; +extern int pvl_list_count; + +/* Create new lists or elements */ +pvl_elem pvl_new_element(void* d, pvl_elem next,pvl_elem prior); +pvl_list pvl_newlist(void); +void pvl_free(pvl_list); + +/* Add, remove, or get the head of the list */ +void pvl_unshift(pvl_list l,void *d); +void* pvl_shift(pvl_list l); +pvl_elem pvl_head(pvl_list); + +/* Add, remove or get the tail of the list */ +void pvl_push(pvl_list l,void *d); +void* pvl_pop(pvl_list l); +pvl_elem pvl_tail(pvl_list); + +/* Insert elements in random places */ +typedef int (*pvl_comparef)(void* a, void* b); /* a, b are of the data type*/ +void pvl_insert_ordered(pvl_list l,pvl_comparef f,void *d); +void pvl_insert_after(pvl_list l,pvl_elem e,void *d); +void pvl_insert_before(pvl_list l,pvl_elem e,void *d); + +/* Remove an element, or clear the entire list */ +void* pvl_remove(pvl_list,pvl_elem); /* Remove element, return data */ +void pvl_clear(pvl_list); /* Remove all elements, de-allocate all data */ + +int pvl_count(pvl_list); + +/* Navagate the list */ +pvl_elem pvl_next(pvl_elem e); +pvl_elem pvl_prior(pvl_elem e); + +/* get the data in the list */ +#ifndef PVL_USE_MACROS +void* pvl_data(pvl_elem); +#else +#define pvl_data(x) x==0 ? 0 : ((struct pvl_elem_t *)x)->d; +#endif + + +/* Find an element for which a function returns true */ +typedef int (*pvl_findf)(void* a, void* b); /*a is list elem, b is other data*/ +pvl_elem pvl_find(pvl_list l,pvl_findf f,void* v); +pvl_elem pvl_find_next(pvl_list l,pvl_findf f,void* v); + +/* Pass each element in the list to a function */ +typedef void (*pvl_applyf)(void* a, void* b); /*a is list elem, b is other data*/ +void pvl_apply(pvl_list l,pvl_applyf f, void *v); + + +#endif /* __PVL_H__ */ + + + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcomponent.h + CREATOR: eric 20 March 1999 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalcomponent.h + +======================================================================*/ + +#ifndef ICALCOMPONENT_H +#define ICALCOMPONENT_H + + +typedef void icalcomponent; + +/* This is exposed so that callers will not have to allocate and + deallocate iterators. Pretend that you can't see it. */ +typedef struct icalcompiter +{ + icalcomponent_kind kind; + pvl_elem iter; + +} icalcompiter; + +icalcomponent* icalcomponent_new(icalcomponent_kind kind); +icalcomponent* icalcomponent_new_clone(icalcomponent* component); +icalcomponent* icalcomponent_new_from_string(char* str); +icalcomponent* icalcomponent_vanew(icalcomponent_kind kind, ...); +void icalcomponent_free(icalcomponent* component); + +char* icalcomponent_as_ical_string(icalcomponent* component); + +int icalcomponent_is_valid(icalcomponent* component); + +icalcomponent_kind icalcomponent_isa(icalcomponent* component); + +int icalcomponent_isa_component (void* component); + +/* + * Working with properties + */ + +void icalcomponent_add_property(icalcomponent* component, + icalproperty* property); + +void icalcomponent_remove_property(icalcomponent* component, + icalproperty* property); + +int icalcomponent_count_properties(icalcomponent* component, + icalproperty_kind kind); + +/* Iterate through the properties */ +icalproperty* icalcomponent_get_current_property(icalcomponent* component); + +icalproperty* icalcomponent_get_first_property(icalcomponent* component, + icalproperty_kind kind); +icalproperty* icalcomponent_get_next_property(icalcomponent* component, + icalproperty_kind kind); + + +/* + * Working with components + */ + + +/* Return the first VEVENT, VTODO or VJOURNAL sub-component of cop, or + comp if it is one of those types */ + +icalcomponent* icalcomponent_get_inner(icalcomponent* comp); + + +void icalcomponent_add_component(icalcomponent* parent, + icalcomponent* child); + +void icalcomponent_remove_component(icalcomponent* parent, + icalcomponent* child); + +int icalcomponent_count_components(icalcomponent* component, + icalcomponent_kind kind); + +/* Iteration Routines. There are two forms of iterators, internal and +external. The internal ones came first, and are almost completely +sufficient, but they fail badly when you want to construct a loop that +removes components from the container.*/ + + +/* Iterate through components */ +icalcomponent* icalcomponent_get_current_component (icalcomponent* component); + +icalcomponent* icalcomponent_get_first_component(icalcomponent* component, + icalcomponent_kind kind); +icalcomponent* icalcomponent_get_next_component(icalcomponent* component, + icalcomponent_kind kind); + +/* Using external iterators */ +icalcompiter icalcomponent_begin_component(icalcomponent* component, + icalcomponent_kind kind); +icalcompiter icalcomponent_end_component(icalcomponent* component, + icalcomponent_kind kind); +icalcomponent* icalcompiter_next(icalcompiter* i); +icalcomponent* icalcompiter_prior(icalcompiter* i); +icalcomponent* icalcompiter_deref(icalcompiter* i); + + + + +/* Working with embedded error properties */ + +int icalcomponent_count_errors(icalcomponent* component); + +/* Remove all X-LIC-ERROR properties*/ +void icalcomponent_strip_errors(icalcomponent* component); + +/* Convert some X-LIC-ERROR properties into RETURN-STATUS properties*/ +void icalcomponent_convert_errors(icalcomponent* component); + +/* Internal operations. They are private, and you should not be using them. */ +icalcomponent* icalcomponent_get_parent(icalcomponent* component); +void icalcomponent_set_parent(icalcomponent* component, + icalcomponent* parent); + +/* Kind conversion routiens */ + +icalcomponent_kind icalcomponent_string_to_kind(const char* string); + +const char* icalcomponent_kind_to_string(icalcomponent_kind kind); + + +/************* Derived class methods. **************************** + +If the code was in an OO language, the remaining routines would be +members of classes derived from icalcomponent. Don't call them on the +wrong component subtypes. */ + +/* For VCOMPONENT: Return a reference to the first VEVENT, VTODO or + VJOURNAL */ +icalcomponent* icalcomponent_get_first_real_component(icalcomponent *c); + +/* For VEVENT, VTODO, VJOURNAL and VTIMEZONE: report the start and end + times of an event in UTC */ +struct icaltime_span icalcomponent_get_span(icalcomponent* comp); + +/******************** Convienience routines **********************/ + +void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v); +struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp); + +/* For the icalcomponent routines only, dtend and duration are tied + together. If you call the set routine for one and the other exists, + the routine will calculate the change to the other. That is, if + there is a DTEND and you call set_duration, the routine will modify + DTEND to be the sum of DTSTART and the duration. If you call a get + routine for one and the other exists, the routine will calculate + the return value. If you call a set routine and neither exists, the + routine will create the apcompriate comperty */ + + +struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp); +void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v); + +void icalcomponent_set_duration(icalcomponent* comp, + struct icaldurationtype v); +struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp); + +void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method); +icalproperty_method icalcomponent_get_method(icalcomponent* comp); + +struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp); +void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v); + + +void icalcomponent_set_summary(icalcomponent* comp, const char* v); +const char* icalcomponent_get_summary(icalcomponent* comp); + +void icalcomponent_set_comment(icalcomponent* comp, const char* v); +const char* icalcomponent_get_comment(icalcomponent* comp); + +void icalcomponent_set_uid(icalcomponent* comp, const char* v); +const char* icalcomponent_get_uid(icalcomponent* comp); + +void icalcomponent_set_recurrenceid(icalcomponent* comp, + struct icaltimetype v); +struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp); + + +void icalcomponent_set_organizer(icalcomponent* comp, + struct icalorganizertype org); + struct icalorganizertype icalcomponent_get_organizer(icalcomponent* comp); + + +void icalcomponent_add_attendee(icalcomponent *comp, + struct icalattendeetype attendee); + +int icalcomponent_remove_attendee(icalcomponent *comp, char* cuid); + +/* Get the Nth attendee. Out of range indices return an attendee + with cuid == 0 */ +struct icalattendeetype icalcomponent_get_attendee(icalcomponent *comp, + int index); + + + + +/*************** Type Specific routines ***************/ + +icalcomponent* icalcomponent_new_vcalendar(); +icalcomponent* icalcomponent_new_vevent(); +icalcomponent* icalcomponent_new_vtodo(); +icalcomponent* icalcomponent_new_vjournal(); +icalcomponent* icalcomponent_new_valarm(); +icalcomponent* icalcomponent_new_vfreebusy(); +icalcomponent* icalcomponent_new_vtimezone(); +icalcomponent* icalcomponent_new_xstandard(); +icalcomponent* icalcomponent_new_xdaylight(); + + + +#endif /* !ICALCOMPONENT_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalparser.h + CREATOR: eric 20 April 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalparser.h + +======================================================================*/ + + +#ifndef ICALPARSER_H +#define ICALPARSER_H + + +#include <stdio.h> /* For FILE* */ + +typedef void* icalparser; + + +/*********************************************************************** + * Line-oriented parsing. + * + * Create a new parser via icalparse_new_parser, then add ines one at + * a time with icalparse_add_line(). icalparser_add_line() will return + * non-zero when it has finished with a component. + ***********************************************************************/ + +typedef enum icalparser_state { + ICALPARSER_ERROR, + ICALPARSER_SUCCESS, + ICALPARSER_BEGIN_COMP, + ICALPARSER_END_COMP, + ICALPARSER_IN_PROGRESS +} icalparser_state; + +icalparser* icalparser_new(void); +icalcomponent* icalparser_add_line(icalparser* parser, char* str ); +icalcomponent* icalparser_clean(icalparser* parser); +icalparser_state icalparser_get_state(icalparser* parser); +void icalparser_free(icalparser* parser); + + +/*********************************************************************** + * Message oriented parsing. icalparser_parse takes a string that + * holds the text ( in RFC 2445 format ) and returns a pointer to an + * icalcomponent. The caller owns the memory. line_gen_func is a + * pointer to a function that returns one content line per invocation + **********************************************************************/ + +icalcomponent* icalparser_parse(icalparser *parser, + char* (*line_gen_func)(char *s, size_t size, void *d)); + +/* Set the data that icalparser_parse will give to the line_gen_func + as the parameter 'd'*/ +void icalparser_set_gen_data(icalparser* parser, void* data); + + +icalcomponent* icalparser_parse_string(const char* str); + + +/*********************************************************************** + * Parser support functions + ***********************************************************************/ + +/* Use the flex/bison parser to turn a string into a value type */ +icalvalue* icalparser_parse_value(icalvalue_kind kind, + const char* str, icalcomponent** errors); + +/* Given a line generator function, return a single iCal content line.*/ +char* icalparser_get_line(icalparser* parser, char* (*line_gen_func)(char *s, size_t size, void *d)); + +char* string_line_generator(char *out, size_t buf_size, void *d); + +#endif /* !ICALPARSE_H */ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalmemory.h + CREATOR: eric 30 June 1999 + + + $Id$ + $Locker$ + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Initial Developer of the Original Code is Eric Busboom + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org +======================================================================*/ + +#ifndef ICALMEMORY_H +#define ICALMEMORY_H + +#include <sys/types.h> /* for size_t */ + + +/* Tmp buffers are managed by ical. References can be returned to the + caller, although the caller will not own the memory. */ + +void* icalmemory_tmp_buffer(size_t size); +char* icalmemory_tmp_copy(const char* str); + +/* Add an externally allocated buffer to the ring. */ +void icalmemory_add_tmp_buffer(void*); + + +/* Free all memory used in the ring */ +void icalmemory_free_ring(void); + +/* Non-tmp buffers must be freed. These are mostly wrappers around + * malloc, etc, but are used so the caller can change the memory + * allocators in a future version of the library */ + +void* icalmemory_new_buffer(size_t size); +void* icalmemory_resize_buffer(void* buf, size_t size); +void icalmemory_free_buffer(void* buf); + +/* icalmemory_append_string will copy the string 'string' to the + buffer 'buf' starting at position 'pos', reallocing 'buf' if it is + too small. 'buf_size' is the size of 'buf' and will be changed if + 'buf' is reallocated. 'pos' will point to the last byte of the new + string in 'buf', usually a '\0' */ + +/* THESE ROUTINES CAN NOT BE USED ON TMP BUFFERS. Only use them on + normally allocated memory, or on buffers created from + icalmemory_new_buffer, never with buffers created by + icalmemory_tmp_buffer. If icalmemory_append_string has to resize a + buffer on the ring, the ring will loose track of it an you will + have memory problems. */ + +void icalmemory_append_string(char** buf, char** pos, size_t* buf_size, + const char* string); + +/* icalmemory_append_char is similar, but is appends a character instead of a string */ +void icalmemory_append_char(char** buf, char** pos, size_t* buf_size, + char ch); + +/* A wrapper around strdup. Partly to trap calls to strdup, partly + because in -ansi, gcc on Red Hat claims that strudup is undeclared */ +char* icalmemory_strdup(const char *s); + +#endif /* !ICALMEMORY_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalerror.h + CREATOR: eric 09 May 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalerror.h + +======================================================================*/ + + +#ifndef ICALERROR_H +#define ICALERROR_H + +#include <assert.h> +#include <stdio.h> /* For icalerror_warn() */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define ICAL_SETERROR_ISFUNC + + +/* This routine is called before any error is triggered. It is called + by icalerror_set_errno, so it does not appear in all of the macros + below */ +void icalerror_stop_here(void); + +void icalerror_crash_here(void); + +typedef enum icalerrorenum { + + ICAL_BADARG_ERROR, + ICAL_NEWFAILED_ERROR, + ICAL_ALLOCATION_ERROR, + ICAL_MALFORMEDDATA_ERROR, + ICAL_PARSE_ERROR, + ICAL_INTERNAL_ERROR, /* Like assert --internal consist. prob */ + ICAL_FILE_ERROR, + ICAL_USAGE_ERROR, + ICAL_UNIMPLEMENTED_ERROR, + ICAL_UNKNOWN_ERROR, /* Used for problems in input to icalerror_strerror()*/ + ICAL_NO_ERROR + +} icalerrorenum; + +/* The libical error enumeration, like errno*/ +extern icalerrorenum icalerrno; + +/* If true, libicl aborts after a call to icalerror_set_error*/ +extern int icalerror_errors_are_fatal; + +/* Warning messages */ + +#ifdef __GNUC__ca +#define icalerror_warn(message) {fprintf(stderr,"%s(), %s:%d: %s\n",__FUNCTION__,__FILE__,__LINE__,message);} +#else /* __GNU_C__ */ +#define icalerror_warn(message) {fprintf(stderr,"%s:%d: %s\n",__FILE__,__LINE__,message);} +#endif /* __GNU_C__ */ + + +void icalerror_clear_errno(void); + +/* Make an individual error fatal or non-fatal. */ +typedef enum icalerrorstate { + ICAL_ERROR_FATAL, /* Not fata */ + ICAL_ERROR_NONFATAL, /* Fatal */ + ICAL_ERROR_DEFAULT, /* Use the value of icalerror_errors_are_fatal*/ + ICAL_ERROR_UNKNOWN /* Asked state for an unknown error type */ +} icalerrorstate ; + +char* icalerror_strerror(icalerrorenum e); +char* icalerror_perror(); +void icalerror_set_error_state( icalerrorenum error, icalerrorstate); +icalerrorstate icalerror_get_error_state( icalerrorenum error); + +#ifndef ICAL_SETERROR_ISFUNC +#define icalerror_set_errno(x) \ +icalerrno = x; \ +if(icalerror_get_error_state(x)==ICAL_ERROR_FATAL || \ + (icalerror_get_error_state(x)==ICAL_ERROR_DEFAULT && \ + icalerror_errors_are_fatal == 1 )){ \ + icalerror_warn(icalerror_strerror(x)); \ + assert(0); \ +} +#else +void icalerror_set_errno(icalerrorenum); +#endif + +#ifdef ICAL_ERRORS_ARE_FATAL +#undef NDEBUG +#endif + +#define icalerror_check_value_type(value,type); +#define icalerror_check_property_type(value,type); +#define icalerror_check_parameter_type(value,type); +#define icalerror_check_component_type(value,type); + +/* Assert with a message */ +#ifdef ICAL_ERRORS_ARE_FATAL + +#ifdef __GNUC__ +#define icalerror_assert(test,message) if(!(test)){fprintf(stderr,"%s(), %s:%d: %s\n",__FUNCTION__,__FILE__,__LINE__,message);icalerror_stop_here(); abort();} +#else /*__GNUC__*/ +#define icalerror_assert(test,message) if(!(test)){fprintf(stderr,"%s:%d: %s\n",__FILE__,__LINE__,message);icalerror_stop_here(); abort();} +#endif /*__GNUC__*/ + +#else /* ICAL_ERRORS_ARE_FATAL */ +#define icalerror_assert(test,message) +#endif /* ICAL_ERRORS_ARE_FATAL */ + +/* Check & abort if check fails */ +#define icalerror_check_arg(test,arg) if(!(test)) { icalerror_set_errno(ICAL_BADARG_ERROR); } + +/* Check & return void if check fails*/ +#define icalerror_check_arg_rv(test,arg) if(!(test)) {icalerror_set_errno(ICAL_BADARG_ERROR); return; } + +/* Check & return 0 if check fails*/ +#define icalerror_check_arg_rz(test,arg) if(!(test)) { icalerror_set_errno(ICAL_BADARG_ERROR); return 0;} + +/* Check & return an error if check fails*/ +#define icalerror_check_arg_re(test,arg,error) if(!(test)) { icalerror_stop_here(); assert(0); return error;} + +/* Check & return something*/ +#define icalerror_check_arg_rx(test,arg,x) if(!(test)) { icalerror_set_errno(ICAL_BADARG_ERROR); return x;} + + + +/* String interfaces to set an error to NONFATAL and restore it to its + original value */ + +icalerrorstate icalerror_supress(const char* error); +void icalerror_restore(const char* error, icalerrorstate es); + + +#endif /* !ICALERROR_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalrestriction.h + CREATOR: eric 24 April 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalrestriction.h + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + +======================================================================*/ + + +#ifndef ICALRESTRICTION_H +#define ICALRESTRICTION_H + +/* These must stay in this order for icalrestriction_compare to work */ +typedef enum icalrestriction_kind { + ICAL_RESTRICTION_NONE=0, /* 0 */ + ICAL_RESTRICTION_ZERO, /* 1 */ + ICAL_RESTRICTION_ONE, /* 2 */ + ICAL_RESTRICTION_ZEROPLUS, /* 3 */ + ICAL_RESTRICTION_ONEPLUS, /* 4 */ + ICAL_RESTRICTION_ZEROORONE, /* 5 */ + ICAL_RESTRICTION_ONEEXCLUSIVE, /* 6 */ + ICAL_RESTRICTION_ONEMUTUAL, /* 7 */ + ICAL_RESTRICTION_UNKNOWN /* 8 */ +} icalrestriction_kind; + +int +icalrestriction_compare(icalrestriction_kind restr, int count); + + +int +icalrestriction_is_parameter_allowed(icalproperty_kind property, + icalparameter_kind parameter); + +int icalrestriction_check(icalcomponent* comp); + + +#endif /* !ICALRESTRICTION_H */ + + + +/* -*- Mode: C -*- + ====================================================================== + FILE: sspm.h Mime Parser + CREATOR: eric 25 June 2000 + + $Id$ + $Locker$ + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Initial Developer of the Original Code is Eric Busboom + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + ======================================================================*/ + +#ifndef SSPM_H +#define SSPM_H + +enum sspm_major_type { + SSPM_NO_MAJOR_TYPE, + SSPM_TEXT_MAJOR_TYPE, + SSPM_IMAGE_MAJOR_TYPE, + SSPM_AUDIO_MAJOR_TYPE, + SSPM_VIDEO_MAJOR_TYPE, + SSPM_APPLICATION_MAJOR_TYPE, + SSPM_MULTIPART_MAJOR_TYPE, + SSPM_MESSAGE_MAJOR_TYPE, + SSPM_UNKNOWN_MAJOR_TYPE +}; + +enum sspm_minor_type { + SSPM_NO_MINOR_TYPE, + SSPM_ANY_MINOR_TYPE, + SSPM_PLAIN_MINOR_TYPE, + SSPM_RFC822_MINOR_TYPE, + SSPM_DIGEST_MINOR_TYPE, + SSPM_CALENDAR_MINOR_TYPE, + SSPM_MIXED_MINOR_TYPE, + SSPM_RELATED_MINOR_TYPE, + SSPM_ALTERNATIVE_MINOR_TYPE, + SSPM_PARALLEL_MINOR_TYPE, + SSPM_UNKNOWN_MINOR_TYPE +}; + +enum sspm_encoding { + SSPM_NO_ENCODING, + SSPM_QUOTED_PRINTABLE_ENCODING, + SSPM_8BIT_ENCODING, + SSPM_7BIT_ENCODING, + SSPM_BINARY_ENCODING, + SSPM_BASE64_ENCODING, + SSPM_UNKNOWN_ENCODING +}; + +enum sspm_error{ + SSPM_NO_ERROR, + SSPM_UNEXPECTED_BOUNDARY_ERROR, + SSPM_WRONG_BOUNDARY_ERROR, + SSPM_NO_BOUNDARY_ERROR, + SSPM_NO_HEADER_ERROR, + SSPM_MALFORMED_HEADER_ERROR +}; + + +struct sspm_header +{ + int def; + char* boundary; + enum sspm_major_type major; + enum sspm_minor_type minor; + char *minor_text; + char ** content_type_params; + char* charset; + enum sspm_encoding encoding; + char* filename; + char* content_id; + enum sspm_error error; + char* error_text; +}; + +struct sspm_part { + struct sspm_header header; + int level; + size_t data_size; + void *data; +}; + +struct sspm_action_map { + enum sspm_major_type major; + enum sspm_minor_type minor; + void* (*new_part)(); + void (*add_line)(void *part, struct sspm_header *header, + char* line, size_t size); + void* (*end_part)(void* part); + void (*free_part)(void *part); +}; + +char* sspm_major_type_string(enum sspm_major_type type); +char* sspm_minor_type_string(enum sspm_minor_type type); +char* sspm_encoding_string(enum sspm_encoding type); + +int sspm_parse_mime(struct sspm_part *parts, + size_t max_parts, + struct sspm_action_map *actions, + char* (*get_string)(char *s, size_t size, void* data), + void *get_string_data, + struct sspm_header *first_header + ); + +void sspm_free_parts(struct sspm_part *parts, size_t max_parts); + +char *decode_quoted_printable(char *dest, + char *src, + size_t *size); +char *decode_base64(char *dest, + char *src, + size_t *size); + + +int sspm_write_mime(struct sspm_part *parts,size_t num_parts, + char **output_string, char* header); + +#endif /*SSPM_H*/ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalmime.h + CREATOR: eric 26 July 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + +======================================================================*/ + +#ifndef ICALMIME_H +#define ICALMIME_H + + +icalcomponent* icalmime_parse( char* (*line_gen_func)(char *s, size_t size, + void *d), + void *data); + +/* The inverse of icalmime_parse, not implemented yet. Use sspm.h directly. */ +char* icalmime_as_mime_string(char* component); + + + +#endif /* !ICALMIME_H */ + + + +/* -*- Mode: C -*- + ====================================================================== + FILE: icallangbind.h + CREATOR: eric 25 jan 2001 + + DESCRIPTION: + + $Id$ + $Locker$ + + (C) COPYRIGHT 1999 Eric Busboom + http://www.softwarestudio.org + + This package is free software and is provided "as is" without + express or implied warranty. It may be used, redistributed and/or + modified under the same terms as perl itself. ( Either the Artistic + License or the GPL. ) + + ======================================================================*/ + +#ifndef __ICALLANGBIND_H__ +#define __ICALLANGBIND_H__ + +int* icallangbind_new_array(int size); +void icallangbind_free_array(int* array); +int icallangbind_access_array(int* array, int index); +icalproperty* icallangbind_get_property(icalcomponent *c, int n, const char* prop); +const char* icallangbind_get_property_val(icalproperty* p); +const char* icallangbind_get_parameter(icalproperty *p, const char* parameter); +icalcomponent* icallangbind_get_component(icalcomponent *c, const char* comp); + +icalproperty* icallangbind_get_first_property(icalcomponent *c, + const char* prop); + +icalproperty* icallangbind_get_next_property(icalcomponent *c, + const char* prop); + +icalcomponent* icallangbind_get_first_component(icalcomponent *c, + const char* comp); + +icalcomponent* icallangbind_get_next_component(icalcomponent *c, + const char* comp); + + +const char* icallangbind_property_eval_string(icalproperty* prop, char* sep); + + +int icallangbind_string_to_open_flag(const char* str); +#endif /*__ICALLANGBIND_H__*/ diff --git a/libical/src/libical/icalattendee.c b/libical/src/libical/icalattendee.c new file mode 100644 index 0000000..30cb949 --- a/dev/null +++ b/libical/src/libical/icalattendee.c @@ -0,0 +1,30 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalattendee.c + CREATOR: eric 08 Mar 01 + + $Id$ + $Locker$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icaltypes.c + + ======================================================================*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalattendee.h" diff --git a/libical/src/libical/icalattendee.h b/libical/src/libical/icalattendee.h new file mode 100644 index 0000000..914e51a --- a/dev/null +++ b/libical/src/libical/icalattendee.h @@ -0,0 +1,69 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalattendee.h + CREATOR: eric 8 Mar 01 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icaltypes.h + +======================================================================*/ + +#ifndef ICALATTENDEE_H +#define ICALATTENDEE_H + + +#include <time.h> +#include "icalenums.h" +#include "icaltime.h" +#include "icalduration.h" +#include "icalperiod.h" +#include "icalderivedparameter.h" +#include "icalderivedvalue.h" + +struct icalorganizertype { + const char* value; + const char* common_name; + const char* dir; + const char* sentby; + const char* language; + +}; + +/* Create a copy of the given organizer. Libical will not own the + memory for the strings in the copy; the call must free them */ +struct icalorganizertype icalorganizertype_new_clone(struct icalorganizertype a); + + +struct icalattendeetype { + const char* cuid; /* Cal user id, contents of the property value */ + /*icalparameter_cutype cutype;*/ + const char* member; + /*icalparameter_role role;*/ + int rsvp; + const char* delto; + const char* delfrom; + const char* sentby; + const char* cn; + const char* dir; + const char* language; +}; + +/* Create a copy of the given attendee. Libical will not own the + memory for the strings in the copy; the call must free them */ +struct icalattendeetype icalattendeetype_new_clone(struct icalattendeetype a); + + +#endif /* !ICALATTENDEE_H */ diff --git a/libical/src/libical/icalcomponent.c b/libical/src/libical/icalcomponent.c new file mode 100644 index 0000000..af0d3ec --- a/dev/null +++ b/libical/src/libical/icalcomponent.c @@ -0,0 +1,1488 @@ +/*====================================================================== + FILE: icalcomponent.c + CREATOR: eric 28 April 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalcomponent.c + +======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalcomponent.h" +#include "pvl.h" /* "Pointer-to-void list" */ +#include "icalerror.h" +#include "icalmemory.h" +#include "icalenums.h" +#include "icaltime.h" +#include "icalduration.h" +#include "icalperiod.h" +#include "icalparser.h" + +#include <stdlib.h> /* for malloc */ +#include <stdarg.h> /* for va_list, etc */ +#include <errno.h> +#include <assert.h> +#include <stdio.h> /* for fprintf */ +#include <string.h> + +#define MAX_TMP 1024 + +struct icalcomponent_impl +{ + char id[5]; + icalcomponent_kind kind; + char* x_name; + pvl_list properties; + pvl_elem property_iterator; + pvl_list components; + pvl_elem component_iterator; + icalcomponent* parent; +}; + +/* icalproperty functions that only components get to use */ +void icalproperty_set_parent(icalproperty* property, + icalcomponent* component); +icalcomponent* icalproperty_get_parent(icalproperty* property); +void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args); +icalcomponent* icalcomponent_new_impl (icalcomponent_kind kind); +int icalcomponent_property_sorter(void *a, void *b); + + +void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args) +{ + void* vp; + + while((vp = va_arg(args, void*)) != 0) { + + assert (icalcomponent_isa_component(vp) != 0 || + icalproperty_isa_property(vp) != 0 ) ; + + if (icalcomponent_isa_component(vp) != 0 ){ + + icalcomponent_add_component((icalcomponent*)impl, + (icalcomponent*)vp); + + } else if (icalproperty_isa_property(vp) != 0 ){ + + icalcomponent_add_property((icalcomponent*)impl, + (icalproperty*)vp); + } + } +} + +icalcomponent* +icalcomponent_new_impl (icalcomponent_kind kind) +{ + struct icalcomponent_impl* comp; + + if ( ( comp = (struct icalcomponent_impl*) + malloc(sizeof(struct icalcomponent_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + strcpy(comp->id,"comp"); + + comp->kind = kind; + comp->properties = pvl_newlist(); + comp->property_iterator = 0; + comp->components = pvl_newlist(); + comp->component_iterator = 0; + comp->x_name = 0; + comp->parent = 0; + + return comp; +} + +icalcomponent* +icalcomponent_new (icalcomponent_kind kind) +{ + return (icalcomponent*)icalcomponent_new_impl(kind); +} + +icalcomponent* +icalcomponent_vanew (icalcomponent_kind kind, ...) +{ + va_list args; + + struct icalcomponent_impl *impl = icalcomponent_new_impl(kind); + + if (impl == 0){ + return 0; + } + + va_start(args,kind); + icalcomponent_add_children(impl, args); + va_end(args); + + return (icalcomponent*) impl; +} + +icalcomponent* icalcomponent_new_from_string(char* str) +{ + return icalparser_parse_string(str); +} + +icalcomponent* icalcomponent_new_clone(icalcomponent* component) +{ + struct icalcomponent_impl *old = (struct icalcomponent_impl*)component; + struct icalcomponent_impl *new; + icalproperty *p; + icalcomponent *c; + pvl_elem itr; + + icalerror_check_arg_rz( (component!=0), "component"); + + new = icalcomponent_new_impl(old->kind); + + if (new == 0){ + return 0; + } + + + for( itr = pvl_head(old->properties); + itr != 0; + itr = pvl_next(itr)) + { + p = (icalproperty*)pvl_data(itr); + icalcomponent_add_property(new,icalproperty_new_clone(p)); + } + + + for( itr = pvl_head(old->components); + itr != 0; + itr = pvl_next(itr)) + { + c = (icalcomponent*)pvl_data(itr); + icalcomponent_add_component(new,icalcomponent_new_clone(c)); + } + + return new; + +} + + +void +icalcomponent_free (icalcomponent* component) +{ + icalproperty* prop; + icalcomponent* comp; + struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; + + icalerror_check_arg_rv( (component!=0), "component"); + +#ifdef ICAL_FREE_ON_LIST_IS_ERROR + icalerror_assert( (c->parent ==0),"Tried to free a component that is still attached to a parent component"); +#else + if(c->parent != 0){ + return; + } +#endif + + if(component != 0 ){ + + while( (prop=pvl_pop(c->properties)) != 0){ + assert(prop != 0); + icalproperty_set_parent(prop,0); + icalproperty_free(prop); + } + + pvl_free(c->properties); + + while( (comp=pvl_data(pvl_head(c->components))) != 0){ + assert(comp!=0); + icalcomponent_remove_component(component,comp); + icalcomponent_free(comp); + } + + pvl_free(c->components); + + if (c->x_name != 0) { + free(c->x_name); + } + + c->kind = ICAL_NO_COMPONENT; + c->properties = 0; + c->property_iterator = 0; + c->components = 0; + c->component_iterator = 0; + c->x_name = 0; + c->id[0] = 'X'; + + free(c); + } +} + +char* +icalcomponent_as_ical_string (icalcomponent* component) +{ + char* buf, *out_buf; + const char* tmp_buf; + size_t buf_size = 1024; + char* buf_ptr = 0; + pvl_elem itr; + struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; + +#ifdef ICAL_UNIX_NEWLINE + char newline[] = "\n"; +#else + char newline[] = "\n"; +#endif + icalcomponent *c; + icalproperty *p; + icalcomponent_kind kind = icalcomponent_isa(component); + + const char* kind_string; + + buf = icalmemory_new_buffer(buf_size); + buf_ptr = buf; + + icalerror_check_arg_rz( (component!=0), "component"); + icalerror_check_arg_rz( (kind!=ICAL_NO_COMPONENT), "component kind is ICAL_NO_COMPONENT"); + + kind_string = icalcomponent_kind_to_string(kind); + + icalerror_check_arg_rz( (kind_string!=0),"Unknown kind of component"); + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:"); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline); + + + for( itr = pvl_head(impl->properties); + itr != 0; + itr = pvl_next(itr)) + { + // printf("3333calcomponent_as_ical_string System Timezone2: %s %s \n", *tzname, getenv("TZ") ); + + p = (icalproperty*)pvl_data(itr); + + icalerror_assert((p!=0),"Got a null property"); + tmp_buf = icalproperty_as_ical_string(p); + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf); + } + + + for( itr = pvl_head(impl->components); + itr != 0; + itr = pvl_next(itr)) + { + + c = (icalcomponent*)pvl_data(itr); + + tmp_buf = icalcomponent_as_ical_string(c); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf); + + } + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:"); //tzset(); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, + icalcomponent_kind_to_string(kind)); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline); //tzset(); + + out_buf = icalmemory_tmp_copy(buf); + free(buf); + + return out_buf; +} + + +int +icalcomponent_is_valid (icalcomponent* component) +{ + struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component; + + + if ( (strcmp(impl->id,"comp") == 0) && + impl->kind != ICAL_NO_COMPONENT){ + return 1; + } else { + return 0; + } + +} + + +icalcomponent_kind +icalcomponent_isa (icalcomponent* component) +{ + struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component; + icalerror_check_arg_rz( (component!=0), "component"); + + if(component != 0) + { + return impl->kind; + } + + return ICAL_NO_COMPONENT; +} + + +int +icalcomponent_isa_component (void* component) +{ + struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component; + + icalerror_check_arg_rz( (component!=0), "component"); + + if (strcmp(impl->id,"comp") == 0) { + return 1; + } else { + return 0; + } + +} + +int icalcomponent_property_sorter(void *a, void *b) +{ + icalproperty_kind kinda, kindb; + const char *ksa, *ksb; + + kinda = icalproperty_isa((icalproperty*)a); + kindb = icalproperty_isa((icalproperty*)b); + + ksa = icalproperty_kind_to_string(kinda); + ksb = icalproperty_kind_to_string(kindb); + + return strcmp(ksa,ksb); +} + + +void +icalcomponent_add_property (icalcomponent* component, icalproperty* property) +{ + struct icalcomponent_impl *impl; + + icalerror_check_arg_rv( (component!=0), "component"); + icalerror_check_arg_rv( (property!=0), "property"); + + impl = (struct icalcomponent_impl*)component; + + icalerror_assert( (!icalproperty_get_parent(property)),"The property has already been added to a component. Remove the property with icalcomponent_remove_property before calling icalcomponent_add_property"); + + icalproperty_set_parent(property,component); + +#ifdef ICAL_INSERT_ORDERED + pvl_insert_ordered(impl->properties, + icalcomponent_property_sorter,property); +#else + pvl_push(impl->properties,property); +#endif + +} + + +void +icalcomponent_remove_property (icalcomponent* component, icalproperty* property) +{ + struct icalcomponent_impl *impl; + pvl_elem itr, next_itr; + struct icalproperty_impl *pimpl; + + icalerror_check_arg_rv( (component!=0), "component"); + icalerror_check_arg_rv( (property!=0), "property"); + + impl = (struct icalcomponent_impl*)component; + + pimpl = (struct icalproperty_impl*)property; + + icalerror_assert( (icalproperty_get_parent(property)),"The property is not a member of a component"); + + + for( itr = pvl_head(impl->properties); + itr != 0; + itr = next_itr) + { + next_itr = pvl_next(itr); + + if( pvl_data(itr) == (void*)property ){ + + if (impl->property_iterator == itr){ + impl->property_iterator = pvl_next(itr); + } + + pvl_remove( impl->properties, itr); + icalproperty_set_parent(property,0); + } + } +} + +int +icalcomponent_count_properties (icalcomponent* component, + icalproperty_kind kind) +{ + int count=0; + pvl_elem itr; + struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; + + icalerror_check_arg_rz( (component!=0), "component"); + + for( itr = pvl_head(impl->properties); + itr != 0; + itr = pvl_next(itr)) + { + if(kind == icalproperty_isa((icalproperty*)pvl_data(itr)) || + kind == ICAL_ANY_PROPERTY){ + count++; + } + } + + + return count; + +} + +icalproperty* icalcomponent_get_current_property (icalcomponent* component) +{ + + struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; + icalerror_check_arg_rz( (component!=0),"component"); + + if ((c->property_iterator==0)){ + return 0; + } + + return (icalproperty*) pvl_data(c->property_iterator); + +} + +icalproperty* +icalcomponent_get_first_property (icalcomponent* component, icalproperty_kind kind) +{ + struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; + icalerror_check_arg_rz( (component!=0),"component"); + + for( c->property_iterator = pvl_head(c->properties); + c->property_iterator != 0; + c->property_iterator = pvl_next(c->property_iterator)) { + + icalproperty *p = (icalproperty*) pvl_data(c->property_iterator); + + if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) { + + return p; + } + } + return 0; +} + +icalproperty* +icalcomponent_get_next_property (icalcomponent* component, icalproperty_kind kind) +{ + struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; + icalerror_check_arg_rz( (component!=0),"component"); + + if (c->property_iterator == 0){ + return 0; + } + + for( c->property_iterator = pvl_next(c->property_iterator); + c->property_iterator != 0; + c->property_iterator = pvl_next(c->property_iterator)) { + + icalproperty *p = (icalproperty*) pvl_data(c->property_iterator); + + if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) { + + return p; + } + } + + return 0; +} + + +icalproperty** +icalcomponent_get_properties (icalcomponent* component, icalproperty_kind kind); + + +void +icalcomponent_add_component (icalcomponent* parent, icalcomponent* child) +{ + struct icalcomponent_impl *impl, *cimpl; + + icalerror_check_arg_rv( (parent!=0), "parent"); + icalerror_check_arg_rv( (child!=0), "child"); + + impl = (struct icalcomponent_impl*)parent; + cimpl = (struct icalcomponent_impl*)child; + + if (cimpl->parent !=0) { + icalerror_set_errno(ICAL_USAGE_ERROR); + } + + cimpl->parent = parent; + + pvl_push(impl->components,child); +} + + +void +icalcomponent_remove_component (icalcomponent* parent, icalcomponent* child) +{ + struct icalcomponent_impl *impl,*cimpl; + pvl_elem itr, next_itr; + + icalerror_check_arg_rv( (parent!=0), "parent"); + icalerror_check_arg_rv( (child!=0), "child"); + + impl = (struct icalcomponent_impl*)parent; + cimpl = (struct icalcomponent_impl*)child; + + for( itr = pvl_head(impl->components); + itr != 0; + itr = next_itr) + { + next_itr = pvl_next(itr); + + if( pvl_data(itr) == (void*)child ){ + + if (impl->component_iterator == itr){ + /* Don't let the current iterator become invalid */ + + /* HACK. The semantics for this are troubling. */ + impl->component_iterator = + pvl_next(impl->component_iterator); + + } + pvl_remove( impl->components, itr); + cimpl->parent = 0; + break; + } + } +} + + +int +icalcomponent_count_components (icalcomponent* component, + icalcomponent_kind kind) +{ + int count=0; + pvl_elem itr; + struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; + + icalerror_check_arg_rz( (component!=0), "component"); + + for( itr = pvl_head(impl->components); + itr != 0; + itr = pvl_next(itr)) + { + if(kind == icalcomponent_isa((icalcomponent*)pvl_data(itr)) || + kind == ICAL_ANY_COMPONENT){ + count++; + } + } + + return count; +} + +icalcomponent* +icalcomponent_get_current_component(icalcomponent* component) +{ + struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; + + icalerror_check_arg_rz( (component!=0),"component"); + + if (c->component_iterator == 0){ + return 0; + } + + return (icalcomponent*) pvl_data(c->component_iterator); +} + +icalcomponent* +icalcomponent_get_first_component (icalcomponent* component, + icalcomponent_kind kind) +{ + struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; + + icalerror_check_arg_rz( (component!=0),"component"); + + for( c->component_iterator = pvl_head(c->components); + c->component_iterator != 0; + c->component_iterator = pvl_next(c->component_iterator)) { + + icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator); + + if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) { + + return p; + } + } + + return 0; +} + + +icalcomponent* +icalcomponent_get_next_component (icalcomponent* component, icalcomponent_kind kind) +{ + struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; + + icalerror_check_arg_rz( (component!=0),"component"); + + if (c->component_iterator == 0){ + return 0; + } + + for( c->component_iterator = pvl_next(c->component_iterator); + c->component_iterator != 0; + c->component_iterator = pvl_next(c->component_iterator)) { + + icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator); + + if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) { + + return p; + } + } + + return 0; +} + +icalcomponent* icalcomponent_get_first_real_component(icalcomponent *c) +{ + icalcomponent *comp; + + for(comp = icalcomponent_get_first_component(c,ICAL_ANY_COMPONENT); + comp != 0; + comp = icalcomponent_get_next_component(c,ICAL_ANY_COMPONENT)){ + + icalcomponent_kind kind = icalcomponent_isa(comp); + + if(kind == ICAL_VEVENT_COMPONENT || + kind == ICAL_VTODO_COMPONENT || + kind == ICAL_VJOURNAL_COMPONENT || + kind == ICAL_VFREEBUSY_COMPONENT ){ + return comp; + } + } + return 0; +} + +time_t icalcomponent_convert_time(icalproperty *p) +{ + struct icaltimetype sict; + time_t convt; + icalproperty *tzp; + + + /* Though it says _dtstart, it will work for dtend too */ + sict = icalproperty_get_dtstart(p); + + tzp = icalproperty_get_first_parameter(p,ICAL_TZID_PARAMETER); + + if (sict.is_utc == 1 && tzp != 0){ + icalerror_warn("icalcomponent_get_span: component has a UTC DTSTART with a timezone specified "); + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + if(sict.is_utc == 1){ + /* _as_timet will use gmtime() to do the conversion */ + convt = icaltime_as_timet(sict); + +#ifdef TEST_CONVERT_TIME + printf("convert time: use as_timet:\n %s\n %s", + icalproperty_as_ical_string(p), ctime(&convt)); +#endif + + } else if (sict.is_utc == 0 && tzp == 0 ) { + time_t offset; + + /* _as_timet will use localtime() to do the conversion */ + convt = icaltime_as_timet(sict); + offset = icaltime_utc_offset(sict,0); + convt += offset; + +#ifdef TEST_CONVERT_TIME + printf("convert time: use as_timet and adjust:\n %s\n %s", + icalproperty_as_ical_string(p), ctime(&convt)); +#endif + } else { + /* Convert the time to UTC for the named timezone*/ + const char* timezone = icalparameter_get_tzid(tzp); + convt = icaltime_as_timet(icaltime_as_utc(sict,timezone)); + +#ifdef TEST_CONVERT_TIME + printf("convert time: use _as_utc:\n %s\n %s", + icalproperty_as_ical_string(p), ctime(&convt)); +#endif + } + + return convt; +} +struct icaltime_span icalcomponent_get_span(icalcomponent* comp) +{ + icalcomponent *inner; + icalproperty *p, *duration; + icalcomponent_kind kind; + struct icaltime_span span; + struct icaltimetype start; + + span.start = 0; + span.end = 0; + span.is_busy= 1; + + /* initial Error checking */ + +/* icalerror_check_arg_rz( (comp!=0),"comp");*/ + + kind = icalcomponent_isa(comp); + + if(kind == ICAL_VCALENDAR_COMPONENT){ + inner = icalcomponent_get_first_real_component(comp); + + /* Maybe there is a VTIMEZONE in there */ + if (inner == 0){ + inner = icalcomponent_get_first_component(comp, + ICAL_VTIMEZONE_COMPONENT); + } + + } else { + inner = comp; + } + + if (inner == 0){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/ + return span; + } + + kind = icalcomponent_isa(inner); + + if( !( kind == ICAL_VEVENT_COMPONENT || + kind == ICAL_VJOURNAL_COMPONENT || + kind == ICAL_VTODO_COMPONENT || + kind == ICAL_VFREEBUSY_COMPONENT )) { + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/ + return span; + + } + + + + /* Get to work. starting with DTSTART */ + + p = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY); + + if (p ==0 ) { + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + /*icalerror_warn("icalcomponent_get_span: component has no DTSTART time");*/ + return span; + } + + + start = icalproperty_get_dtstart(p); + + icalerror_clear_errno(); + + span.start = icalcomponent_convert_time(p); + +#ifdef TEST_CONVERT_TIME + printf("convert time:\n %s %s", + icalproperty_as_ical_string(p), ctime(&span.start)); +#endif + + if(icalerrno != ICAL_NO_ERROR){ + span.start = 0; + return span; + } + + /* The end time could be specified as either a DTEND or a DURATION */ + p = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY); + duration = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY); + + if (p==0 && duration == 0 && start.is_date != 1) { + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + /*icalerror_warn("icalcomponent_get_span: component has neither DTEND nor DURATION time");*/ + span.start = 0; + return span; + } + + if (p!=0){ + span.end = icalcomponent_convert_time(p); + } else if (start.is_date == 1) { + /* Duration is all day */ + span.end = span.start + 60*60*24; + } else { + /* Use the duration */ + struct icaldurationtype dur; + time_t durt; + + + dur = icalproperty_get_duration(duration); + + durt = icaldurationtype_as_int(dur); + span.end = span.start+durt; + } + + return span; + +} + + +int icalcomponent_count_errors(icalcomponent* component) +{ + int errors = 0; + icalproperty *p; + icalcomponent *c; + pvl_elem itr; + struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; + + for( itr = pvl_head(impl->properties); + itr != 0; + itr = pvl_next(itr)) + { + p = (icalproperty*)pvl_data(itr); + + if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY) + { + errors++; + } + } + + + for( itr = pvl_head(impl->components); + itr != 0; + itr = pvl_next(itr)) + { + c = (icalcomponent*)pvl_data(itr); + + errors += icalcomponent_count_errors(c); + + } + + return errors; +} + + +void icalcomponent_strip_errors(icalcomponent* component) +{ + icalproperty *p; + icalcomponent *c; + pvl_elem itr, next_itr; + struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; + + for( itr = pvl_head(impl->properties); + itr != 0; + itr = next_itr) + { + p = (icalproperty*)pvl_data(itr); + next_itr = pvl_next(itr); + + if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY) + { + icalcomponent_remove_property(component,p); + } + } + + for( itr = pvl_head(impl->components); + itr != 0; + itr = pvl_next(itr)) + { + c = (icalcomponent*)pvl_data(itr); + icalcomponent_strip_errors(c); + } +} + +/* Hack. This will change the state of the iterators */ +void icalcomponent_convert_errors(icalcomponent* component) +{ + icalproperty *p, *next_p; + icalcomponent *c; + + for(p = icalcomponent_get_first_property(component,ICAL_ANY_PROPERTY); + p != 0; + p = next_p){ + + next_p = icalcomponent_get_next_property(component,ICAL_ANY_PROPERTY); + + if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY) + { + struct icalreqstattype rst; + icalparameter *param = icalproperty_get_first_parameter + (p,ICAL_XLICERRORTYPE_PARAMETER); + + rst.code = ICAL_UNKNOWN_STATUS; + rst.desc = 0; + + switch(icalparameter_get_xlicerrortype(param)){ + + case ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR: { + rst.code = ICAL_3_2_INVPARAM_STATUS; + break; + } + case ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR: { + rst.code = ICAL_3_3_INVPARAMVAL_STATUS; + break; + } + case ICAL_XLICERRORTYPE_PROPERTYPARSEERROR: { + rst.code = ICAL_3_0_INVPROPNAME_STATUS; + break; + } + case ICAL_XLICERRORTYPE_VALUEPARSEERROR: { + rst.code = ICAL_3_1_INVPROPVAL_STATUS; + break; + } + case ICAL_XLICERRORTYPE_COMPONENTPARSEERROR: { + rst.code = ICAL_3_4_INVCOMP_STATUS; + break; + } + + default: { + } + } + if (rst.code != ICAL_UNKNOWN_STATUS){ + + rst.debug = icalproperty_get_xlicerror(p); + icalcomponent_add_property(component, + icalproperty_new_requeststatus(rst)); + + icalcomponent_remove_property(component,p); + } + } + } + + for(c = icalcomponent_get_first_component(component,ICAL_ANY_COMPONENT); + c != 0; + c = icalcomponent_get_next_component(component,ICAL_ANY_COMPONENT)){ + + icalcomponent_convert_errors(c); + } +} + + +icalcomponent* icalcomponent_get_parent(icalcomponent* component) +{ + struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; + + return c->parent; +} + +void icalcomponent_set_parent(icalcomponent* component, icalcomponent* parent) +{ + struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; + + c->parent = parent; +} + +icalcompiter icalcompiter_null = {ICAL_NO_COMPONENT,0}; + + +struct icalcomponent_kind_map { + icalcomponent_kind kind; + char name[20]; +}; + + + +static struct icalcomponent_kind_map component_map[] = +{ + { ICAL_VEVENT_COMPONENT, "VEVENT" }, + { ICAL_VTODO_COMPONENT, "VTODO" }, + { ICAL_VJOURNAL_COMPONENT, "VJOURNAL" }, + { ICAL_VCALENDAR_COMPONENT, "VCALENDAR" }, + { ICAL_VFREEBUSY_COMPONENT, "VFREEBUSY" }, + { ICAL_VTIMEZONE_COMPONENT, "VTIMEZONE" }, + { ICAL_VALARM_COMPONENT, "VALARM" }, + { ICAL_XSTANDARD_COMPONENT, "STANDARD" }, /*These are part of RFC2445 */ + { ICAL_XDAYLIGHT_COMPONENT, "DAYLIGHT" }, /*but are not really components*/ + { ICAL_X_COMPONENT, "X" }, + { ICAL_VSCHEDULE_COMPONENT, "SCHEDULE" }, + + /* CAP components */ + { ICAL_VQUERY_COMPONENT, "VQUERY" }, + { ICAL_VCAR_COMPONENT, "VCAR" }, + { ICAL_VCOMMAND_COMPONENT, "VCOMMAND" }, + + /* libical private components */ + { ICAL_XLICINVALID_COMPONENT, "X-LIC-UNKNOWN" }, + { ICAL_XLICMIMEPART_COMPONENT, "X-LIC-MIME-PART" }, + { ICAL_ANY_COMPONENT, "ANY" }, + { ICAL_XROOT_COMPONENT, "XROOT" }, + + /* End of list */ + { ICAL_NO_COMPONENT, "" }, +}; + + + +const char* icalcomponent_kind_to_string(icalcomponent_kind kind) +{ + int i; + + for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) { + if (component_map[i].kind == kind) { + return component_map[i].name; + } + } + + return 0; + +} + +icalcomponent_kind icalcomponent_string_to_kind(const char* string) +{ + int i; + + if (string ==0 ) { + return ICAL_NO_COMPONENT; + } + + for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) { + if (strcmp(component_map[i].name, string) == 0) { + return component_map[i].kind; + } + } + + return ICAL_NO_COMPONENT; +} + + + +icalcompiter +icalcomponent_begin_component(icalcomponent* component,icalcomponent_kind kind) +{ + struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; + icalcompiter itr = icalcompiter_null; + pvl_elem i; + + itr.kind = kind; + + icalerror_check_arg_re( (component!=0),"component",icalcompiter_null); + + for( i = pvl_head(impl->components); i != 0; i = pvl_next(itr.iter)) { + + icalcomponent *c = (icalcomponent*) pvl_data(i); + + if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) { + + itr.iter = i; + + return itr; + } + } + + return icalcompiter_null; +} + +icalcompiter +icalcomponent_end_component(icalcomponent* component,icalcomponent_kind kind) +{ + struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; + icalcompiter itr; + pvl_elem i; + + itr.kind = kind; + + icalerror_check_arg_re( (component!=0),"component",icalcompiter_null); + + for( i = pvl_tail(impl->components); i != 0; i = pvl_prior(i)) { + + icalcomponent *c = (icalcomponent*) pvl_data(i); + + if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) { + + itr.iter = pvl_next(i); + + return itr; + } + } + + return icalcompiter_null;; +} + + +icalcomponent* icalcompiter_next(icalcompiter* i) +{ + if (i->iter == 0){ + return 0; + } + + icalerror_check_arg_rz( (i!=0),"i"); + + for( i->iter = pvl_next(i->iter); + i->iter != 0; + i->iter = pvl_next(i->iter)) { + + icalcomponent *c = (icalcomponent*) pvl_data(i->iter); + + if (icalcomponent_isa(c) == i->kind + || i->kind == ICAL_ANY_COMPONENT) { + + return icalcompiter_deref(i);; + } + } + + return 0; + +} + +icalcomponent* icalcompiter_prior(icalcompiter* i) +{ + if (i->iter == 0){ + return 0; + } + + for( i->iter = pvl_prior(i->iter); + i->iter != 0; + i->iter = pvl_prior(i->iter)) { + + icalcomponent *c = (icalcomponent*) pvl_data(i->iter); + + if (icalcomponent_isa(c) == i->kind + || i->kind == ICAL_ANY_COMPONENT) { + + return icalcompiter_deref(i);; + } + } + + return 0; + +} +icalcomponent* icalcompiter_deref(icalcompiter* i) +{ + if(i->iter ==0){ + return 0; + } + + return pvl_data(i->iter); +} + +icalcomponent* icalcomponent_get_inner(icalcomponent* comp) +{ + if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){ + return icalcomponent_get_first_real_component(comp); + } else { + return comp; + } +} + + +void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v) +{ + + icalcomponent *inner = icalcomponent_get_inner(comp); + icalproperty *prop + = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY); + + + if (prop == 0){ + prop = icalproperty_new_dtstart(v); + icalcomponent_add_property(inner, prop); + } + + icalproperty_set_dtstart(prop,v); + +} + + +struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + icalproperty *prop + = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY); + + if (prop == 0){ + return icaltime_null_time(); + } + + return icalproperty_get_dtstart(prop); +} + + +struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + + icalproperty *end_prop + = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY); + + icalproperty *dur_prop + = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY); + + + if( end_prop == 0 && dur_prop == 0){ + return icaltime_null_time(); + } else if ( end_prop != 0) { + return icalproperty_get_dtend(end_prop); + } else if ( dur_prop != 0) { + + struct icaltimetype start = + icalcomponent_get_dtstart(inner); + struct icaldurationtype duration = + icalproperty_get_duration(dur_prop); + + struct icaltimetype end = icaltime_add(start,duration); + + return end; + + } else { + /* Error, both duration and dtend have been specified */ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return icaltime_null_time(); + + } + +} + + +void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + + icalproperty *end_prop + = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY); + + icalproperty *dur_prop + = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY); + + + if( end_prop == 0 && dur_prop == 0){ + end_prop = icalproperty_new_dtend(v); + icalcomponent_add_property(inner,end_prop); + } else if ( end_prop != 0) { + icalproperty_set_dtend(end_prop,v); + } else if ( dur_prop != 0) { + struct icaltimetype start = + icalcomponent_get_dtstart(inner); + + struct icaltimetype end = + icalcomponent_get_dtend(inner); + + struct icaldurationtype dur + = icaltime_subtract(end,start); + + icalproperty_set_duration(dur_prop,dur); + + } else { + /* Error, both duration and dtend have been specified */ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + } +} + +void icalcomponent_set_duration(icalcomponent* comp, + struct icaldurationtype v) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + + icalproperty *end_prop + = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY); + + icalproperty *dur_prop + = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY); + + + if( end_prop == 0 && dur_prop == 0){ + dur_prop = icalproperty_new_duration(v); + icalcomponent_add_property(inner, dur_prop); + } else if ( end_prop != 0) { + struct icaltimetype start = + icalcomponent_get_dtstart(inner); + + struct icaltimetype new_end = icaltime_add(start,v); + + icalproperty_set_dtend(end_prop,new_end); + + } else if ( dur_prop != 0) { + icalproperty_set_duration(dur_prop,v); + } else { + /* Error, both duration and dtend have been specified */ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + } +} + +struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + + icalproperty *end_prop + = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY); + + icalproperty *dur_prop + = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY); + + struct icaldurationtype null_duration; + memset(&null_duration,0,sizeof(struct icaldurationtype)); + + + if( end_prop == 0 && dur_prop == 0){ + return null_duration; + } else if ( end_prop != 0) { + struct icaltimetype start = + icalcomponent_get_dtstart(inner); + time_t startt = icaltime_as_timet(start); + + struct icaltimetype end = + icalcomponent_get_dtend(inner); + time_t endt = icaltime_as_timet(end); + + return icaldurationtype_from_int(endt-startt); + } else if ( dur_prop != 0) { + return icalproperty_get_duration(dur_prop); + } else { + /* Error, both duration and dtend have been specified */ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return null_duration; + } +} + +void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method) +{ + icalproperty *prop + = icalcomponent_get_first_property(comp, ICAL_METHOD_PROPERTY); + + + if (prop == 0){ + prop = icalproperty_new_method(method); + icalcomponent_add_property(comp, prop); + } + + icalproperty_set_method(prop,method); + +} + +icalproperty_method icalcomponent_get_method(icalcomponent* comp) +{ + icalproperty *prop + = icalcomponent_get_first_property(comp,ICAL_METHOD_PROPERTY); + + if (prop == 0){ + return ICAL_METHOD_NONE; + } + + return icalproperty_get_method(prop); +} + +void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v) +{ + + icalcomponent *inner = icalcomponent_get_inner(comp); + icalproperty *prop + = icalcomponent_get_first_property(inner, ICAL_DTSTAMP_PROPERTY); + + + if (prop == 0){ + prop = icalproperty_new_dtstamp(v); + icalcomponent_add_property(inner, prop); + } + + icalproperty_set_dtstamp(prop,v); + +} + + +struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + icalproperty *prop + = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY); + + if (prop == 0){ + return icaltime_null_time(); + } + + return icalproperty_get_dtstamp(prop); +} + + +void icalcomponent_set_summary(icalcomponent* comp, const char* v) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + icalproperty *prop + = icalcomponent_get_first_property(inner, ICAL_SUMMARY_PROPERTY); + + if (prop == 0){ + prop = icalproperty_new_summary(v); + icalcomponent_add_property(inner, prop); + } + + icalproperty_set_summary(prop,v); +} + + +const char* icalcomponent_get_summary(icalcomponent* comp) +{ + icalcomponent *inner = icalcomponent_get_inner(comp); + icalproperty *prop + = icalcomponent_get_first_property(inner,ICAL_SUMMARY_PROPERTY); + + if (prop == 0){ + return 0; + } + + return icalproperty_get_summary(prop); + +} + +void icalcomponent_set_comment(icalcomponent* comp, const char* v); +const char* icalcomponent_get_comment(icalcomponent* comp); + +void icalcomponent_set_uid(icalcomponent* comp, const char* v); +const char* icalcomponent_get_uid(icalcomponent* comp); + +void icalcomponent_set_recurrenceid(icalcomponent* comp, + struct icaltimetype v); +struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp); + + + + +icalcomponent* icalcomponent_new_vcalendar() +{ + return icalcomponent_new(ICAL_VCALENDAR_COMPONENT); +} +icalcomponent* icalcomponent_new_vevent() +{ + return icalcomponent_new(ICAL_VEVENT_COMPONENT); +} +icalcomponent* icalcomponent_new_vtodo() +{ + return icalcomponent_new(ICAL_VTODO_COMPONENT); +} +icalcomponent* icalcomponent_new_vjournal() +{ + return icalcomponent_new(ICAL_VJOURNAL_COMPONENT); +} +icalcomponent* icalcomponent_new_valarm() +{ + return icalcomponent_new(ICAL_VALARM_COMPONENT); +} +icalcomponent* icalcomponent_new_vfreebusy() +{ + return icalcomponent_new(ICAL_VFREEBUSY_COMPONENT); +} +icalcomponent* icalcomponent_new_vtimezone() +{ + return icalcomponent_new(ICAL_VTIMEZONE_COMPONENT); +} +icalcomponent* icalcomponent_new_xstandard() +{ + return icalcomponent_new(ICAL_XSTANDARD_COMPONENT); +} +icalcomponent* icalcomponent_new_xdaylight() +{ + return icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); +} diff --git a/libical/src/libical/icalcomponent.h b/libical/src/libical/icalcomponent.h new file mode 100644 index 0000000..6046bbe --- a/dev/null +++ b/libical/src/libical/icalcomponent.h @@ -0,0 +1,240 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcomponent.h + CREATOR: eric 20 March 1999 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalcomponent.h + +======================================================================*/ + +#ifndef ICALCOMPONENT_H +#define ICALCOMPONENT_H + +#include "icalproperty.h" +#include "icalvalue.h" +#include "icalenums.h" /* defines icalcomponent_kind */ +#include "icalattendee.h" +#include "pvl.h" + +typedef void icalcomponent; + +/* This is exposed so that callers will not have to allocate and + deallocate iterators. Pretend that you can't see it. */ +typedef struct icalcompiter +{ + icalcomponent_kind kind; + pvl_elem iter; + +} icalcompiter; + +icalcomponent* icalcomponent_new(icalcomponent_kind kind); +icalcomponent* icalcomponent_new_clone(icalcomponent* component); +icalcomponent* icalcomponent_new_from_string(char* str); +icalcomponent* icalcomponent_vanew(icalcomponent_kind kind, ...); +void icalcomponent_free(icalcomponent* component); + +char* icalcomponent_as_ical_string(icalcomponent* component); + +int icalcomponent_is_valid(icalcomponent* component); + +icalcomponent_kind icalcomponent_isa(icalcomponent* component); + +int icalcomponent_isa_component (void* component); + +/* + * Working with properties + */ + +void icalcomponent_add_property(icalcomponent* component, + icalproperty* property); + +void icalcomponent_remove_property(icalcomponent* component, + icalproperty* property); + +int icalcomponent_count_properties(icalcomponent* component, + icalproperty_kind kind); + +/* Iterate through the properties */ +icalproperty* icalcomponent_get_current_property(icalcomponent* component); + +icalproperty* icalcomponent_get_first_property(icalcomponent* component, + icalproperty_kind kind); +icalproperty* icalcomponent_get_next_property(icalcomponent* component, + icalproperty_kind kind); + + +/* + * Working with components + */ + + +/* Return the first VEVENT, VTODO or VJOURNAL sub-component of cop, or + comp if it is one of those types */ + +icalcomponent* icalcomponent_get_inner(icalcomponent* comp); + + +void icalcomponent_add_component(icalcomponent* parent, + icalcomponent* child); + +void icalcomponent_remove_component(icalcomponent* parent, + icalcomponent* child); + +int icalcomponent_count_components(icalcomponent* component, + icalcomponent_kind kind); + +/* Iteration Routines. There are two forms of iterators, internal and +external. The internal ones came first, and are almost completely +sufficient, but they fail badly when you want to construct a loop that +removes components from the container.*/ + + +/* Iterate through components */ +icalcomponent* icalcomponent_get_current_component (icalcomponent* component); + +icalcomponent* icalcomponent_get_first_component(icalcomponent* component, + icalcomponent_kind kind); +icalcomponent* icalcomponent_get_next_component(icalcomponent* component, + icalcomponent_kind kind); + +/* Using external iterators */ +icalcompiter icalcomponent_begin_component(icalcomponent* component, + icalcomponent_kind kind); +icalcompiter icalcomponent_end_component(icalcomponent* component, + icalcomponent_kind kind); +icalcomponent* icalcompiter_next(icalcompiter* i); +icalcomponent* icalcompiter_prior(icalcompiter* i); +icalcomponent* icalcompiter_deref(icalcompiter* i); + + + + +/* Working with embedded error properties */ + +int icalcomponent_count_errors(icalcomponent* component); + +/* Remove all X-LIC-ERROR properties*/ +void icalcomponent_strip_errors(icalcomponent* component); + +/* Convert some X-LIC-ERROR properties into RETURN-STATUS properties*/ +void icalcomponent_convert_errors(icalcomponent* component); + +/* Internal operations. They are private, and you should not be using them. */ +icalcomponent* icalcomponent_get_parent(icalcomponent* component); +void icalcomponent_set_parent(icalcomponent* component, + icalcomponent* parent); + +/* Kind conversion routiens */ + +icalcomponent_kind icalcomponent_string_to_kind(const char* string); + +const char* icalcomponent_kind_to_string(icalcomponent_kind kind); + + +/************* Derived class methods. **************************** + +If the code was in an OO language, the remaining routines would be +members of classes derived from icalcomponent. Don't call them on the +wrong component subtypes. */ + +/* For VCOMPONENT: Return a reference to the first VEVENT, VTODO or + VJOURNAL */ +icalcomponent* icalcomponent_get_first_real_component(icalcomponent *c); + +/* For VEVENT, VTODO, VJOURNAL and VTIMEZONE: report the start and end + times of an event in UTC */ +struct icaltime_span icalcomponent_get_span(icalcomponent* comp); + +/******************** Convienience routines **********************/ + +void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v); +struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp); + +/* For the icalcomponent routines only, dtend and duration are tied + together. If you call the set routine for one and the other exists, + the routine will calculate the change to the other. That is, if + there is a DTEND and you call set_duration, the routine will modify + DTEND to be the sum of DTSTART and the duration. If you call a get + routine for one and the other exists, the routine will calculate + the return value. If you call a set routine and neither exists, the + routine will create the apcompriate comperty */ + + +struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp); +void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v); + +void icalcomponent_set_duration(icalcomponent* comp, + struct icaldurationtype v); +struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp); + +void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method); +icalproperty_method icalcomponent_get_method(icalcomponent* comp); + +struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp); +void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v); + + +void icalcomponent_set_summary(icalcomponent* comp, const char* v); +const char* icalcomponent_get_summary(icalcomponent* comp); + +void icalcomponent_set_comment(icalcomponent* comp, const char* v); +const char* icalcomponent_get_comment(icalcomponent* comp); + +void icalcomponent_set_uid(icalcomponent* comp, const char* v); +const char* icalcomponent_get_uid(icalcomponent* comp); + +void icalcomponent_set_recurrenceid(icalcomponent* comp, + struct icaltimetype v); +struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp); + + +void icalcomponent_set_organizer(icalcomponent* comp, + struct icalorganizertype org); + struct icalorganizertype icalcomponent_get_organizer(icalcomponent* comp); + + +void icalcomponent_add_attendee(icalcomponent *comp, + struct icalattendeetype attendee); + +int icalcomponent_remove_attendee(icalcomponent *comp, char* cuid); + +/* Get the Nth attendee. Out of range indices return an attendee + with cuid == 0 */ +struct icalattendeetype icalcomponent_get_attendee(icalcomponent *comp, + int index); + + + + +/*************** Type Specific routines ***************/ + +icalcomponent* icalcomponent_new_vcalendar(); +icalcomponent* icalcomponent_new_vevent(); +icalcomponent* icalcomponent_new_vtodo(); +icalcomponent* icalcomponent_new_vjournal(); +icalcomponent* icalcomponent_new_valarm(); +icalcomponent* icalcomponent_new_vfreebusy(); +icalcomponent* icalcomponent_new_vtimezone(); +icalcomponent* icalcomponent_new_xstandard(); +icalcomponent* icalcomponent_new_xdaylight(); + + + +#endif /* !ICALCOMPONENT_H */ + + + diff --git a/libical/src/libical/icalderivedparameter.c b/libical/src/libical/icalderivedparameter.c new file mode 100644 index 0000000..6898eb6 --- a/dev/null +++ b/libical/src/libical/icalderivedparameter.c @@ -0,0 +1,1205 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalderivedparameters.{c,h} + CREATOR: eric 09 May 1999 + + $Id$ + $Locker$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalderivedparameters.{c,h} + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + ======================================================================*/ +/*#line 29 "icalparameter.c.in"*/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +#include "icalparameter.h" +#include "icalparameterimpl.h" + +#include "icalproperty.h" +#include "icalerror.h" +#include "icalmemory.h" + +#include <stdlib.h> /* for malloc() */ +#include <errno.h> +#include <string.h> /* for memset() */ + +icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value); + +struct icalparameter_impl* icalparameter_new_impl(icalparameter_kind kind); + +/* This map associates each of the parameters with the string + representation of the paramter's name */ +struct icalparameter_kind_map { + icalparameter_kind kind; + char *name; + +}; + +extern struct icalparameter_kind_map parameter_map[]; + + +const char* icalparameter_kind_to_string(icalparameter_kind kind) +{ + int i; + + for (i=0; parameter_map[i].kind != ICAL_NO_PARAMETER; i++) { + if (parameter_map[i].kind == kind) { + return parameter_map[i].name; + } + } + + return 0; + +} + +icalparameter_kind icalparameter_string_to_kind(const char* string) +{ + int i; + + if (string ==0 ) { + return ICAL_NO_PARAMETER; + } + + for (i=0; parameter_map[i].kind != ICAL_NO_PARAMETER; i++) { + + if (strcmp(parameter_map[i].name, string) == 0) { + return parameter_map[i].kind; + } + } + + if(strncmp(string,"X-",2)==0){ + return ICAL_X_PARAMETER; + } + + return ICAL_NO_PARAMETER; +} + +/* This map associates the enumerations for the VALUE parameter with + the kinds of VALUEs. */ + +struct icalparameter_value_kind_map { + icalparameter_value value; + icalvalue_kind kind; +}; + +extern struct icalparameter_value_kind_map value_kind_map[]; + + +icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value) +{ + int i; + + for (i=0; value_kind_map[i].kind != ICAL_NO_VALUE; i++) { + + if (value_kind_map[i].value == value) { + return value_kind_map[i].kind; + } + } + + return ICAL_NO_VALUE; +} + + +/* This map associates the parameter enumerations with a specific parameter and the string representation of the enumeration */ + +struct icalparameter_map { + icalparameter_kind kind; + int enumeration; + const char* str; +}; + + +extern struct icalparameter_map icalparameter_map[]; + + +const char* icalparameter_enum_to_string(int e) +{ + int i; + + icalerror_check_arg_rz(e >= ICALPARAMETER_FIRST_ENUM,"e"); + icalerror_check_arg_rz(e <= ICALPARAMETER_LAST_ENUM,"e"); + + for (i=0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++){ + if(e == icalparameter_map[i].enumeration){ + return icalparameter_map[i].str; + } + } + + return 0; +} + +int icalparameter_string_to_enum(const char* str) +{ + int i; + + icalerror_check_arg_rz(str != 0,"str"); + + for (i=0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++){ + if(strcmp(str,icalparameter_map[i].str) == 0) { + return icalparameter_map[i].enumeration; + } + } + + return 0; +} + +icalparameter* icalparameter_new_from_value_string(icalparameter_kind kind,const char* val) +{ + + struct icalparameter_impl* param=0; + int found_kind = 0; + int i; + + icalerror_check_arg_rz((val!=0),"val"); + + /* Search through the parameter map to find a matching kind */ + + param = icalparameter_new_impl(kind); + + for (i=0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++){ + if(kind == icalparameter_map[i].kind) { + found_kind = 1; + if(strcmp(val,icalparameter_map[i].str) == 0) { + + param->data = (int)icalparameter_map[i].enumeration; + return param; + } + } + } + + if(found_kind == 1){ + /* The kind was in the parameter map, but the string did not + match, so assume that it is an alternate value, like an + X-value.*/ + + icalparameter_set_xvalue(param, val); + + } else { + + /* If the kind was not found, then it must be a string type */ + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(val); + + } + + return param; +} + + + + +/* Everything below this line is machine generated. Do not edit. */ +struct icalparameter_value_kind_map value_kind_map[] = { + {ICAL_VALUE_BINARY,ICAL_BINARY_VALUE}, + {ICAL_VALUE_BOOLEAN,ICAL_BOOLEAN_VALUE}, + {ICAL_VALUE_DATE,ICAL_DATE_VALUE}, + {ICAL_VALUE_DURATION,ICAL_DURATION_VALUE}, + {ICAL_VALUE_FLOAT,ICAL_FLOAT_VALUE}, + {ICAL_VALUE_INTEGER,ICAL_INTEGER_VALUE}, + {ICAL_VALUE_PERIOD,ICAL_PERIOD_VALUE}, + {ICAL_VALUE_RECUR,ICAL_RECUR_VALUE}, + {ICAL_VALUE_TEXT,ICAL_TEXT_VALUE}, + {ICAL_VALUE_URI,ICAL_URI_VALUE}, + {ICAL_VALUE_DATETIME,ICAL_DATETIME_VALUE}, + {ICAL_VALUE_UTCOFFSET,ICAL_UTCOFFSET_VALUE}, + {ICAL_VALUE_CALADDRESS,ICAL_CALADDRESS_VALUE}, + {ICAL_VALUE_X,ICAL_X_VALUE}, + {ICAL_VALUE_NONE,ICAL_NO_VALUE} +}; + +static struct icalparameter_kind_map parameter_map[] = { + {ICAL_ALTREP_PARAMETER,"ALTREP"}, + {ICAL_CN_PARAMETER,"CN"}, + {ICAL_CUTYPE_PARAMETER,"CUTYPE"}, + {ICAL_DELEGATEDFROM_PARAMETER,"DELEGATED-FROM"}, + {ICAL_DELEGATEDTO_PARAMETER,"DELEGATED-TO"}, + {ICAL_DIR_PARAMETER,"DIR"}, + {ICAL_ENCODING_PARAMETER,"ENCODING"}, + {ICAL_FBTYPE_PARAMETER,"FBTYPE"}, + {ICAL_FMTTYPE_PARAMETER,"FMTTYPE"}, + {ICAL_LANGUAGE_PARAMETER,"LANGUAGE"}, + {ICAL_MEMBER_PARAMETER,"MEMBER"}, + {ICAL_PARTSTAT_PARAMETER,"PARTSTAT"}, + {ICAL_RANGE_PARAMETER,"RANGE"}, + {ICAL_RELATED_PARAMETER,"RELATED"}, + {ICAL_RELTYPE_PARAMETER,"RELTYPE"}, + {ICAL_ROLE_PARAMETER,"ROLE"}, + {ICAL_RSVP_PARAMETER,"RSVP"}, + {ICAL_SENTBY_PARAMETER,"SENT-BY"}, + {ICAL_TZID_PARAMETER,"TZID"}, + {ICAL_VALUE_PARAMETER,"VALUE"}, + {ICAL_X_PARAMETER,"X"}, + {ICAL_XLICCOMPARETYPE_PARAMETER,"X-LIC-COMPARETYPE"}, + {ICAL_XLICERRORTYPE_PARAMETER,"X-LIC-ERRORTYPE"}, + { ICAL_NO_PARAMETER, ""} +}; + +static struct icalparameter_map icalparameter_map[] = { +{ICAL_ANY_PARAMETER,0,""}, + {ICAL_CUTYPE_PARAMETER,ICAL_CUTYPE_INDIVIDUAL,"INDIVIDUAL"}, + {ICAL_CUTYPE_PARAMETER,ICAL_CUTYPE_GROUP,"GROUP"}, + {ICAL_CUTYPE_PARAMETER,ICAL_CUTYPE_RESOURCE,"RESOURCE"}, + {ICAL_CUTYPE_PARAMETER,ICAL_CUTYPE_ROOM,"ROOM"}, + {ICAL_CUTYPE_PARAMETER,ICAL_CUTYPE_UNKNOWN,"UNKNOWN"}, + {ICAL_ENCODING_PARAMETER,ICAL_ENCODING_8BIT,"8BIT"}, + {ICAL_ENCODING_PARAMETER,ICAL_ENCODING_BASE64,"BASE64"}, + {ICAL_FBTYPE_PARAMETER,ICAL_FBTYPE_FREE,"FREE"}, + {ICAL_FBTYPE_PARAMETER,ICAL_FBTYPE_BUSY,"BUSY"}, + {ICAL_FBTYPE_PARAMETER,ICAL_FBTYPE_BUSYUNAVAILABLE,"BUSYUNAVAILABLE"}, + {ICAL_FBTYPE_PARAMETER,ICAL_FBTYPE_BUSYTENTATIVE,"BUSYTENTATIVE"}, + {ICAL_PARTSTAT_PARAMETER,ICAL_PARTSTAT_NEEDSACTION,"NEEDS-ACTION"}, + {ICAL_PARTSTAT_PARAMETER,ICAL_PARTSTAT_ACCEPTED,"ACCEPTED"}, + {ICAL_PARTSTAT_PARAMETER,ICAL_PARTSTAT_DECLINED,"DECLINED"}, + {ICAL_PARTSTAT_PARAMETER,ICAL_PARTSTAT_TENTATIVE,"TENTATIVE"}, + {ICAL_PARTSTAT_PARAMETER,ICAL_PARTSTAT_DELEGATED,"DELEGATED"}, + {ICAL_PARTSTAT_PARAMETER,ICAL_PARTSTAT_COMPLETED,"COMPLETED"}, + {ICAL_PARTSTAT_PARAMETER,ICAL_PARTSTAT_INPROCESS,"INPROCESS"}, + {ICAL_RANGE_PARAMETER,ICAL_RANGE_THISANDPRIOR,"THISANDPRIOR"}, + {ICAL_RANGE_PARAMETER,ICAL_RANGE_THISANDFUTURE,"THISANDFUTURE"}, + {ICAL_RELATED_PARAMETER,ICAL_RELATED_START,"START"}, + {ICAL_RELATED_PARAMETER,ICAL_RELATED_END ,"END "}, + {ICAL_RELTYPE_PARAMETER,ICAL_RELTYPE_PARENT,"PARENT"}, + {ICAL_RELTYPE_PARAMETER,ICAL_RELTYPE_CHILD,"CHILD"}, + {ICAL_RELTYPE_PARAMETER,ICAL_RELTYPE_SIBLING,"SIBLING"}, + {ICAL_ROLE_PARAMETER,ICAL_ROLE_CHAIR,"CHAIR"}, + {ICAL_ROLE_PARAMETER,ICAL_ROLE_REQPARTICIPANT,"REQ-PARTICIPANT"}, + {ICAL_ROLE_PARAMETER,ICAL_ROLE_OPTPARTICIPANT,"OPT-PARTICIPANT"}, + {ICAL_ROLE_PARAMETER,ICAL_ROLE_NONPARTICIPANT,"NON-PARTICIPANT"}, + {ICAL_RSVP_PARAMETER,ICAL_RSVP_TRUE,"TRUE"}, + {ICAL_RSVP_PARAMETER,ICAL_RSVP_FALSE,"FALSE"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_BINARY,"BINARY"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_BOOLEAN,"BOOLEAN"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_DATE,"DATE"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_DURATION,"DURATION"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_FLOAT,"FLOAT"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_INTEGER,"INTEGER"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_PERIOD,"PERIOD"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_RECUR,"RECUR"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_TEXT,"TEXT"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_URI,"URI"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_ERROR,"ERROR"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_DATETIME,"DATE-TIME"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_UTCOFFSET,"UTC-OFFSET"}, + {ICAL_VALUE_PARAMETER,ICAL_VALUE_CALADDRESS,"CAL-ADDRESS"}, + {ICAL_XLICCOMPARETYPE_PARAMETER,ICAL_XLICCOMPARETYPE_EQUAL,"EQUAL"}, + {ICAL_XLICCOMPARETYPE_PARAMETER,ICAL_XLICCOMPARETYPE_NOTEQUAL,"NOTEQUAL"}, + {ICAL_XLICCOMPARETYPE_PARAMETER,ICAL_XLICCOMPARETYPE_LESS,"LESS"}, + {ICAL_XLICCOMPARETYPE_PARAMETER,ICAL_XLICCOMPARETYPE_GREATER,"GREATER"}, + {ICAL_XLICCOMPARETYPE_PARAMETER,ICAL_XLICCOMPARETYPE_LESSEQUAL,"LESSEQUAL"}, + {ICAL_XLICCOMPARETYPE_PARAMETER,ICAL_XLICCOMPARETYPE_GREATEREQUAL,"GREATEREQUAL"}, + {ICAL_XLICCOMPARETYPE_PARAMETER,ICAL_XLICCOMPARETYPE_REGEX,"REGEX"}, + {ICAL_XLICERRORTYPE_PARAMETER,ICAL_XLICERRORTYPE_COMPONENTPARSEERROR,"COMPONENT-PARSE-ERROR"}, + {ICAL_XLICERRORTYPE_PARAMETER,ICAL_XLICERRORTYPE_PROPERTYPARSEERROR,"PROPERTY-PARSE-ERROR"}, + {ICAL_XLICERRORTYPE_PARAMETER,ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR,"PARAMETER-NAME-PARSE-ERROR"}, + {ICAL_XLICERRORTYPE_PARAMETER,ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR,"PARAMETER-VALUE-PARSE-ERROR"}, + {ICAL_XLICERRORTYPE_PARAMETER,ICAL_XLICERRORTYPE_VALUEPARSEERROR,"VALUE-PARSE-ERROR"}, + {ICAL_XLICERRORTYPE_PARAMETER,ICAL_XLICERRORTYPE_INVALIDITIP,"INVALID-ITIP"}, + {ICAL_XLICERRORTYPE_PARAMETER,ICAL_XLICERRORTYPE_UNKNOWNVCALPROPERROR,"UNKNOWN-VCAL-PROP-ERROR"}, + {ICAL_XLICERRORTYPE_PARAMETER,ICAL_XLICERRORTYPE_MIMEPARSEERROR,"MIME-PARSE-ERROR"}, + {ICAL_NO_PARAMETER,0,""}}; + +/* DELEGATED-FROM */ +icalparameter* icalparameter_new_delegatedfrom(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_DELEGATEDFROM_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_delegatedfrom((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_delegatedfrom(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_delegatedfrom(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* DELEGATED-TO */ +icalparameter* icalparameter_new_delegatedto(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_DELEGATEDTO_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_delegatedto((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_delegatedto(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_delegatedto(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* RANGE */ +icalparameter* icalparameter_new_range(icalparameter_range v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_RANGE_X,"v"); + icalerror_check_arg_rz(v < ICAL_RANGE_NONE,"v"); + impl = icalparameter_new_impl(ICAL_RANGE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_range((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_range icalparameter_get_range(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + +return (icalparameter_range)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_range(icalparameter* param, icalparameter_range v) +{ + icalerror_check_arg_rv(v >= ICAL_RANGE_X,"v"); + icalerror_check_arg_rv(v < ICAL_RANGE_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* ENCODING */ +icalparameter* icalparameter_new_encoding(icalparameter_encoding v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_ENCODING_X,"v"); + icalerror_check_arg_rz(v < ICAL_ENCODING_NONE,"v"); + impl = icalparameter_new_impl(ICAL_ENCODING_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_encoding((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_encoding icalparameter_get_encoding(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + if ( ((struct icalparameter_impl*)param)->string != 0){ + return ICAL_ENCODING_X; + } + +return (icalparameter_encoding)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_encoding(icalparameter* param, icalparameter_encoding v) +{ + icalerror_check_arg_rv(v >= ICAL_ENCODING_X,"v"); + icalerror_check_arg_rv(v < ICAL_ENCODING_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* RSVP */ +icalparameter* icalparameter_new_rsvp(icalparameter_rsvp v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_RSVP_X,"v"); + icalerror_check_arg_rz(v < ICAL_RSVP_NONE,"v"); + impl = icalparameter_new_impl(ICAL_RSVP_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_rsvp((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_rsvp icalparameter_get_rsvp(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + +return (icalparameter_rsvp)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_rsvp(icalparameter* param, icalparameter_rsvp v) +{ + icalerror_check_arg_rv(v >= ICAL_RSVP_X,"v"); + icalerror_check_arg_rv(v < ICAL_RSVP_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* PARTSTAT */ +icalparameter* icalparameter_new_partstat(icalparameter_partstat v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_PARTSTAT_X,"v"); + icalerror_check_arg_rz(v < ICAL_PARTSTAT_NONE,"v"); + impl = icalparameter_new_impl(ICAL_PARTSTAT_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_partstat((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_partstat icalparameter_get_partstat(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + if ( ((struct icalparameter_impl*)param)->string != 0){ + return ICAL_PARTSTAT_X; + } + +return (icalparameter_partstat)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_partstat(icalparameter* param, icalparameter_partstat v) +{ + icalerror_check_arg_rv(v >= ICAL_PARTSTAT_X,"v"); + icalerror_check_arg_rv(v < ICAL_PARTSTAT_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* RELTYPE */ +icalparameter* icalparameter_new_reltype(icalparameter_reltype v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_RELTYPE_X,"v"); + icalerror_check_arg_rz(v < ICAL_RELTYPE_NONE,"v"); + impl = icalparameter_new_impl(ICAL_RELTYPE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_reltype((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_reltype icalparameter_get_reltype(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + if ( ((struct icalparameter_impl*)param)->string != 0){ + return ICAL_RELTYPE_X; + } + +return (icalparameter_reltype)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_reltype(icalparameter* param, icalparameter_reltype v) +{ + icalerror_check_arg_rv(v >= ICAL_RELTYPE_X,"v"); + icalerror_check_arg_rv(v < ICAL_RELTYPE_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* CUTYPE */ +icalparameter* icalparameter_new_cutype(icalparameter_cutype v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_CUTYPE_X,"v"); + icalerror_check_arg_rz(v < ICAL_CUTYPE_NONE,"v"); + impl = icalparameter_new_impl(ICAL_CUTYPE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_cutype((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_cutype icalparameter_get_cutype(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + if ( ((struct icalparameter_impl*)param)->string != 0){ + return ICAL_CUTYPE_X; + } + +return (icalparameter_cutype)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_cutype(icalparameter* param, icalparameter_cutype v) +{ + icalerror_check_arg_rv(v >= ICAL_CUTYPE_X,"v"); + icalerror_check_arg_rv(v < ICAL_CUTYPE_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* MEMBER */ +icalparameter* icalparameter_new_member(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_MEMBER_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_member((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_member(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_member(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* FMTTYPE */ +icalparameter* icalparameter_new_fmttype(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_FMTTYPE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_fmttype((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_fmttype(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_fmttype(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* SENT-BY */ +icalparameter* icalparameter_new_sentby(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_SENTBY_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_sentby((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_sentby(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_sentby(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* VALUE */ +icalparameter* icalparameter_new_value(icalparameter_value v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_VALUE_X,"v"); + icalerror_check_arg_rz(v < ICAL_VALUE_NONE,"v"); + impl = icalparameter_new_impl(ICAL_VALUE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_value((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_value icalparameter_get_value(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + if ( ((struct icalparameter_impl*)param)->string != 0){ + return ICAL_VALUE_X; + } + +return (icalparameter_value)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_value(icalparameter* param, icalparameter_value v) +{ + icalerror_check_arg_rv(v >= ICAL_VALUE_X,"v"); + icalerror_check_arg_rv(v < ICAL_VALUE_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* ALTREP */ +icalparameter* icalparameter_new_altrep(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_ALTREP_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_altrep((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_altrep(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_altrep(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* DIR */ +icalparameter* icalparameter_new_dir(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_DIR_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_dir((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_dir(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_dir(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* RELATED */ +icalparameter* icalparameter_new_related(icalparameter_related v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_RELATED_X,"v"); + icalerror_check_arg_rz(v < ICAL_RELATED_NONE,"v"); + impl = icalparameter_new_impl(ICAL_RELATED_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_related((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_related icalparameter_get_related(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + +return (icalparameter_related)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_related(icalparameter* param, icalparameter_related v) +{ + icalerror_check_arg_rv(v >= ICAL_RELATED_X,"v"); + icalerror_check_arg_rv(v < ICAL_RELATED_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* CN */ +icalparameter* icalparameter_new_cn(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_CN_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_cn((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_cn(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_cn(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* X-LIC-ERRORTYPE */ +icalparameter* icalparameter_new_xlicerrortype(icalparameter_xlicerrortype v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_XLICERRORTYPE_X,"v"); + icalerror_check_arg_rz(v < ICAL_XLICERRORTYPE_NONE,"v"); + impl = icalparameter_new_impl(ICAL_XLICERRORTYPE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_xlicerrortype((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_xlicerrortype icalparameter_get_xlicerrortype(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + +return (icalparameter_xlicerrortype)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_xlicerrortype(icalparameter* param, icalparameter_xlicerrortype v) +{ + icalerror_check_arg_rv(v >= ICAL_XLICERRORTYPE_X,"v"); + icalerror_check_arg_rv(v < ICAL_XLICERRORTYPE_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* X */ +icalparameter* icalparameter_new_x(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_X_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_x((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_x(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_x(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* LANGUAGE */ +icalparameter* icalparameter_new_language(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_LANGUAGE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_language((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_language(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_language(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + +/* ROLE */ +icalparameter* icalparameter_new_role(icalparameter_role v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_ROLE_X,"v"); + icalerror_check_arg_rz(v < ICAL_ROLE_NONE,"v"); + impl = icalparameter_new_impl(ICAL_ROLE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_role((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_role icalparameter_get_role(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + if ( ((struct icalparameter_impl*)param)->string != 0){ + return ICAL_ROLE_X; + } + +return (icalparameter_role)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_role(icalparameter* param, icalparameter_role v) +{ + icalerror_check_arg_rv(v >= ICAL_ROLE_X,"v"); + icalerror_check_arg_rv(v < ICAL_ROLE_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* X-LIC-COMPARETYPE */ +icalparameter* icalparameter_new_xliccomparetype(icalparameter_xliccomparetype v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_XLICCOMPARETYPE_X,"v"); + icalerror_check_arg_rz(v < ICAL_XLICCOMPARETYPE_NONE,"v"); + impl = icalparameter_new_impl(ICAL_XLICCOMPARETYPE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_xliccomparetype((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_xliccomparetype icalparameter_get_xliccomparetype(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + +return (icalparameter_xliccomparetype)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_xliccomparetype(icalparameter* param, icalparameter_xliccomparetype v) +{ + icalerror_check_arg_rv(v >= ICAL_XLICCOMPARETYPE_X,"v"); + icalerror_check_arg_rv(v < ICAL_XLICCOMPARETYPE_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* FBTYPE */ +icalparameter* icalparameter_new_fbtype(icalparameter_fbtype v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz(v >= ICAL_FBTYPE_X,"v"); + icalerror_check_arg_rz(v < ICAL_FBTYPE_NONE,"v"); + impl = icalparameter_new_impl(ICAL_FBTYPE_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_fbtype((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +icalparameter_fbtype icalparameter_get_fbtype(icalparameter* param) +{ + icalerror_clear_errno(); +icalerror_check_arg( (param!=0), "param"); + if ( ((struct icalparameter_impl*)param)->string != 0){ + return ICAL_FBTYPE_X; + } + +return (icalparameter_fbtype)((struct icalparameter_impl*)param)->data; +} + +void icalparameter_set_fbtype(icalparameter* param, icalparameter_fbtype v) +{ + icalerror_check_arg_rv(v >= ICAL_FBTYPE_X,"v"); + icalerror_check_arg_rv(v < ICAL_FBTYPE_NONE,"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->data = (int)v; +} + +/* TZID */ +icalparameter* icalparameter_new_tzid(const char* v) +{ + struct icalparameter_impl *impl; + icalerror_clear_errno(); + icalerror_check_arg_rz( (v!=0),"v"); + impl = icalparameter_new_impl(ICAL_TZID_PARAMETER); + if (impl == 0) { + return 0; + } + + icalparameter_set_tzid((icalparameter*) impl,v); + if (icalerrno != ICAL_NO_ERROR) { + icalparameter_free((icalparameter*) impl); + return 0; + } + + return (icalparameter*) impl; +} + +const char* icalparameter_get_tzid(icalparameter* param) +{ + icalerror_clear_errno(); + icalerror_check_arg_rz( (param!=0), "param"); + return (const char*)((struct icalparameter_impl*)param)->string; +} + +void icalparameter_set_tzid(icalparameter* param, const char* v) +{ + icalerror_check_arg_rv( (v!=0),"v"); + icalerror_check_arg_rv( (param!=0), "param"); + icalerror_clear_errno(); + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(v); +} + diff --git a/libical/src/libical/icalderivedparameter.h b/libical/src/libical/icalderivedparameter.h new file mode 100644 index 0000000..adf4724 --- a/dev/null +++ b/libical/src/libical/icalderivedparameter.h @@ -0,0 +1,307 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalparam.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalparam.h + + ======================================================================*/ + +#ifndef ICALDERIVEDPARAMETER_H +#define ICALDERIVEDPARAMETER_H + + +typedef void icalparameter; + +const char* icalparameter_enum_to_string(int e); +int icalparameter_string_to_enum(const char* str); + +/* Everything below this line is machine generated. Do not edit. */ +typedef enum icalparameter_kind { + ICAL_ANY_PARAMETER = 0, + ICAL_ALTREP_PARAMETER, + ICAL_CN_PARAMETER, + ICAL_CUTYPE_PARAMETER, + ICAL_DELEGATEDFROM_PARAMETER, + ICAL_DELEGATEDTO_PARAMETER, + ICAL_DIR_PARAMETER, + ICAL_ENCODING_PARAMETER, + ICAL_FBTYPE_PARAMETER, + ICAL_FMTTYPE_PARAMETER, + ICAL_LANGUAGE_PARAMETER, + ICAL_MEMBER_PARAMETER, + ICAL_PARTSTAT_PARAMETER, + ICAL_RANGE_PARAMETER, + ICAL_RELATED_PARAMETER, + ICAL_RELTYPE_PARAMETER, + ICAL_ROLE_PARAMETER, + ICAL_RSVP_PARAMETER, + ICAL_SENTBY_PARAMETER, + ICAL_TZID_PARAMETER, + ICAL_VALUE_PARAMETER, + ICAL_X_PARAMETER, + ICAL_XLICCOMPARETYPE_PARAMETER, + ICAL_XLICERRORTYPE_PARAMETER, + ICAL_NO_PARAMETER +} icalparameter_kind; + +#define ICALPARAMETER_FIRST_ENUM 20000 + +typedef enum icalparameter_cutype { + ICAL_CUTYPE_X = 20000, + ICAL_CUTYPE_INDIVIDUAL = 20001, + ICAL_CUTYPE_GROUP = 20002, + ICAL_CUTYPE_RESOURCE = 20003, + ICAL_CUTYPE_ROOM = 20004, + ICAL_CUTYPE_UNKNOWN = 20005, + ICAL_CUTYPE_NONE = 20006 +} icalparameter_cutype; + +typedef enum icalparameter_encoding { + ICAL_ENCODING_X = 20007, + ICAL_ENCODING_8BIT = 20008, + ICAL_ENCODING_BASE64 = 20009, + ICAL_ENCODING_NONE = 20010 +} icalparameter_encoding; + +typedef enum icalparameter_fbtype { + ICAL_FBTYPE_X = 20011, + ICAL_FBTYPE_FREE = 20012, + ICAL_FBTYPE_BUSY = 20013, + ICAL_FBTYPE_BUSYUNAVAILABLE = 20014, + ICAL_FBTYPE_BUSYTENTATIVE = 20015, + ICAL_FBTYPE_NONE = 20016 +} icalparameter_fbtype; + +typedef enum icalparameter_partstat { + ICAL_PARTSTAT_X = 20017, + ICAL_PARTSTAT_NEEDSACTION = 20018, + ICAL_PARTSTAT_ACCEPTED = 20019, + ICAL_PARTSTAT_DECLINED = 20020, + ICAL_PARTSTAT_TENTATIVE = 20021, + ICAL_PARTSTAT_DELEGATED = 20022, + ICAL_PARTSTAT_COMPLETED = 20023, + ICAL_PARTSTAT_INPROCESS = 20024, + ICAL_PARTSTAT_NONE = 20025 +} icalparameter_partstat; + +typedef enum icalparameter_range { + ICAL_RANGE_X = 20026, + ICAL_RANGE_THISANDPRIOR = 20027, + ICAL_RANGE_THISANDFUTURE = 20028, + ICAL_RANGE_NONE = 20029 +} icalparameter_range; + +typedef enum icalparameter_related { + ICAL_RELATED_X = 20030, + ICAL_RELATED_START = 20031, + ICAL_RELATED_END = 20032, + ICAL_RELATED_NONE = 20033 +} icalparameter_related; + +typedef enum icalparameter_reltype { + ICAL_RELTYPE_X = 20034, + ICAL_RELTYPE_PARENT = 20035, + ICAL_RELTYPE_CHILD = 20036, + ICAL_RELTYPE_SIBLING = 20037, + ICAL_RELTYPE_NONE = 20038 +} icalparameter_reltype; + +typedef enum icalparameter_role { + ICAL_ROLE_X = 20039, + ICAL_ROLE_CHAIR = 20040, + ICAL_ROLE_REQPARTICIPANT = 20041, + ICAL_ROLE_OPTPARTICIPANT = 20042, + ICAL_ROLE_NONPARTICIPANT = 20043, + ICAL_ROLE_NONE = 20044 +} icalparameter_role; + +typedef enum icalparameter_rsvp { + ICAL_RSVP_X = 20045, + ICAL_RSVP_TRUE = 20046, + ICAL_RSVP_FALSE = 20047, + ICAL_RSVP_NONE = 20048 +} icalparameter_rsvp; + +typedef enum icalparameter_value { + ICAL_VALUE_X = 20049, + ICAL_VALUE_BINARY = 20050, + ICAL_VALUE_BOOLEAN = 20051, + ICAL_VALUE_DATE = 20052, + ICAL_VALUE_DURATION = 20053, + ICAL_VALUE_FLOAT = 20054, + ICAL_VALUE_INTEGER = 20055, + ICAL_VALUE_PERIOD = 20056, + ICAL_VALUE_RECUR = 20057, + ICAL_VALUE_TEXT = 20058, + ICAL_VALUE_URI = 20059, + ICAL_VALUE_ERROR = 20060, + ICAL_VALUE_DATETIME = 20061, + ICAL_VALUE_UTCOFFSET = 20062, + ICAL_VALUE_CALADDRESS = 20063, + ICAL_VALUE_NONE = 20064 +} icalparameter_value; + +typedef enum icalparameter_xliccomparetype { + ICAL_XLICCOMPARETYPE_X = 20065, + ICAL_XLICCOMPARETYPE_EQUAL = 20066, + ICAL_XLICCOMPARETYPE_NOTEQUAL = 20067, + ICAL_XLICCOMPARETYPE_LESS = 20068, + ICAL_XLICCOMPARETYPE_GREATER = 20069, + ICAL_XLICCOMPARETYPE_LESSEQUAL = 20070, + ICAL_XLICCOMPARETYPE_GREATEREQUAL = 20071, + ICAL_XLICCOMPARETYPE_REGEX = 20072, + ICAL_XLICCOMPARETYPE_NONE = 20073 +} icalparameter_xliccomparetype; + +typedef enum icalparameter_xlicerrortype { + ICAL_XLICERRORTYPE_X = 20074, + ICAL_XLICERRORTYPE_COMPONENTPARSEERROR = 20075, + ICAL_XLICERRORTYPE_PROPERTYPARSEERROR = 20076, + ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR = 20077, + ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR = 20078, + ICAL_XLICERRORTYPE_VALUEPARSEERROR = 20079, + ICAL_XLICERRORTYPE_INVALIDITIP = 20080, + ICAL_XLICERRORTYPE_UNKNOWNVCALPROPERROR = 20081, + ICAL_XLICERRORTYPE_MIMEPARSEERROR = 20082, + ICAL_XLICERRORTYPE_NONE = 20083 +} icalparameter_xlicerrortype; + +#define ICALPARAMETER_LAST_ENUM 20084 + +/* DELEGATED-FROM */ +icalparameter* icalparameter_new_delegatedfrom(const char* v); +const char* icalparameter_get_delegatedfrom(icalparameter* value); +void icalparameter_set_delegatedfrom(icalparameter* value, const char* v); + +/* DELEGATED-TO */ +icalparameter* icalparameter_new_delegatedto(const char* v); +const char* icalparameter_get_delegatedto(icalparameter* value); +void icalparameter_set_delegatedto(icalparameter* value, const char* v); + +/* RANGE */ +icalparameter* icalparameter_new_range(icalparameter_range v); +icalparameter_range icalparameter_get_range(icalparameter* value); +void icalparameter_set_range(icalparameter* value, icalparameter_range v); + +/* ENCODING */ +icalparameter* icalparameter_new_encoding(icalparameter_encoding v); +icalparameter_encoding icalparameter_get_encoding(icalparameter* value); +void icalparameter_set_encoding(icalparameter* value, icalparameter_encoding v); + +/* RSVP */ +icalparameter* icalparameter_new_rsvp(icalparameter_rsvp v); +icalparameter_rsvp icalparameter_get_rsvp(icalparameter* value); +void icalparameter_set_rsvp(icalparameter* value, icalparameter_rsvp v); + +/* PARTSTAT */ +icalparameter* icalparameter_new_partstat(icalparameter_partstat v); +icalparameter_partstat icalparameter_get_partstat(icalparameter* value); +void icalparameter_set_partstat(icalparameter* value, icalparameter_partstat v); + +/* RELTYPE */ +icalparameter* icalparameter_new_reltype(icalparameter_reltype v); +icalparameter_reltype icalparameter_get_reltype(icalparameter* value); +void icalparameter_set_reltype(icalparameter* value, icalparameter_reltype v); + +/* CUTYPE */ +icalparameter* icalparameter_new_cutype(icalparameter_cutype v); +icalparameter_cutype icalparameter_get_cutype(icalparameter* value); +void icalparameter_set_cutype(icalparameter* value, icalparameter_cutype v); + +/* MEMBER */ +icalparameter* icalparameter_new_member(const char* v); +const char* icalparameter_get_member(icalparameter* value); +void icalparameter_set_member(icalparameter* value, const char* v); + +/* FMTTYPE */ +icalparameter* icalparameter_new_fmttype(const char* v); +const char* icalparameter_get_fmttype(icalparameter* value); +void icalparameter_set_fmttype(icalparameter* value, const char* v); + +/* SENT-BY */ +icalparameter* icalparameter_new_sentby(const char* v); +const char* icalparameter_get_sentby(icalparameter* value); +void icalparameter_set_sentby(icalparameter* value, const char* v); + +/* VALUE */ +icalparameter* icalparameter_new_value(icalparameter_value v); +icalparameter_value icalparameter_get_value(icalparameter* value); +void icalparameter_set_value(icalparameter* value, icalparameter_value v); + +/* ALTREP */ +icalparameter* icalparameter_new_altrep(const char* v); +const char* icalparameter_get_altrep(icalparameter* value); +void icalparameter_set_altrep(icalparameter* value, const char* v); + +/* DIR */ +icalparameter* icalparameter_new_dir(const char* v); +const char* icalparameter_get_dir(icalparameter* value); +void icalparameter_set_dir(icalparameter* value, const char* v); + +/* RELATED */ +icalparameter* icalparameter_new_related(icalparameter_related v); +icalparameter_related icalparameter_get_related(icalparameter* value); +void icalparameter_set_related(icalparameter* value, icalparameter_related v); + +/* CN */ +icalparameter* icalparameter_new_cn(const char* v); +const char* icalparameter_get_cn(icalparameter* value); +void icalparameter_set_cn(icalparameter* value, const char* v); + +/* X-LIC-ERRORTYPE */ +icalparameter* icalparameter_new_xlicerrortype(icalparameter_xlicerrortype v); +icalparameter_xlicerrortype icalparameter_get_xlicerrortype(icalparameter* value); +void icalparameter_set_xlicerrortype(icalparameter* value, icalparameter_xlicerrortype v); + +/* X */ +icalparameter* icalparameter_new_x(const char* v); +const char* icalparameter_get_x(icalparameter* value); +void icalparameter_set_x(icalparameter* value, const char* v); + +/* LANGUAGE */ +icalparameter* icalparameter_new_language(const char* v); +const char* icalparameter_get_language(icalparameter* value); +void icalparameter_set_language(icalparameter* value, const char* v); + +/* ROLE */ +icalparameter* icalparameter_new_role(icalparameter_role v); +icalparameter_role icalparameter_get_role(icalparameter* value); +void icalparameter_set_role(icalparameter* value, icalparameter_role v); + +/* X-LIC-COMPARETYPE */ +icalparameter* icalparameter_new_xliccomparetype(icalparameter_xliccomparetype v); +icalparameter_xliccomparetype icalparameter_get_xliccomparetype(icalparameter* value); +void icalparameter_set_xliccomparetype(icalparameter* value, icalparameter_xliccomparetype v); + +/* FBTYPE */ +icalparameter* icalparameter_new_fbtype(icalparameter_fbtype v); +icalparameter_fbtype icalparameter_get_fbtype(icalparameter* value); +void icalparameter_set_fbtype(icalparameter* value, icalparameter_fbtype v); + +/* TZID */ +icalparameter* icalparameter_new_tzid(const char* v); +const char* icalparameter_get_tzid(icalparameter* value); +void icalparameter_set_tzid(icalparameter* value, const char* v); + +#endif /*ICALPARAMETER_H*/ + diff --git a/libical/src/libical/icalderivedproperty.c b/libical/src/libical/icalderivedproperty.c new file mode 100644 index 0000000..b41562b --- a/dev/null +++ b/libical/src/libical/icalderivedproperty.c @@ -0,0 +1,2014 @@ +/* -*- Mode: C -*- */ + +/*====================================================================== + FILE: icalderivedproperty.c + CREATOR: eric 15 Feb 2001 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalproperty.c + +======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalproperty.h" +#include "icalcomponent.h" +#include "pvl.h" +#include "icalenums.h" +#include "icalerror.h" +#include "icalmemory.h" +#include "icalparser.h" + +#include <string.h> /* For icalmemory_strdup, rindex */ +#include <assert.h> +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> /* for printf */ +#include <stdarg.h> /* for va_list, va_start, etc. */ + +#define TMP_BUF_SIZE 1024 + +struct icalproperty_impl* +icalproperty_new_impl (icalproperty_kind kind); + +/* This map associates the property kinds with the string + representation of the property name and the kind of VALUE that the + property uses as a default */ + +struct icalproperty_map { + icalproperty_kind kind; + const char *name; + icalvalue_kind value; + +}; + +extern struct icalproperty_map property_map[]; +extern void icalproperty_add_parameters(struct icalproperty_impl *prop,va_list args); +const char* icalproperty_kind_to_string(icalproperty_kind kind) +{ + int i; + + for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) { + if (property_map[i].kind == kind) { + return property_map[i].name; + } + } + + return 0; + +} + + +icalproperty_kind icalproperty_string_to_kind(const char* string) +{ + int i; + + if (string ==0 ) { + return ICAL_NO_PROPERTY; + } + + + for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) { + if (strcmp(property_map[i].name, string) == 0) { + return property_map[i].kind; + } + } + + if(strncmp(string,"X-",2)==0){ + return ICAL_X_PROPERTY; + } + + + return ICAL_NO_PROPERTY; +} + + +icalvalue_kind icalproperty_value_kind_to_kind(icalvalue_kind kind) +{ + int i; + + for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) { + if ( property_map[i].value == kind ) { + return property_map[i].kind; + } + } + + return ICAL_NO_VALUE; +} + + + +icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind) +{ + int i; + + for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) { + if ( property_map[i].kind == kind ) { + return property_map[i].value; + } + } + + return ICAL_NO_VALUE; +} + + +/* This map associates the property enumerations with the king of + property that they are used in and the string representation of the + enumeration */ + +struct icalproperty_enum_map { + icalproperty_kind prop; + int prop_enum; + const char* str; +}; + +extern struct icalproperty_enum_map enum_map[]; + + +const char* icalproperty_enum_to_string(int e) +{ + icalerror_check_arg_rz(e >= ICALPROPERTY_FIRST_ENUM,"e"); + icalerror_check_arg_rz(e <= ICALPROPERTY_LAST_ENUM,"e"); + + return enum_map[e-ICALPROPERTY_FIRST_ENUM].str; +} + +int icalproperty_string_to_enum(const char* str) +{ + int i; + + icalerror_check_arg_rz(str!=0,"str") + + while(*str == ' '){ + str++; + } + + for (i=ICALPROPERTY_FIRST_ENUM; i != ICALPROPERTY_LAST_ENUM; i++) { + if ( strcmp(enum_map[i-ICALPROPERTY_FIRST_ENUM].str, str) == 0) { + return enum_map[i-ICALPROPERTY_FIRST_ENUM].prop_enum; + } + } + + return 0; +} + +int icalproperty_enum_belongs_to_property(icalproperty_kind kind, int e) +{ + int i; + + + for (i=ICALPROPERTY_FIRST_ENUM; i != ICALPROPERTY_LAST_ENUM; i++) { + if(enum_map[i-ICALPROPERTY_FIRST_ENUM].prop_enum == e && + enum_map[i-ICALPROPERTY_FIRST_ENUM].prop == kind ){ + return 1; + } + } + + return 0; +} + + +const char* icalproperty_method_to_string(icalproperty_method method) +{ + icalerror_check_arg_rz(method >= ICAL_METHOD_X,"method"); + icalerror_check_arg_rz(method <= ICAL_METHOD_NONE,"method"); + + return enum_map[method-ICALPROPERTY_FIRST_ENUM].str; +} + +icalproperty_method icalproperty_string_to_method(const char* str) +{ + int i; + + icalerror_check_arg_rx(str!=0,"str",ICAL_METHOD_NONE) + + while(*str == ' '){ + str++; + } + + for (i=ICAL_METHOD_X-ICALPROPERTY_FIRST_ENUM; + i != ICAL_METHOD_NONE-ICALPROPERTY_FIRST_ENUM; + i++) { + if ( strcmp(enum_map[i].str, str) == 0) { + return (icalproperty_method)enum_map[i].prop_enum; + } + } + + return ICAL_METHOD_NONE; +} + + +const char* icalenum_status_to_string(icalproperty_status status) +{ + icalerror_check_arg_rz(status >= ICAL_STATUS_X,"status"); + icalerror_check_arg_rz(status <= ICAL_STATUS_NONE,"status"); + + return enum_map[status-ICALPROPERTY_FIRST_ENUM].str; +} + +icalproperty_status icalenum_string_to_status(const char* str) +{ + int i; + + icalerror_check_arg_rx(str!=0,"str",ICAL_STATUS_NONE) + + while(*str == ' '){ + str++; + } + + for (i=ICAL_STATUS_X-ICALPROPERTY_FIRST_ENUM; + i != ICAL_STATUS_NONE-ICALPROPERTY_FIRST_ENUM; + i++) { + if ( strcmp(enum_map[i].str, str) == 0) { + return (icalproperty_method)enum_map[i].prop_enum; + } + } + + return ICAL_STATUS_NONE; + +} + + + +/* Everything below this line is machine generated. Do not edit. */ +static struct icalproperty_map property_map[] = { +{ICAL_ACTION_PROPERTY,"ACTION",ICAL_ACTION_VALUE}, +{ICAL_ANY_PROPERTY,"ANY",ICAL_NO_VALUE}, +{ICAL_ATTACH_PROPERTY,"ATTACH",ICAL_ATTACH_VALUE}, +{ICAL_ATTENDEE_PROPERTY,"ATTENDEE",ICAL_CALADDRESS_VALUE}, +{ICAL_CALSCALE_PROPERTY,"CALSCALE",ICAL_TEXT_VALUE}, +{ICAL_CATEGORIES_PROPERTY,"CATEGORIES",ICAL_TEXT_VALUE}, +{ICAL_CLASS_PROPERTY,"CLASS",ICAL_TEXT_VALUE}, +{ICAL_COMMENT_PROPERTY,"COMMENT",ICAL_TEXT_VALUE}, +{ICAL_COMPLETED_PROPERTY,"COMPLETED",ICAL_DATETIME_VALUE}, +{ICAL_CONTACT_PROPERTY,"CONTACT",ICAL_TEXT_VALUE}, +{ICAL_CREATED_PROPERTY,"CREATED",ICAL_DATETIME_VALUE}, +{ICAL_DESCRIPTION_PROPERTY,"DESCRIPTION",ICAL_TEXT_VALUE}, +{ICAL_DTEND_PROPERTY,"DTEND",ICAL_DATETIME_VALUE}, +{ICAL_DTSTAMP_PROPERTY,"DTSTAMP",ICAL_DATETIME_VALUE}, +{ICAL_DTSTART_PROPERTY,"DTSTART",ICAL_DATETIME_VALUE}, +{ICAL_DUE_PROPERTY,"DUE",ICAL_DATETIME_VALUE}, +{ICAL_DURATION_PROPERTY,"DURATION",ICAL_DURATION_VALUE}, +{ICAL_EXDATE_PROPERTY,"EXDATE",ICAL_DATETIME_VALUE}, +{ICAL_EXRULE_PROPERTY,"EXRULE",ICAL_RECUR_VALUE}, +{ICAL_FREEBUSY_PROPERTY,"FREEBUSY",ICAL_PERIOD_VALUE}, +{ICAL_GEO_PROPERTY,"GEO",ICAL_GEO_VALUE}, +{ICAL_LASTMODIFIED_PROPERTY,"LAST-MODIFIED",ICAL_DATETIME_VALUE}, +{ICAL_LOCATION_PROPERTY,"LOCATION",ICAL_TEXT_VALUE}, +{ICAL_MAXRESULTS_PROPERTY,"MAXRESULTS",ICAL_INTEGER_VALUE}, +{ICAL_MAXRESULTSSIZE_PROPERTY,"MAXRESULTSSIZE",ICAL_INTEGER_VALUE}, +{ICAL_METHOD_PROPERTY,"METHOD",ICAL_METHOD_VALUE}, +{ICAL_ORGANIZER_PROPERTY,"ORGANIZER",ICAL_CALADDRESS_VALUE}, +{ICAL_PERCENTCOMPLETE_PROPERTY,"PERCENT-COMPLETE",ICAL_INTEGER_VALUE}, +{ICAL_PRIORITY_PROPERTY,"PRIORITY",ICAL_INTEGER_VALUE}, +{ICAL_PRODID_PROPERTY,"PRODID",ICAL_TEXT_VALUE}, +{ICAL_QUERY_PROPERTY,"QUERY",ICAL_QUERY_VALUE}, +{ICAL_QUERYNAME_PROPERTY,"QUERYNAME",ICAL_TEXT_VALUE}, +{ICAL_RDATE_PROPERTY,"RDATE",ICAL_DATETIMEPERIOD_VALUE}, +{ICAL_RECURRENCEID_PROPERTY,"RECURRENCE-ID",ICAL_DATETIME_VALUE}, +{ICAL_RELATEDTO_PROPERTY,"RELATED-TO",ICAL_TEXT_VALUE}, +{ICAL_REPEAT_PROPERTY,"REPEAT",ICAL_INTEGER_VALUE}, +{ICAL_REQUESTSTATUS_PROPERTY,"REQUEST-STATUS",ICAL_REQUESTSTATUS_VALUE}, +{ICAL_RESOURCES_PROPERTY,"RESOURCES",ICAL_TEXT_VALUE}, +{ICAL_RRULE_PROPERTY,"RRULE",ICAL_RECUR_VALUE}, +{ICAL_SCOPE_PROPERTY,"SCOPE",ICAL_TEXT_VALUE}, +{ICAL_SEQUENCE_PROPERTY,"SEQUENCE",ICAL_INTEGER_VALUE}, +{ICAL_STATUS_PROPERTY,"STATUS",ICAL_STATUS_VALUE}, +{ICAL_SUMMARY_PROPERTY,"SUMMARY",ICAL_TEXT_VALUE}, +{ICAL_TARGET_PROPERTY,"TARGET",ICAL_CALADDRESS_VALUE}, +{ICAL_TRANSP_PROPERTY,"TRANSP",ICAL_TEXT_VALUE}, +{ICAL_TRIGGER_PROPERTY,"TRIGGER",ICAL_TRIGGER_VALUE}, +{ICAL_TZID_PROPERTY,"TZID",ICAL_TEXT_VALUE}, +{ICAL_TZNAME_PROPERTY,"TZNAME",ICAL_TEXT_VALUE}, +{ICAL_TZOFFSETFROM_PROPERTY,"TZOFFSETFROM",ICAL_UTCOFFSET_VALUE}, +{ICAL_TZOFFSETTO_PROPERTY,"TZOFFSETTO",ICAL_UTCOFFSET_VALUE}, +{ICAL_TZURL_PROPERTY,"TZURL",ICAL_URI_VALUE}, +{ICAL_UID_PROPERTY,"UID",ICAL_TEXT_VALUE}, +{ICAL_URL_PROPERTY,"URL",ICAL_URI_VALUE}, +{ICAL_VERSION_PROPERTY,"VERSION",ICAL_TEXT_VALUE}, +{ICAL_X_PROPERTY,"X",ICAL_TEXT_VALUE}, +{ICAL_XLICCLUSTERCOUNT_PROPERTY,"X-LIC-CLUSTERCOUNT",ICAL_STRING_VALUE}, +{ICAL_XLICERROR_PROPERTY,"X-LIC-ERROR",ICAL_TEXT_VALUE}, +{ICAL_XLICMIMECHARSET_PROPERTY,"X-LIC-MIMECHARSET",ICAL_STRING_VALUE}, +{ICAL_XLICMIMECID_PROPERTY,"X-LIC-MIMECID",ICAL_STRING_VALUE}, +{ICAL_XLICMIMECONTENTTYPE_PROPERTY,"X-LIC-MIMECONTENTTYPE",ICAL_STRING_VALUE}, +{ICAL_XLICMIMEENCODING_PROPERTY,"X-LIC-MIMEENCODING",ICAL_STRING_VALUE}, +{ICAL_XLICMIMEFILENAME_PROPERTY,"X-LIC-MIMEFILENAME",ICAL_STRING_VALUE}, +{ICAL_XLICMIMEOPTINFO_PROPERTY,"X-LIC-MIMEOPTINFO",ICAL_STRING_VALUE}, +{ICAL_NO_PROPERTY,"",ICAL_NO_VALUE}}; + +static struct icalproperty_enum_map enum_map[] = { + {ICAL_ACTION_PROPERTY,ICAL_ACTION_X,"" }, /*10000*/ + {ICAL_ACTION_PROPERTY,ICAL_ACTION_AUDIO,"AUDIO" }, /*10001*/ + {ICAL_ACTION_PROPERTY,ICAL_ACTION_DISPLAY,"DISPLAY" }, /*10002*/ + {ICAL_ACTION_PROPERTY,ICAL_ACTION_EMAIL,"EMAIL" }, /*10003*/ + {ICAL_ACTION_PROPERTY,ICAL_ACTION_PROCEDURE,"PROCEDURE" }, /*10004*/ + {ICAL_ACTION_PROPERTY,ICAL_ACTION_NONE,"" }, /*10005*/ + {ICAL_CLASS_PROPERTY,ICAL_CLASS_X,"" }, /*10006*/ + {ICAL_CLASS_PROPERTY,ICAL_CLASS_PUBLIC,"PUBLIC" }, /*10007*/ + {ICAL_CLASS_PROPERTY,ICAL_CLASS_PRIVATE,"PRIVATE" }, /*10008*/ + {ICAL_CLASS_PROPERTY,ICAL_CLASS_CONFIDENTIAL,"CONFIDENTIAL" }, /*10009*/ + {ICAL_CLASS_PROPERTY,ICAL_CLASS_NONE,"" }, /*10010*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_X,"" }, /*10011*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_PUBLISH,"PUBLISH" }, /*10012*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_REQUEST,"REQUEST" }, /*10013*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_REPLY,"REPLY" }, /*10014*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_ADD,"ADD" }, /*10015*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_CANCEL,"CANCEL" }, /*10016*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_REFRESH,"REFRESH" }, /*10017*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_COUNTER,"COUNTER" }, /*10018*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_DECLINECOUNTER,"DECLINECOUNTER" }, /*10019*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_CREATE,"CREATE" }, /*10020*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_READ,"READ" }, /*10021*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_RESPONSE,"RESPONSE" }, /*10022*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_MOVE,"MOVE" }, /*10023*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_MODIFY,"MODIFY" }, /*10024*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_GENERATEUID,"GENERATEUID" }, /*10025*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_DELETE,"DELETE" }, /*10026*/ + {ICAL_METHOD_PROPERTY,ICAL_METHOD_NONE,"" }, /*10027*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_X,"" }, /*10028*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_TENTATIVE,"TENTATIVE" }, /*10029*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_CONFIRMED,"CONFIRMED" }, /*10030*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_COMPLETED,"COMPLETED" }, /*10031*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_NEEDSACTION,"NEEDS-ACTION" }, /*10032*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_CANCELLED,"CANCELLED" }, /*10033*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_INPROCESS,"IN-PROCESS" }, /*10034*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_DRAFT,"DRAFT" }, /*10035*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_FINAL,"FINAL" }, /*10036*/ + {ICAL_STATUS_PROPERTY,ICAL_STATUS_NONE,"" }, /*10037*/ + {ICAL_TRANSP_PROPERTY,ICAL_TRANSP_X,"" }, /*10038*/ + {ICAL_TRANSP_PROPERTY,ICAL_TRANSP_OPAQUE,"OPAQUE" }, /*10039*/ + {ICAL_TRANSP_PROPERTY,ICAL_TRANSP_TRANSPARENT,"TRANSPARENT" }, /*10040*/ + {ICAL_TRANSP_PROPERTY,ICAL_TRANSP_NONE,"" }, /*10041*/ + {ICAL_NO_PROPERTY,0,""} +}; + +icalproperty* icalproperty_vanew_action(enum icalproperty_action v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_ACTION_PROPERTY); + icalproperty_set_action((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* ACTION */ +icalproperty* icalproperty_new_action(enum icalproperty_action v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_ACTION_PROPERTY); + icalproperty_set_action((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_action(icalproperty* prop, enum icalproperty_action v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_action(v)); +} +enum icalproperty_action icalproperty_get_action(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_action(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_attach(struct icalattachtype* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_ATTACH_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_attach((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* ATTACH */ +icalproperty* icalproperty_new_attach(struct icalattachtype* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_ATTACH_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_attach((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_attach(icalproperty* prop, struct icalattachtype* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_attach(v)); +} +struct icalattachtype* icalproperty_get_attach(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_attach(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_attendee(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_ATTENDEE_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_attendee((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* ATTENDEE */ +icalproperty* icalproperty_new_attendee(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_ATTENDEE_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_attendee((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_attendee(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_caladdress(v)); +} +const char* icalproperty_get_attendee(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_caladdress(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_calscale(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CALSCALE_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_calscale((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* CALSCALE */ +icalproperty* icalproperty_new_calscale(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CALSCALE_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_calscale((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_calscale(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_calscale(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_categories(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CATEGORIES_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_categories((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* CATEGORIES */ +icalproperty* icalproperty_new_categories(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CATEGORIES_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_categories((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_categories(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_categories(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_class(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CLASS_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_class((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* CLASS */ +icalproperty* icalproperty_new_class(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CLASS_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_class((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_class(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_class(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_comment(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_COMMENT_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_comment((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* COMMENT */ +icalproperty* icalproperty_new_comment(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_COMMENT_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_comment((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_comment(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_comment(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_completed(struct icaltimetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_COMPLETED_PROPERTY); + icalproperty_set_completed((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* COMPLETED */ +icalproperty* icalproperty_new_completed(struct icaltimetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_COMPLETED_PROPERTY); + icalproperty_set_completed((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_completed(icalproperty* prop, struct icaltimetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetime(v)); +} +struct icaltimetype icalproperty_get_completed(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetime(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_contact(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CONTACT_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_contact((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* CONTACT */ +icalproperty* icalproperty_new_contact(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CONTACT_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_contact((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_contact(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_contact(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_created(struct icaltimetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CREATED_PROPERTY); + icalproperty_set_created((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* CREATED */ +icalproperty* icalproperty_new_created(struct icaltimetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_CREATED_PROPERTY); + icalproperty_set_created((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_created(icalproperty* prop, struct icaltimetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetime(v)); +} +struct icaltimetype icalproperty_get_created(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetime(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_description(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DESCRIPTION_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_description((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* DESCRIPTION */ +icalproperty* icalproperty_new_description(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DESCRIPTION_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_description((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_description(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_description(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_dtend(struct icaltimetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DTEND_PROPERTY); + icalproperty_set_dtend((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* DTEND */ +icalproperty* icalproperty_new_dtend(struct icaltimetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DTEND_PROPERTY); + icalproperty_set_dtend((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_dtend(icalproperty* prop, struct icaltimetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetime(v)); +} +struct icaltimetype icalproperty_get_dtend(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetime(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_dtstamp(struct icaltimetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DTSTAMP_PROPERTY); + icalproperty_set_dtstamp((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* DTSTAMP */ +icalproperty* icalproperty_new_dtstamp(struct icaltimetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DTSTAMP_PROPERTY); + icalproperty_set_dtstamp((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_dtstamp(icalproperty* prop, struct icaltimetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetime(v)); +} +struct icaltimetype icalproperty_get_dtstamp(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetime(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_dtstart(struct icaltimetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DTSTART_PROPERTY); + icalproperty_set_dtstart((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* DTSTART */ +icalproperty* icalproperty_new_dtstart(struct icaltimetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DTSTART_PROPERTY); + icalproperty_set_dtstart((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_dtstart(icalproperty* prop, struct icaltimetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetime(v)); +} +struct icaltimetype icalproperty_get_dtstart(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetime(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_due(struct icaltimetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DUE_PROPERTY); + icalproperty_set_due((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* DUE */ +icalproperty* icalproperty_new_due(struct icaltimetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DUE_PROPERTY); + icalproperty_set_due((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_due(icalproperty* prop, struct icaltimetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetime(v)); +} +struct icaltimetype icalproperty_get_due(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetime(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_duration(struct icaldurationtype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DURATION_PROPERTY); + icalproperty_set_duration((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* DURATION */ +icalproperty* icalproperty_new_duration(struct icaldurationtype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_DURATION_PROPERTY); + icalproperty_set_duration((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_duration(icalproperty* prop, struct icaldurationtype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_duration(v)); +} +struct icaldurationtype icalproperty_get_duration(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_duration(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_exdate(struct icaltimetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_EXDATE_PROPERTY); + icalproperty_set_exdate((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* EXDATE */ +icalproperty* icalproperty_new_exdate(struct icaltimetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_EXDATE_PROPERTY); + icalproperty_set_exdate((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_exdate(icalproperty* prop, struct icaltimetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetime(v)); +} +struct icaltimetype icalproperty_get_exdate(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetime(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_exrule(struct icalrecurrencetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_EXRULE_PROPERTY); + icalproperty_set_exrule((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* EXRULE */ +icalproperty* icalproperty_new_exrule(struct icalrecurrencetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_EXRULE_PROPERTY); + icalproperty_set_exrule((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_exrule(icalproperty* prop, struct icalrecurrencetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_recur(v)); +} +struct icalrecurrencetype icalproperty_get_exrule(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_recur(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_freebusy(struct icalperiodtype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_FREEBUSY_PROPERTY); + icalproperty_set_freebusy((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* FREEBUSY */ +icalproperty* icalproperty_new_freebusy(struct icalperiodtype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_FREEBUSY_PROPERTY); + icalproperty_set_freebusy((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_freebusy(icalproperty* prop, struct icalperiodtype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_period(v)); +} +struct icalperiodtype icalproperty_get_freebusy(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_period(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_geo(struct icalgeotype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_GEO_PROPERTY); + icalproperty_set_geo((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* GEO */ +icalproperty* icalproperty_new_geo(struct icalgeotype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_GEO_PROPERTY); + icalproperty_set_geo((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_geo(icalproperty* prop, struct icalgeotype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_geo(v)); +} +struct icalgeotype icalproperty_get_geo(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_geo(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_lastmodified(struct icaltimetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_LASTMODIFIED_PROPERTY); + icalproperty_set_lastmodified((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* LAST-MODIFIED */ +icalproperty* icalproperty_new_lastmodified(struct icaltimetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_LASTMODIFIED_PROPERTY); + icalproperty_set_lastmodified((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_lastmodified(icalproperty* prop, struct icaltimetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetime(v)); +} +struct icaltimetype icalproperty_get_lastmodified(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetime(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_location(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_LOCATION_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_location((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* LOCATION */ +icalproperty* icalproperty_new_location(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_LOCATION_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_location((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_location(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_location(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_maxresults(int v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_MAXRESULTS_PROPERTY); + icalproperty_set_maxresults((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* MAXRESULTS */ +icalproperty* icalproperty_new_maxresults(int v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_MAXRESULTS_PROPERTY); + icalproperty_set_maxresults((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_maxresults(icalproperty* prop, int v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_integer(v)); +} +int icalproperty_get_maxresults(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_integer(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_maxresultssize(int v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_MAXRESULTSSIZE_PROPERTY); + icalproperty_set_maxresultssize((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* MAXRESULTSSIZE */ +icalproperty* icalproperty_new_maxresultssize(int v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_MAXRESULTSSIZE_PROPERTY); + icalproperty_set_maxresultssize((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_maxresultssize(icalproperty* prop, int v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_integer(v)); +} +int icalproperty_get_maxresultssize(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_integer(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_method(enum icalproperty_method v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_METHOD_PROPERTY); + icalproperty_set_method((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* METHOD */ +icalproperty* icalproperty_new_method(enum icalproperty_method v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_METHOD_PROPERTY); + icalproperty_set_method((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_method(icalproperty* prop, enum icalproperty_method v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_method(v)); +} +enum icalproperty_method icalproperty_get_method(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_method(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_organizer(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_ORGANIZER_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_organizer((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* ORGANIZER */ +icalproperty* icalproperty_new_organizer(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_ORGANIZER_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_organizer((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_organizer(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_caladdress(v)); +} +const char* icalproperty_get_organizer(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_caladdress(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_percentcomplete(int v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_PERCENTCOMPLETE_PROPERTY); + icalproperty_set_percentcomplete((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* PERCENT-COMPLETE */ +icalproperty* icalproperty_new_percentcomplete(int v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_PERCENTCOMPLETE_PROPERTY); + icalproperty_set_percentcomplete((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_percentcomplete(icalproperty* prop, int v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_integer(v)); +} +int icalproperty_get_percentcomplete(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_integer(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_priority(int v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_PRIORITY_PROPERTY); + icalproperty_set_priority((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* PRIORITY */ +icalproperty* icalproperty_new_priority(int v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_PRIORITY_PROPERTY); + icalproperty_set_priority((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_priority(icalproperty* prop, int v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_integer(v)); +} +int icalproperty_get_priority(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_integer(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_prodid(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_PRODID_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_prodid((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* PRODID */ +icalproperty* icalproperty_new_prodid(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_PRODID_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_prodid((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_prodid(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_prodid(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_query(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_QUERY_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_query((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* QUERY */ +icalproperty* icalproperty_new_query(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_QUERY_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_query((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_query(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_query(v)); +} +const char* icalproperty_get_query(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_query(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_queryname(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_QUERYNAME_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_queryname((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* QUERYNAME */ +icalproperty* icalproperty_new_queryname(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_QUERYNAME_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_queryname((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_queryname(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_queryname(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_rdate(struct icaldatetimeperiodtype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RDATE_PROPERTY); + icalproperty_set_rdate((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* RDATE */ +icalproperty* icalproperty_new_rdate(struct icaldatetimeperiodtype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RDATE_PROPERTY); + icalproperty_set_rdate((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_rdate(icalproperty* prop, struct icaldatetimeperiodtype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetimeperiod(v)); +} +struct icaldatetimeperiodtype icalproperty_get_rdate(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetimeperiod(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_recurrenceid(struct icaltimetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RECURRENCEID_PROPERTY); + icalproperty_set_recurrenceid((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* RECURRENCE-ID */ +icalproperty* icalproperty_new_recurrenceid(struct icaltimetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RECURRENCEID_PROPERTY); + icalproperty_set_recurrenceid((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_recurrenceid(icalproperty* prop, struct icaltimetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_datetime(v)); +} +struct icaltimetype icalproperty_get_recurrenceid(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_datetime(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_relatedto(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RELATEDTO_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_relatedto((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* RELATED-TO */ +icalproperty* icalproperty_new_relatedto(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RELATEDTO_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_relatedto((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_relatedto(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_relatedto(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_repeat(int v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_REPEAT_PROPERTY); + icalproperty_set_repeat((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* REPEAT */ +icalproperty* icalproperty_new_repeat(int v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_REPEAT_PROPERTY); + icalproperty_set_repeat((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_repeat(icalproperty* prop, int v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_integer(v)); +} +int icalproperty_get_repeat(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_integer(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_requeststatus(struct icalreqstattype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_REQUESTSTATUS_PROPERTY); + icalproperty_set_requeststatus((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* REQUEST-STATUS */ +icalproperty* icalproperty_new_requeststatus(struct icalreqstattype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_REQUESTSTATUS_PROPERTY); + icalproperty_set_requeststatus((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_requeststatus(icalproperty* prop, struct icalreqstattype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_requeststatus(v)); +} +struct icalreqstattype icalproperty_get_requeststatus(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_requeststatus(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_resources(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RESOURCES_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_resources((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* RESOURCES */ +icalproperty* icalproperty_new_resources(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RESOURCES_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_resources((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_resources(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_resources(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_rrule(struct icalrecurrencetype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RRULE_PROPERTY); + icalproperty_set_rrule((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* RRULE */ +icalproperty* icalproperty_new_rrule(struct icalrecurrencetype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_RRULE_PROPERTY); + icalproperty_set_rrule((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_rrule(icalproperty* prop, struct icalrecurrencetype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_recur(v)); +} +struct icalrecurrencetype icalproperty_get_rrule(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_recur(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_scope(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_SCOPE_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_scope((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* SCOPE */ +icalproperty* icalproperty_new_scope(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_SCOPE_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_scope((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_scope(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_scope(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_sequence(int v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_SEQUENCE_PROPERTY); + icalproperty_set_sequence((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* SEQUENCE */ +icalproperty* icalproperty_new_sequence(int v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_SEQUENCE_PROPERTY); + icalproperty_set_sequence((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_sequence(icalproperty* prop, int v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_integer(v)); +} +int icalproperty_get_sequence(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_integer(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_status(enum icalproperty_status v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_STATUS_PROPERTY); + icalproperty_set_status((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* STATUS */ +icalproperty* icalproperty_new_status(enum icalproperty_status v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_STATUS_PROPERTY); + icalproperty_set_status((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_status(icalproperty* prop, enum icalproperty_status v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_status(v)); +} +enum icalproperty_status icalproperty_get_status(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_status(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_summary(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_SUMMARY_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_summary((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* SUMMARY */ +icalproperty* icalproperty_new_summary(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_SUMMARY_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_summary((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_summary(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_summary(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_target(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TARGET_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_target((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* TARGET */ +icalproperty* icalproperty_new_target(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TARGET_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_target((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_target(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_caladdress(v)); +} +const char* icalproperty_get_target(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_caladdress(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_transp(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TRANSP_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_transp((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* TRANSP */ +icalproperty* icalproperty_new_transp(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TRANSP_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_transp((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_transp(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_transp(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_trigger(struct icaltriggertype v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TRIGGER_PROPERTY); + icalproperty_set_trigger((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* TRIGGER */ +icalproperty* icalproperty_new_trigger(struct icaltriggertype v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TRIGGER_PROPERTY); + icalproperty_set_trigger((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_trigger(icalproperty* prop, struct icaltriggertype v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_trigger(v)); +} +struct icaltriggertype icalproperty_get_trigger(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_trigger(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_tzid(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZID_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_tzid((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* TZID */ +icalproperty* icalproperty_new_tzid(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZID_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_tzid((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_tzid(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_tzid(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_tzname(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZNAME_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_tzname((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* TZNAME */ +icalproperty* icalproperty_new_tzname(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZNAME_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_tzname((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_tzname(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_tzname(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_tzoffsetfrom(int v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZOFFSETFROM_PROPERTY); + icalproperty_set_tzoffsetfrom((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* TZOFFSETFROM */ +icalproperty* icalproperty_new_tzoffsetfrom(int v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZOFFSETFROM_PROPERTY); + icalproperty_set_tzoffsetfrom((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_tzoffsetfrom(icalproperty* prop, int v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_utcoffset(v)); +} +int icalproperty_get_tzoffsetfrom(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_utcoffset(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_tzoffsetto(int v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZOFFSETTO_PROPERTY); + icalproperty_set_tzoffsetto((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* TZOFFSETTO */ +icalproperty* icalproperty_new_tzoffsetto(int v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZOFFSETTO_PROPERTY); + icalproperty_set_tzoffsetto((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_tzoffsetto(icalproperty* prop, int v){ + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_utcoffset(v)); +} +int icalproperty_get_tzoffsetto(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_utcoffset(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_tzurl(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZURL_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_tzurl((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* TZURL */ +icalproperty* icalproperty_new_tzurl(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_TZURL_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_tzurl((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_tzurl(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_uri(v)); +} +const char* icalproperty_get_tzurl(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_uri(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_uid(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_UID_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_uid((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* UID */ +icalproperty* icalproperty_new_uid(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_UID_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_uid((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_uid(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_uid(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_url(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_URL_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_url((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* URL */ +icalproperty* icalproperty_new_url(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_URL_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_url((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_url(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_uri(v)); +} +const char* icalproperty_get_url(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_uri(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_version(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_VERSION_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_version((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* VERSION */ +icalproperty* icalproperty_new_version(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_VERSION_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_version((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_version(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_version(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_x(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_X_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_x((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* X */ +icalproperty* icalproperty_new_x(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_X_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_x((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_x(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_x(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_xlicclustercount(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICCLUSTERCOUNT_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicclustercount((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* X-LIC-CLUSTERCOUNT */ +icalproperty* icalproperty_new_xlicclustercount(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICCLUSTERCOUNT_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicclustercount((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_xlicclustercount(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_string(v)); +} +const char* icalproperty_get_xlicclustercount(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_string(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_xlicerror(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICERROR_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicerror((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* X-LIC-ERROR */ +icalproperty* icalproperty_new_xlicerror(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICERROR_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicerror((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_xlicerror(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_text(v)); +} +const char* icalproperty_get_xlicerror(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_text(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_xlicmimecharset(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMECHARSET_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimecharset((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* X-LIC-MIMECHARSET */ +icalproperty* icalproperty_new_xlicmimecharset(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMECHARSET_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimecharset((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_xlicmimecharset(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_string(v)); +} +const char* icalproperty_get_xlicmimecharset(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_string(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_xlicmimecid(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMECID_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimecid((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* X-LIC-MIMECID */ +icalproperty* icalproperty_new_xlicmimecid(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMECID_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimecid((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_xlicmimecid(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_string(v)); +} +const char* icalproperty_get_xlicmimecid(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_string(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_xlicmimecontenttype(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMECONTENTTYPE_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimecontenttype((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* X-LIC-MIMECONTENTTYPE */ +icalproperty* icalproperty_new_xlicmimecontenttype(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMECONTENTTYPE_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimecontenttype((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_xlicmimecontenttype(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_string(v)); +} +const char* icalproperty_get_xlicmimecontenttype(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_string(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_xlicmimeencoding(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMEENCODING_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimeencoding((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* X-LIC-MIMEENCODING */ +icalproperty* icalproperty_new_xlicmimeencoding(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMEENCODING_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimeencoding((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_xlicmimeencoding(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_string(v)); +} +const char* icalproperty_get_xlicmimeencoding(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_string(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_xlicmimefilename(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMEFILENAME_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimefilename((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* X-LIC-MIMEFILENAME */ +icalproperty* icalproperty_new_xlicmimefilename(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMEFILENAME_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimefilename((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_xlicmimefilename(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_string(v)); +} +const char* icalproperty_get_xlicmimefilename(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_string(icalproperty_get_value(prop)); +} +icalproperty* icalproperty_vanew_xlicmimeoptinfo(const char* v, ...){ + va_list args; + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMEOPTINFO_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimeoptinfo((icalproperty*)impl,v); + va_start(args,v); + icalproperty_add_parameters(impl, args); + va_end(args); + return (icalproperty*)impl; +} +/* X-LIC-MIMEOPTINFO */ +icalproperty* icalproperty_new_xlicmimeoptinfo(const char* v) { + struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_XLICMIMEOPTINFO_PROPERTY); icalerror_check_arg_rz( (v!=0),"v"); + + icalproperty_set_xlicmimeoptinfo((icalproperty*)impl,v); + return (icalproperty*)impl; +} + +void icalproperty_set_xlicmimeoptinfo(icalproperty* prop, const char* v){ + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalproperty_set_value(prop,icalvalue_new_string(v)); +} +const char* icalproperty_get_xlicmimeoptinfo(icalproperty* prop){ + icalerror_check_arg( (prop!=0),"prop"); + return icalvalue_get_string(icalproperty_get_value(prop)); +} diff --git a/libical/src/libical/icalderivedproperty.h b/libical/src/libical/icalderivedproperty.h new file mode 100644 index 0000000..07e01b0 --- a/dev/null +++ b/libical/src/libical/icalderivedproperty.h @@ -0,0 +1,403 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalderivedproperties.{c,h} + CREATOR: eric 09 May 1999 + + $Id$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + ======================================================================*/ + + +#ifndef ICALDERIVEDPROPERTY_H +#define ICALDERIVEDPROPERTY_H + +#include <time.h> +#include "icalparameter.h" +#include "icalderivedvalue.h" +#include "icalrecur.h" + +typedef void icalproperty; + + +/* Everything below this line is machine generated. Do not edit. */ +typedef enum icalproperty_kind { + ICAL_ANY_PROPERTY = 0, + ICAL_ACTION_PROPERTY, + ICAL_ATTACH_PROPERTY, + ICAL_ATTENDEE_PROPERTY, + ICAL_CALSCALE_PROPERTY, + ICAL_CATEGORIES_PROPERTY, + ICAL_CLASS_PROPERTY, + ICAL_COMMENT_PROPERTY, + ICAL_COMPLETED_PROPERTY, + ICAL_CONTACT_PROPERTY, + ICAL_CREATED_PROPERTY, + ICAL_DESCRIPTION_PROPERTY, + ICAL_DTEND_PROPERTY, + ICAL_DTSTAMP_PROPERTY, + ICAL_DTSTART_PROPERTY, + ICAL_DUE_PROPERTY, + ICAL_DURATION_PROPERTY, + ICAL_EXDATE_PROPERTY, + ICAL_EXRULE_PROPERTY, + ICAL_FREEBUSY_PROPERTY, + ICAL_GEO_PROPERTY, + ICAL_LASTMODIFIED_PROPERTY, + ICAL_LOCATION_PROPERTY, + ICAL_MAXRESULTS_PROPERTY, + ICAL_MAXRESULTSSIZE_PROPERTY, + ICAL_METHOD_PROPERTY, + ICAL_ORGANIZER_PROPERTY, + ICAL_PERCENTCOMPLETE_PROPERTY, + ICAL_PRIORITY_PROPERTY, + ICAL_PRODID_PROPERTY, + ICAL_QUERY_PROPERTY, + ICAL_QUERYNAME_PROPERTY, + ICAL_RDATE_PROPERTY, + ICAL_RECURRENCEID_PROPERTY, + ICAL_RELATEDTO_PROPERTY, + ICAL_REPEAT_PROPERTY, + ICAL_REQUESTSTATUS_PROPERTY, + ICAL_RESOURCES_PROPERTY, + ICAL_RRULE_PROPERTY, + ICAL_SCOPE_PROPERTY, + ICAL_SEQUENCE_PROPERTY, + ICAL_STATUS_PROPERTY, + ICAL_SUMMARY_PROPERTY, + ICAL_TARGET_PROPERTY, + ICAL_TRANSP_PROPERTY, + ICAL_TRIGGER_PROPERTY, + ICAL_TZID_PROPERTY, + ICAL_TZNAME_PROPERTY, + ICAL_TZOFFSETFROM_PROPERTY, + ICAL_TZOFFSETTO_PROPERTY, + ICAL_TZURL_PROPERTY, + ICAL_UID_PROPERTY, + ICAL_URL_PROPERTY, + ICAL_VERSION_PROPERTY, + ICAL_X_PROPERTY, + ICAL_XLICCLUSTERCOUNT_PROPERTY, + ICAL_XLICERROR_PROPERTY, + ICAL_XLICMIMECHARSET_PROPERTY, + ICAL_XLICMIMECID_PROPERTY, + ICAL_XLICMIMECONTENTTYPE_PROPERTY, + ICAL_XLICMIMEENCODING_PROPERTY, + ICAL_XLICMIMEFILENAME_PROPERTY, + ICAL_XLICMIMEOPTINFO_PROPERTY, + ICAL_NO_PROPERTY +} icalproperty_kind; + +icalproperty* icalproperty_vanew_action(enum icalproperty_action v, ...); + +/* ACTION */ +icalproperty* icalproperty_new_action(enum icalproperty_action v); +void icalproperty_set_action(icalproperty* prop, enum icalproperty_action v); +enum icalproperty_action icalproperty_get_action(icalproperty* prop);icalproperty* icalproperty_vanew_attach(struct icalattachtype* v, ...); + +/* ATTACH */ +icalproperty* icalproperty_new_attach(struct icalattachtype* v); +void icalproperty_set_attach(icalproperty* prop, struct icalattachtype* v); +struct icalattachtype* icalproperty_get_attach(icalproperty* prop);icalproperty* icalproperty_vanew_attendee(const char* v, ...); + +/* ATTENDEE */ +icalproperty* icalproperty_new_attendee(const char* v); +void icalproperty_set_attendee(icalproperty* prop, const char* v); +const char* icalproperty_get_attendee(icalproperty* prop);icalproperty* icalproperty_vanew_calscale(const char* v, ...); + +/* CALSCALE */ +icalproperty* icalproperty_new_calscale(const char* v); +void icalproperty_set_calscale(icalproperty* prop, const char* v); +const char* icalproperty_get_calscale(icalproperty* prop);icalproperty* icalproperty_vanew_categories(const char* v, ...); + +/* CATEGORIES */ +icalproperty* icalproperty_new_categories(const char* v); +void icalproperty_set_categories(icalproperty* prop, const char* v); +const char* icalproperty_get_categories(icalproperty* prop);icalproperty* icalproperty_vanew_class(const char* v, ...); + +/* CLASS */ +icalproperty* icalproperty_new_class(const char* v); +void icalproperty_set_class(icalproperty* prop, const char* v); +const char* icalproperty_get_class(icalproperty* prop);icalproperty* icalproperty_vanew_comment(const char* v, ...); + +/* COMMENT */ +icalproperty* icalproperty_new_comment(const char* v); +void icalproperty_set_comment(icalproperty* prop, const char* v); +const char* icalproperty_get_comment(icalproperty* prop);icalproperty* icalproperty_vanew_completed(struct icaltimetype v, ...); + +/* COMPLETED */ +icalproperty* icalproperty_new_completed(struct icaltimetype v); +void icalproperty_set_completed(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_completed(icalproperty* prop);icalproperty* icalproperty_vanew_contact(const char* v, ...); + +/* CONTACT */ +icalproperty* icalproperty_new_contact(const char* v); +void icalproperty_set_contact(icalproperty* prop, const char* v); +const char* icalproperty_get_contact(icalproperty* prop);icalproperty* icalproperty_vanew_created(struct icaltimetype v, ...); + +/* CREATED */ +icalproperty* icalproperty_new_created(struct icaltimetype v); +void icalproperty_set_created(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_created(icalproperty* prop);icalproperty* icalproperty_vanew_description(const char* v, ...); + +/* DESCRIPTION */ +icalproperty* icalproperty_new_description(const char* v); +void icalproperty_set_description(icalproperty* prop, const char* v); +const char* icalproperty_get_description(icalproperty* prop);icalproperty* icalproperty_vanew_dtend(struct icaltimetype v, ...); + +/* DTEND */ +icalproperty* icalproperty_new_dtend(struct icaltimetype v); +void icalproperty_set_dtend(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_dtend(icalproperty* prop);icalproperty* icalproperty_vanew_dtstamp(struct icaltimetype v, ...); + +/* DTSTAMP */ +icalproperty* icalproperty_new_dtstamp(struct icaltimetype v); +void icalproperty_set_dtstamp(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_dtstamp(icalproperty* prop);icalproperty* icalproperty_vanew_dtstart(struct icaltimetype v, ...); + +/* DTSTART */ +icalproperty* icalproperty_new_dtstart(struct icaltimetype v); +void icalproperty_set_dtstart(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_dtstart(icalproperty* prop);icalproperty* icalproperty_vanew_due(struct icaltimetype v, ...); + +/* DUE */ +icalproperty* icalproperty_new_due(struct icaltimetype v); +void icalproperty_set_due(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_due(icalproperty* prop);icalproperty* icalproperty_vanew_duration(struct icaldurationtype v, ...); + +/* DURATION */ +icalproperty* icalproperty_new_duration(struct icaldurationtype v); +void icalproperty_set_duration(icalproperty* prop, struct icaldurationtype v); +struct icaldurationtype icalproperty_get_duration(icalproperty* prop);icalproperty* icalproperty_vanew_exdate(struct icaltimetype v, ...); + +/* EXDATE */ +icalproperty* icalproperty_new_exdate(struct icaltimetype v); +void icalproperty_set_exdate(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_exdate(icalproperty* prop);icalproperty* icalproperty_vanew_exrule(struct icalrecurrencetype v, ...); + +/* EXRULE */ +icalproperty* icalproperty_new_exrule(struct icalrecurrencetype v); +void icalproperty_set_exrule(icalproperty* prop, struct icalrecurrencetype v); +struct icalrecurrencetype icalproperty_get_exrule(icalproperty* prop);icalproperty* icalproperty_vanew_freebusy(struct icalperiodtype v, ...); + +/* FREEBUSY */ +icalproperty* icalproperty_new_freebusy(struct icalperiodtype v); +void icalproperty_set_freebusy(icalproperty* prop, struct icalperiodtype v); +struct icalperiodtype icalproperty_get_freebusy(icalproperty* prop);icalproperty* icalproperty_vanew_geo(struct icalgeotype v, ...); + +/* GEO */ +icalproperty* icalproperty_new_geo(struct icalgeotype v); +void icalproperty_set_geo(icalproperty* prop, struct icalgeotype v); +struct icalgeotype icalproperty_get_geo(icalproperty* prop);icalproperty* icalproperty_vanew_lastmodified(struct icaltimetype v, ...); + +/* LAST-MODIFIED */ +icalproperty* icalproperty_new_lastmodified(struct icaltimetype v); +void icalproperty_set_lastmodified(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_lastmodified(icalproperty* prop);icalproperty* icalproperty_vanew_location(const char* v, ...); + +/* LOCATION */ +icalproperty* icalproperty_new_location(const char* v); +void icalproperty_set_location(icalproperty* prop, const char* v); +const char* icalproperty_get_location(icalproperty* prop);icalproperty* icalproperty_vanew_maxresults(int v, ...); + +/* MAXRESULTS */ +icalproperty* icalproperty_new_maxresults(int v); +void icalproperty_set_maxresults(icalproperty* prop, int v); +int icalproperty_get_maxresults(icalproperty* prop);icalproperty* icalproperty_vanew_maxresultssize(int v, ...); + +/* MAXRESULTSSIZE */ +icalproperty* icalproperty_new_maxresultssize(int v); +void icalproperty_set_maxresultssize(icalproperty* prop, int v); +int icalproperty_get_maxresultssize(icalproperty* prop);icalproperty* icalproperty_vanew_method(enum icalproperty_method v, ...); + +/* METHOD */ +icalproperty* icalproperty_new_method(enum icalproperty_method v); +void icalproperty_set_method(icalproperty* prop, enum icalproperty_method v); +enum icalproperty_method icalproperty_get_method(icalproperty* prop);icalproperty* icalproperty_vanew_organizer(const char* v, ...); + +/* ORGANIZER */ +icalproperty* icalproperty_new_organizer(const char* v); +void icalproperty_set_organizer(icalproperty* prop, const char* v); +const char* icalproperty_get_organizer(icalproperty* prop);icalproperty* icalproperty_vanew_percentcomplete(int v, ...); + +/* PERCENT-COMPLETE */ +icalproperty* icalproperty_new_percentcomplete(int v); +void icalproperty_set_percentcomplete(icalproperty* prop, int v); +int icalproperty_get_percentcomplete(icalproperty* prop);icalproperty* icalproperty_vanew_priority(int v, ...); + +/* PRIORITY */ +icalproperty* icalproperty_new_priority(int v); +void icalproperty_set_priority(icalproperty* prop, int v); +int icalproperty_get_priority(icalproperty* prop);icalproperty* icalproperty_vanew_prodid(const char* v, ...); + +/* PRODID */ +icalproperty* icalproperty_new_prodid(const char* v); +void icalproperty_set_prodid(icalproperty* prop, const char* v); +const char* icalproperty_get_prodid(icalproperty* prop);icalproperty* icalproperty_vanew_query(const char* v, ...); + +/* QUERY */ +icalproperty* icalproperty_new_query(const char* v); +void icalproperty_set_query(icalproperty* prop, const char* v); +const char* icalproperty_get_query(icalproperty* prop);icalproperty* icalproperty_vanew_queryname(const char* v, ...); + +/* QUERYNAME */ +icalproperty* icalproperty_new_queryname(const char* v); +void icalproperty_set_queryname(icalproperty* prop, const char* v); +const char* icalproperty_get_queryname(icalproperty* prop);icalproperty* icalproperty_vanew_rdate(struct icaldatetimeperiodtype v, ...); + +/* RDATE */ +icalproperty* icalproperty_new_rdate(struct icaldatetimeperiodtype v); +void icalproperty_set_rdate(icalproperty* prop, struct icaldatetimeperiodtype v); +struct icaldatetimeperiodtype icalproperty_get_rdate(icalproperty* prop);icalproperty* icalproperty_vanew_recurrenceid(struct icaltimetype v, ...); + +/* RECURRENCE-ID */ +icalproperty* icalproperty_new_recurrenceid(struct icaltimetype v); +void icalproperty_set_recurrenceid(icalproperty* prop, struct icaltimetype v); +struct icaltimetype icalproperty_get_recurrenceid(icalproperty* prop);icalproperty* icalproperty_vanew_relatedto(const char* v, ...); + +/* RELATED-TO */ +icalproperty* icalproperty_new_relatedto(const char* v); +void icalproperty_set_relatedto(icalproperty* prop, const char* v); +const char* icalproperty_get_relatedto(icalproperty* prop);icalproperty* icalproperty_vanew_repeat(int v, ...); + +/* REPEAT */ +icalproperty* icalproperty_new_repeat(int v); +void icalproperty_set_repeat(icalproperty* prop, int v); +int icalproperty_get_repeat(icalproperty* prop);icalproperty* icalproperty_vanew_requeststatus(struct icalreqstattype v, ...); + +/* REQUEST-STATUS */ +icalproperty* icalproperty_new_requeststatus(struct icalreqstattype v); +void icalproperty_set_requeststatus(icalproperty* prop, struct icalreqstattype v); +struct icalreqstattype icalproperty_get_requeststatus(icalproperty* prop);icalproperty* icalproperty_vanew_resources(const char* v, ...); + +/* RESOURCES */ +icalproperty* icalproperty_new_resources(const char* v); +void icalproperty_set_resources(icalproperty* prop, const char* v); +const char* icalproperty_get_resources(icalproperty* prop);icalproperty* icalproperty_vanew_rrule(struct icalrecurrencetype v, ...); + +/* RRULE */ +icalproperty* icalproperty_new_rrule(struct icalrecurrencetype v); +void icalproperty_set_rrule(icalproperty* prop, struct icalrecurrencetype v); +struct icalrecurrencetype icalproperty_get_rrule(icalproperty* prop);icalproperty* icalproperty_vanew_scope(const char* v, ...); + +/* SCOPE */ +icalproperty* icalproperty_new_scope(const char* v); +void icalproperty_set_scope(icalproperty* prop, const char* v); +const char* icalproperty_get_scope(icalproperty* prop);icalproperty* icalproperty_vanew_sequence(int v, ...); + +/* SEQUENCE */ +icalproperty* icalproperty_new_sequence(int v); +void icalproperty_set_sequence(icalproperty* prop, int v); +int icalproperty_get_sequence(icalproperty* prop);icalproperty* icalproperty_vanew_status(enum icalproperty_status v, ...); + +/* STATUS */ +icalproperty* icalproperty_new_status(enum icalproperty_status v); +void icalproperty_set_status(icalproperty* prop, enum icalproperty_status v); +enum icalproperty_status icalproperty_get_status(icalproperty* prop);icalproperty* icalproperty_vanew_summary(const char* v, ...); + +/* SUMMARY */ +icalproperty* icalproperty_new_summary(const char* v); +void icalproperty_set_summary(icalproperty* prop, const char* v); +const char* icalproperty_get_summary(icalproperty* prop);icalproperty* icalproperty_vanew_target(const char* v, ...); + +/* TARGET */ +icalproperty* icalproperty_new_target(const char* v); +void icalproperty_set_target(icalproperty* prop, const char* v); +const char* icalproperty_get_target(icalproperty* prop);icalproperty* icalproperty_vanew_transp(const char* v, ...); + +/* TRANSP */ +icalproperty* icalproperty_new_transp(const char* v); +void icalproperty_set_transp(icalproperty* prop, const char* v); +const char* icalproperty_get_transp(icalproperty* prop);icalproperty* icalproperty_vanew_trigger(struct icaltriggertype v, ...); + +/* TRIGGER */ +icalproperty* icalproperty_new_trigger(struct icaltriggertype v); +void icalproperty_set_trigger(icalproperty* prop, struct icaltriggertype v); +struct icaltriggertype icalproperty_get_trigger(icalproperty* prop);icalproperty* icalproperty_vanew_tzid(const char* v, ...); + +/* TZID */ +icalproperty* icalproperty_new_tzid(const char* v); +void icalproperty_set_tzid(icalproperty* prop, const char* v); +const char* icalproperty_get_tzid(icalproperty* prop);icalproperty* icalproperty_vanew_tzname(const char* v, ...); + +/* TZNAME */ +icalproperty* icalproperty_new_tzname(const char* v); +void icalproperty_set_tzname(icalproperty* prop, const char* v); +const char* icalproperty_get_tzname(icalproperty* prop);icalproperty* icalproperty_vanew_tzoffsetfrom(int v, ...); + +/* TZOFFSETFROM */ +icalproperty* icalproperty_new_tzoffsetfrom(int v); +void icalproperty_set_tzoffsetfrom(icalproperty* prop, int v); +int icalproperty_get_tzoffsetfrom(icalproperty* prop);icalproperty* icalproperty_vanew_tzoffsetto(int v, ...); + +/* TZOFFSETTO */ +icalproperty* icalproperty_new_tzoffsetto(int v); +void icalproperty_set_tzoffsetto(icalproperty* prop, int v); +int icalproperty_get_tzoffsetto(icalproperty* prop);icalproperty* icalproperty_vanew_tzurl(const char* v, ...); + +/* TZURL */ +icalproperty* icalproperty_new_tzurl(const char* v); +void icalproperty_set_tzurl(icalproperty* prop, const char* v); +const char* icalproperty_get_tzurl(icalproperty* prop);icalproperty* icalproperty_vanew_uid(const char* v, ...); + +/* UID */ +icalproperty* icalproperty_new_uid(const char* v); +void icalproperty_set_uid(icalproperty* prop, const char* v); +const char* icalproperty_get_uid(icalproperty* prop);icalproperty* icalproperty_vanew_url(const char* v, ...); + +/* URL */ +icalproperty* icalproperty_new_url(const char* v); +void icalproperty_set_url(icalproperty* prop, const char* v); +const char* icalproperty_get_url(icalproperty* prop);icalproperty* icalproperty_vanew_version(const char* v, ...); + +/* VERSION */ +icalproperty* icalproperty_new_version(const char* v); +void icalproperty_set_version(icalproperty* prop, const char* v); +const char* icalproperty_get_version(icalproperty* prop);icalproperty* icalproperty_vanew_x(const char* v, ...); + +/* X */ +icalproperty* icalproperty_new_x(const char* v); +void icalproperty_set_x(icalproperty* prop, const char* v); +const char* icalproperty_get_x(icalproperty* prop);icalproperty* icalproperty_vanew_xlicclustercount(const char* v, ...); + +/* X-LIC-CLUSTERCOUNT */ +icalproperty* icalproperty_new_xlicclustercount(const char* v); +void icalproperty_set_xlicclustercount(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicclustercount(icalproperty* prop);icalproperty* icalproperty_vanew_xlicerror(const char* v, ...); + +/* X-LIC-ERROR */ +icalproperty* icalproperty_new_xlicerror(const char* v); +void icalproperty_set_xlicerror(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicerror(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimecharset(const char* v, ...); + +/* X-LIC-MIMECHARSET */ +icalproperty* icalproperty_new_xlicmimecharset(const char* v); +void icalproperty_set_xlicmimecharset(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimecharset(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimecid(const char* v, ...); + +/* X-LIC-MIMECID */ +icalproperty* icalproperty_new_xlicmimecid(const char* v); +void icalproperty_set_xlicmimecid(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimecid(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimecontenttype(const char* v, ...); + +/* X-LIC-MIMECONTENTTYPE */ +icalproperty* icalproperty_new_xlicmimecontenttype(const char* v); +void icalproperty_set_xlicmimecontenttype(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimecontenttype(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimeencoding(const char* v, ...); + +/* X-LIC-MIMEENCODING */ +icalproperty* icalproperty_new_xlicmimeencoding(const char* v); +void icalproperty_set_xlicmimeencoding(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimeencoding(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimefilename(const char* v, ...); + +/* X-LIC-MIMEFILENAME */ +icalproperty* icalproperty_new_xlicmimefilename(const char* v); +void icalproperty_set_xlicmimefilename(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimefilename(icalproperty* prop);icalproperty* icalproperty_vanew_xlicmimeoptinfo(const char* v, ...); + +/* X-LIC-MIMEOPTINFO */ +icalproperty* icalproperty_new_xlicmimeoptinfo(const char* v); +void icalproperty_set_xlicmimeoptinfo(icalproperty* prop, const char* v); +const char* icalproperty_get_xlicmimeoptinfo(icalproperty* prop); + +#endif /*ICALPROPERTY_H*/ diff --git a/libical/src/libical/icalderivedvalue.c b/libical/src/libical/icalderivedvalue.c new file mode 100644 index 0000000..db762ea --- a/dev/null +++ b/libical/src/libical/icalderivedvalue.c @@ -0,0 +1,981 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.c + CREATOR: eric 02 May 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalvalue.c + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + +======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalerror.h" +#include "icalmemory.h" +#include "icalparser.h" +#include "icalenums.h" + +#include "icalvalueimpl.h" + +#include <stdlib.h> /* for malloc */ +#include <stdio.h> /* for sprintf */ +#include <string.h> /* For memset, others */ +#include <stddef.h> /* For offsetof() macro */ +#include <errno.h> +#include <time.h> /* for mktime */ +#include <stdlib.h> /* for atoi and atof */ +#include <limits.h> /* for SHRT_MAX */ + + + +#define TMP_BUF_SIZE 1024 + +struct icalvalue_impl* icalvalue_new_impl(icalvalue_kind kind); + +/* This map associates each of the value types with its string + representation */ +struct icalvalue_kind_map { + icalvalue_kind kind; + char name[20]; +}; + +extern struct icalvalue_kind_map value_map[]; + +const char* icalvalue_kind_to_string(icalvalue_kind kind) +{ + int i; + + for (i=0; value_map[i].kind != ICAL_NO_VALUE; i++) { + if (value_map[i].kind == kind) { + return value_map[i].name; + } + } + + return 0; +} + +icalvalue_kind icalvalue_string_to_kind(const char* str) +{ + int i; + + for (i=0; value_map[i].kind != ICAL_NO_VALUE; i++) { + if (strcmp(value_map[i].name,str) == 0) { + return value_map[i].kind; + } + } + + return value_map[i].kind; + +} + +icalvalue* icalvalue_new_x (const char* v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_X_VALUE); + icalerror_check_arg_rz( (v!=0),"v"); + + icalvalue_set_x((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_x(icalvalue* value, const char* v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_arg_rv( (v!=0),"v"); + + impl = (struct icalvalue_impl*)value; + if(impl->x_value!=0) {free((void*)impl->x_value);} + + impl->x_value = icalmemory_strdup(v); + + if (impl->x_value == 0){ + errno = ENOMEM; + } + + } +const char* icalvalue_get_x(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_X_VALUE); + return ((struct icalvalue_impl*)value)->x_value; +} + +/* Attachment is a special case, so it is not auto generated. */ +icalvalue* +icalvalue_new_attach (struct icalattachtype *v) +{ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_ATTACH_VALUE); + + icalvalue_set_attach((icalvalue*)impl,v); + + return (icalvalue*)impl; +} + +void +icalvalue_set_attach(icalvalue* value, struct icalattachtype *v) +{ + struct icalvalue_impl* impl; + + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_ATTACH_VALUE); + + impl = (struct icalvalue_impl*)value; + + if (impl->data.v_attach != 0){ + icalattachtype_free(impl->data.v_attach); + } + + impl->data.v_attach = v; + icalattachtype_add_reference(v); +} + +struct icalattachtype* +icalvalue_get_attach(icalvalue* value) +{ + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_ATTACH_VALUE); + + return ((struct icalvalue_impl*)value)->data.v_attach; +} + + +/* Recur is a special case, so it is not auto generated. */ +icalvalue* +icalvalue_new_recur (struct icalrecurrencetype v) +{ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_RECUR_VALUE); + + icalvalue_set_recur((icalvalue*)impl,v); + + return (icalvalue*)impl; +} + +void +icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v) +{ + struct icalvalue_impl* impl; + + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_RECUR_VALUE); + + impl = (struct icalvalue_impl*)value; + + if (impl->data.v_recur != 0){ + free(impl->data.v_recur); + impl->data.v_recur = 0; + } + + impl->data.v_recur = malloc(sizeof(struct icalrecurrencetype)); + + if (impl->data.v_recur == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return; + } else { + memcpy(impl->data.v_recur, &v, sizeof(struct icalrecurrencetype)); + } + +} + +struct icalrecurrencetype +icalvalue_get_recur(icalvalue* value) +{ + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_RECUR_VALUE); + + return *(((struct icalvalue_impl*)value)->data.v_recur); +} + + + + +icalvalue* +icalvalue_new_trigger (struct icaltriggertype v) +{ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_TRIGGER_VALUE); + + icalvalue_set_trigger((icalvalue*)impl,v); + + return (icalvalue*)impl; +} + +void +icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v) +{ + struct icalvalue_impl* impl; + + icalerror_check_arg_rv( (value!=0),"value"); + + impl = (struct icalvalue_impl*)value; + + if(!icaltime_is_null_time(v.time)){ + icalvalue_set_datetime((icalvalue*)impl,v.time); + impl->kind = ICAL_DATETIME_VALUE; + } else { + icalvalue_set_duration((icalvalue*)impl,v.duration); + impl->kind = ICAL_DURATION_VALUE; + } + +} + +struct icaltriggertype +icalvalue_get_trigger(icalvalue* value) +{ + struct icalvalue_impl *impl = (struct icalvalue_impl*)value; + struct icaltriggertype tr; + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_arg( (value!=0),"value"); + + if(impl->kind == ICAL_DATETIME_VALUE){ + tr.duration = icaldurationtype_from_int(0); + tr.time = impl->data.v_time; + } else if(impl->kind == ICAL_DURATION_VALUE){ + tr.time = icaltime_null_time(); + tr.duration = impl->data.v_duration; + } else { + tr.duration = icaldurationtype_from_int(0); + tr.time = icaltime_null_time(); + icalerror_set_errno(ICAL_BADARG_ERROR); + } + + return tr; +} + +/* DATE-TIME-PERIOD is a special case, and is not auto generated */ + +icalvalue* +icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v) +{ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_DATETIMEPERIOD_VALUE); + + icalvalue_set_datetimeperiod((icalvalue*)impl,v); + + return (icalvalue*)impl; +} + +void +icalvalue_set_datetimeperiod(icalvalue* value, struct icaldatetimeperiodtype v) +{ + struct icalvalue_impl* impl = (struct icalvalue_impl*)value; + + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_DATETIMEPERIOD_VALUE); + + if(!icaltime_is_null_time(v.time)){ + if(!icaltime_is_valid_time(v.time)){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return; + } + impl->kind = ICAL_DATETIME_VALUE; + icalvalue_set_datetime(impl,v.time); + } else if (!icalperiodtype_is_null_period(v.period)) { + if(!icalperiodtype_is_valid_period(v.period)){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return; + } + impl->kind = ICAL_PERIOD_VALUE; + icalvalue_set_period(impl,v.period); + } else { + icalerror_set_errno(ICAL_BADARG_ERROR); + } +} + +struct icaldatetimeperiodtype +icalvalue_get_datetimeperiod(icalvalue* value) +{ + struct icaldatetimeperiodtype dtp; + + struct icalvalue_impl* impl = (struct icalvalue_impl*)value; + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_DATETIMEPERIOD_VALUE); + + if(impl->kind == ICAL_DATETIME_VALUE){ + dtp.period = icalperiodtype_null_period(); + dtp.time = impl->data.v_time; + } else if(impl->kind == ICAL_PERIOD_VALUE) { + dtp.period = impl->data.v_period; + dtp.time = icaltime_null_time(); + } else { + dtp.period = icalperiodtype_null_period(); + dtp.time = icaltime_null_time(); + icalerror_set_errno(ICAL_BADARG_ERROR); + } + + return dtp; +} + + + + + + + + + +/* The remaining interfaces are 'new', 'set' and 'get' for each of the value + types */ + + +/* Everything below this line is machine generated. Do not edit. */ +static struct icalvalue_kind_map value_map[]={ + {ICAL_QUERY_VALUE,"QUERY"}, + {ICAL_TRIGGER_VALUE,"TRIGGER"}, + {ICAL_STATUS_VALUE,"STATUS"}, + {ICAL_TRANSP_VALUE,"TRANSP"}, + {ICAL_CLASS_VALUE,"CLASS"}, + {ICAL_DATE_VALUE,"DATE"}, + {ICAL_STRING_VALUE,"STRING"}, + {ICAL_INTEGER_VALUE,"INTEGER"}, + {ICAL_PERIOD_VALUE,"PERIOD"}, + {ICAL_TEXT_VALUE,"TEXT"}, + {ICAL_DURATION_VALUE,"DURATION"}, + {ICAL_BOOLEAN_VALUE,"BOOLEAN"}, + {ICAL_URI_VALUE,"URI"}, + {ICAL_DATETIMEPERIOD_VALUE,"DATE-TIME-PERIOD"}, + {ICAL_GEO_VALUE,"GEO"}, + {ICAL_DATETIME_VALUE,"DATE-TIME"}, + {ICAL_UTCOFFSET_VALUE,"UTC-OFFSET"}, + {ICAL_ATTACH_VALUE,"ATTACH"}, + {ICAL_ACTION_VALUE,"ACTION"}, + {ICAL_CALADDRESS_VALUE,"CAL-ADDRESS"}, + {ICAL_X_VALUE,"X"}, + {ICAL_FLOAT_VALUE,"FLOAT"}, + {ICAL_REQUESTSTATUS_VALUE,"REQUEST-STATUS"}, + {ICAL_METHOD_VALUE,"METHOD"}, + {ICAL_BINARY_VALUE,"BINARY"}, + {ICAL_RECUR_VALUE,"RECUR"}, + {ICAL_NO_VALUE,""} +}; + + +icalvalue* icalvalue_new_query (const char* v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_QUERY_VALUE); + icalerror_check_arg_rz( (v!=0),"v"); + + icalvalue_set_query((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_query(icalvalue* value, const char* v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_value_type(value, ICAL_QUERY_VALUE); + impl = (struct icalvalue_impl*)value; + if(impl->data.v_string!=0) {free((void*)impl->data.v_string);} + + + impl->data.v_string = icalmemory_strdup(v); + + if (impl->data.v_string == 0){ + errno = ENOMEM; + } + + + icalvalue_reset_kind(impl); +} +const char* icalvalue_get_query(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_QUERY_VALUE); + return ((struct icalvalue_impl*)value)->data.v_string; +} + + + +icalvalue* icalvalue_new_status (enum icalproperty_status v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_STATUS_VALUE); + + icalvalue_set_status((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_status(icalvalue* value, enum icalproperty_status v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_STATUS_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_enum = v; + + icalvalue_reset_kind(impl); +} +enum icalproperty_status icalvalue_get_status(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_STATUS_VALUE); + return ((struct icalvalue_impl*)value)->data.v_enum; +} + + + +icalvalue* icalvalue_new_transp (enum icalproperty_transp v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_TRANSP_VALUE); + + icalvalue_set_transp((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_transp(icalvalue* value, enum icalproperty_transp v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_TRANSP_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_enum = v; + + icalvalue_reset_kind(impl); +} +enum icalproperty_transp icalvalue_get_transp(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_TRANSP_VALUE); + return ((struct icalvalue_impl*)value)->data.v_enum; +} + + + +icalvalue* icalvalue_new_class (enum icalproperty_class v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_CLASS_VALUE); + + icalvalue_set_class((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_class(icalvalue* value, enum icalproperty_class v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_CLASS_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_enum = v; + + icalvalue_reset_kind(impl); +} +enum icalproperty_class icalvalue_get_class(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_CLASS_VALUE); + return ((struct icalvalue_impl*)value)->data.v_enum; +} + + + +icalvalue* icalvalue_new_date (struct icaltimetype v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_DATE_VALUE); + + icalvalue_set_date((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_date(icalvalue* value, struct icaltimetype v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_DATE_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_time = v; + + icalvalue_reset_kind(impl); +} +struct icaltimetype icalvalue_get_date(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_DATE_VALUE); + return ((struct icalvalue_impl*)value)->data.v_time; +} + + + +icalvalue* icalvalue_new_string (const char* v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_STRING_VALUE); + icalerror_check_arg_rz( (v!=0),"v"); + + icalvalue_set_string((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_string(icalvalue* value, const char* v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_value_type(value, ICAL_STRING_VALUE); + impl = (struct icalvalue_impl*)value; + if(impl->data.v_string!=0) {free((void*)impl->data.v_string);} + + + impl->data.v_string = icalmemory_strdup(v); + + if (impl->data.v_string == 0){ + errno = ENOMEM; + } + + + icalvalue_reset_kind(impl); +} +const char* icalvalue_get_string(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_STRING_VALUE); + return ((struct icalvalue_impl*)value)->data.v_string; +} + + + +icalvalue* icalvalue_new_integer (int v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_INTEGER_VALUE); + + icalvalue_set_integer((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_integer(icalvalue* value, int v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_INTEGER_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_int = v; + + icalvalue_reset_kind(impl); +} +int icalvalue_get_integer(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_INTEGER_VALUE); + return ((struct icalvalue_impl*)value)->data.v_int; +} + + + +icalvalue* icalvalue_new_period (struct icalperiodtype v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_PERIOD_VALUE); + + icalvalue_set_period((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_period(icalvalue* value, struct icalperiodtype v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_PERIOD_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_period = v; + + icalvalue_reset_kind(impl); +} +struct icalperiodtype icalvalue_get_period(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_PERIOD_VALUE); + return ((struct icalvalue_impl*)value)->data.v_period; +} + + + +icalvalue* icalvalue_new_text (const char* v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_TEXT_VALUE); + icalerror_check_arg_rz( (v!=0),"v"); + + icalvalue_set_text((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_text(icalvalue* value, const char* v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_value_type(value, ICAL_TEXT_VALUE); + impl = (struct icalvalue_impl*)value; + if(impl->data.v_string!=0) {free((void*)impl->data.v_string);} + + + impl->data.v_string = icalmemory_strdup(v); + + if (impl->data.v_string == 0){ + errno = ENOMEM; + } + + + icalvalue_reset_kind(impl); +} +const char* icalvalue_get_text(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_TEXT_VALUE); + return ((struct icalvalue_impl*)value)->data.v_string; +} + + + +icalvalue* icalvalue_new_duration (struct icaldurationtype v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_DURATION_VALUE); + + icalvalue_set_duration((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_duration(icalvalue* value, struct icaldurationtype v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_DURATION_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_duration = v; + + icalvalue_reset_kind(impl); +} +struct icaldurationtype icalvalue_get_duration(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_DURATION_VALUE); + return ((struct icalvalue_impl*)value)->data.v_duration; +} + + + +icalvalue* icalvalue_new_boolean (int v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_BOOLEAN_VALUE); + + icalvalue_set_boolean((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_boolean(icalvalue* value, int v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_BOOLEAN_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_int = v; + + icalvalue_reset_kind(impl); +} +int icalvalue_get_boolean(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_BOOLEAN_VALUE); + return ((struct icalvalue_impl*)value)->data.v_int; +} + + + +icalvalue* icalvalue_new_uri (const char* v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_URI_VALUE); + icalerror_check_arg_rz( (v!=0),"v"); + + icalvalue_set_uri((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_uri(icalvalue* value, const char* v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_value_type(value, ICAL_URI_VALUE); + impl = (struct icalvalue_impl*)value; + if(impl->data.v_string!=0) {free((void*)impl->data.v_string);} + + + impl->data.v_string = icalmemory_strdup(v); + + if (impl->data.v_string == 0){ + errno = ENOMEM; + } + + + icalvalue_reset_kind(impl); +} +const char* icalvalue_get_uri(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_URI_VALUE); + return ((struct icalvalue_impl*)value)->data.v_string; +} + + + +icalvalue* icalvalue_new_geo (struct icalgeotype v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_GEO_VALUE); + + icalvalue_set_geo((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_geo(icalvalue* value, struct icalgeotype v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_GEO_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_geo = v; + + icalvalue_reset_kind(impl); +} +struct icalgeotype icalvalue_get_geo(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_GEO_VALUE); + return ((struct icalvalue_impl*)value)->data.v_geo; +} + + + +icalvalue* icalvalue_new_datetime (struct icaltimetype v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_DATETIME_VALUE); + + icalvalue_set_datetime((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_datetime(icalvalue* value, struct icaltimetype v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_DATETIME_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_time = v; + + icalvalue_reset_kind(impl); +} +struct icaltimetype icalvalue_get_datetime(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_DATETIME_VALUE); + return ((struct icalvalue_impl*)value)->data.v_time; +} + + + +icalvalue* icalvalue_new_utcoffset (int v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_UTCOFFSET_VALUE); + + icalvalue_set_utcoffset((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_utcoffset(icalvalue* value, int v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_UTCOFFSET_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_int = v; + + icalvalue_reset_kind(impl); +} +int icalvalue_get_utcoffset(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_UTCOFFSET_VALUE); + return ((struct icalvalue_impl*)value)->data.v_int; +} + + + +icalvalue* icalvalue_new_action (enum icalproperty_action v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_ACTION_VALUE); + + icalvalue_set_action((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_action(icalvalue* value, enum icalproperty_action v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_ACTION_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_enum = v; + + icalvalue_reset_kind(impl); +} +enum icalproperty_action icalvalue_get_action(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_ACTION_VALUE); + return ((struct icalvalue_impl*)value)->data.v_enum; +} + + + +icalvalue* icalvalue_new_caladdress (const char* v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_CALADDRESS_VALUE); + icalerror_check_arg_rz( (v!=0),"v"); + + icalvalue_set_caladdress((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_caladdress(icalvalue* value, const char* v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_value_type(value, ICAL_CALADDRESS_VALUE); + impl = (struct icalvalue_impl*)value; + if(impl->data.v_string!=0) {free((void*)impl->data.v_string);} + + + impl->data.v_string = icalmemory_strdup(v); + + if (impl->data.v_string == 0){ + errno = ENOMEM; + } + + + icalvalue_reset_kind(impl); +} +const char* icalvalue_get_caladdress(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_CALADDRESS_VALUE); + return ((struct icalvalue_impl*)value)->data.v_string; +} + + + +icalvalue* icalvalue_new_float (float v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_FLOAT_VALUE); + + icalvalue_set_float((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_float(icalvalue* value, float v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_FLOAT_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_float = v; + + icalvalue_reset_kind(impl); +} +float icalvalue_get_float(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_FLOAT_VALUE); + return ((struct icalvalue_impl*)value)->data.v_float; +} + + + +icalvalue* icalvalue_new_requeststatus (struct icalreqstattype v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_REQUESTSTATUS_VALUE); + + icalvalue_set_requeststatus((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_requeststatus(icalvalue* value, struct icalreqstattype v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_REQUESTSTATUS_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_requeststatus = v; + + icalvalue_reset_kind(impl); +} +struct icalreqstattype icalvalue_get_requeststatus(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_REQUESTSTATUS_VALUE); + return ((struct icalvalue_impl*)value)->data.v_requeststatus; +} + + + +icalvalue* icalvalue_new_method (enum icalproperty_method v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_METHOD_VALUE); + + icalvalue_set_method((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_method(icalvalue* value, enum icalproperty_method v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_METHOD_VALUE); + impl = (struct icalvalue_impl*)value; + + + impl->data.v_enum = v; + + icalvalue_reset_kind(impl); +} +enum icalproperty_method icalvalue_get_method(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_METHOD_VALUE); + return ((struct icalvalue_impl*)value)->data.v_enum; +} + + + +icalvalue* icalvalue_new_binary (const char* v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_BINARY_VALUE); + icalerror_check_arg_rz( (v!=0),"v"); + + icalvalue_set_binary((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_binary(icalvalue* value, const char* v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_arg_rv( (v!=0),"v"); + + icalerror_check_value_type(value, ICAL_BINARY_VALUE); + impl = (struct icalvalue_impl*)value; + if(impl->data.v_string!=0) {free((void*)impl->data.v_string);} + + + impl->data.v_string = icalmemory_strdup(v); + + if (impl->data.v_string == 0){ + errno = ENOMEM; + } + + + icalvalue_reset_kind(impl); +} +const char* icalvalue_get_binary(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_BINARY_VALUE); + return ((struct icalvalue_impl*)value)->data.v_string; +} diff --git a/libical/src/libical/icalderivedvalue.h b/libical/src/libical/icalderivedvalue.h new file mode 100644 index 0000000..8324f04 --- a/dev/null +++ b/libical/src/libical/icalderivedvalue.h @@ -0,0 +1,283 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalvalue.h + + ======================================================================*/ + +#ifndef ICALDERIVEDVALUE_H +#define ICALDERIVEDVALUE_H + +#include "icaltypes.h" +#include "icalrecur.h" +#include "icaltime.h" +#include "icalduration.h" +#include "icalperiod.h" + +typedef void icalvalue; + + + +void icalvalue_set_x(icalvalue* value, const char* v); +icalvalue* icalvalue_new_x(const char* v); +const char* icalvalue_get_x(icalvalue* value); + +icalvalue* icalvalue_new_attach (struct icalattachtype* v); +void icalvalue_set_attach(icalvalue* value, struct icalattachtype* v); +struct icalattachtype* icalvalue_get_attach(icalvalue* value); + +icalvalue* icalvalue_new_recur (struct icalrecurrencetype v); +void icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v); +struct icalrecurrencetype icalvalue_get_recur(icalvalue* value); + +icalvalue* icalvalue_new_trigger (struct icaltriggertype v); +void icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v); +struct icaltriggertype icalvalue_get_trigger(icalvalue* value); + +icalvalue* icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v); +void icalvalue_set_datetimeperiod(icalvalue* value, struct icaldatetimeperiodtype v); +struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(icalvalue* value); + +void icalvalue_reset_kind(icalvalue* value); + +/* Everything below this line is machine generated. Do not edit. */ +typedef enum icalvalue_kind { + ICAL_ANY_VALUE=5000, + ICAL_QUERY_VALUE=5001, + ICAL_TRIGGER_VALUE=5002, + ICAL_STATUS_VALUE=5003, + ICAL_TRANSP_VALUE=5004, + ICAL_CLASS_VALUE=5005, + ICAL_DATE_VALUE=5006, + ICAL_STRING_VALUE=5007, + ICAL_INTEGER_VALUE=5008, + ICAL_PERIOD_VALUE=5009, + ICAL_TEXT_VALUE=5010, + ICAL_DURATION_VALUE=5011, + ICAL_BOOLEAN_VALUE=5012, + ICAL_URI_VALUE=5013, + ICAL_DATETIMEPERIOD_VALUE=5014, + ICAL_GEO_VALUE=5015, + ICAL_DATETIME_VALUE=5016, + ICAL_UTCOFFSET_VALUE=5017, + ICAL_ATTACH_VALUE=5018, + ICAL_ACTION_VALUE=5019, + ICAL_CALADDRESS_VALUE=5020, + ICAL_X_VALUE=5021, + ICAL_FLOAT_VALUE=5022, + ICAL_REQUESTSTATUS_VALUE=5023, + ICAL_METHOD_VALUE=5024, + ICAL_BINARY_VALUE=5025, + ICAL_RECUR_VALUE=5026, + ICAL_NO_VALUE=5027 +} icalvalue_kind ; + +#define ICALPROPERTY_FIRST_ENUM 10000 + +typedef enum icalproperty_action { + ICAL_ACTION_X = 10000, + ICAL_ACTION_AUDIO = 10001, + ICAL_ACTION_DISPLAY = 10002, + ICAL_ACTION_EMAIL = 10003, + ICAL_ACTION_PROCEDURE = 10004, + ICAL_ACTION_NONE = 10005 +} icalproperty_action; + +typedef enum icalproperty_class { + ICAL_CLASS_X = 10006, + ICAL_CLASS_PUBLIC = 10007, + ICAL_CLASS_PRIVATE = 10008, + ICAL_CLASS_CONFIDENTIAL = 10009, + ICAL_CLASS_NONE = 10010 +} icalproperty_class; + +typedef enum icalproperty_method { + ICAL_METHOD_X = 10011, + ICAL_METHOD_PUBLISH = 10012, + ICAL_METHOD_REQUEST = 10013, + ICAL_METHOD_REPLY = 10014, + ICAL_METHOD_ADD = 10015, + ICAL_METHOD_CANCEL = 10016, + ICAL_METHOD_REFRESH = 10017, + ICAL_METHOD_COUNTER = 10018, + ICAL_METHOD_DECLINECOUNTER = 10019, + ICAL_METHOD_CREATE = 10020, + ICAL_METHOD_READ = 10021, + ICAL_METHOD_RESPONSE = 10022, + ICAL_METHOD_MOVE = 10023, + ICAL_METHOD_MODIFY = 10024, + ICAL_METHOD_GENERATEUID = 10025, + ICAL_METHOD_DELETE = 10026, + ICAL_METHOD_NONE = 10027 +} icalproperty_method; + +typedef enum icalproperty_status { + ICAL_STATUS_X = 10028, + ICAL_STATUS_TENTATIVE = 10029, + ICAL_STATUS_CONFIRMED = 10030, + ICAL_STATUS_COMPLETED = 10031, + ICAL_STATUS_NEEDSACTION = 10032, + ICAL_STATUS_CANCELLED = 10033, + ICAL_STATUS_INPROCESS = 10034, + ICAL_STATUS_DRAFT = 10035, + ICAL_STATUS_FINAL = 10036, + ICAL_STATUS_NONE = 10037 +} icalproperty_status; + +typedef enum icalproperty_transp { + ICAL_TRANSP_X = 10038, + ICAL_TRANSP_OPAQUE = 10039, + ICAL_TRANSP_TRANSPARENT = 10040, + ICAL_TRANSP_NONE = 10041 +} icalproperty_transp; + +#define ICALPROPERTY_LAST_ENUM 10042 + + + /* QUERY */ +icalvalue* icalvalue_new_query(const char* v); +const char* icalvalue_get_query(icalvalue* value); +void icalvalue_set_query(icalvalue* value, const char* v); + + + /* STATUS */ +icalvalue* icalvalue_new_status(enum icalproperty_status v); +enum icalproperty_status icalvalue_get_status(icalvalue* value); +void icalvalue_set_status(icalvalue* value, enum icalproperty_status v); + + + /* TRANSP */ +icalvalue* icalvalue_new_transp(enum icalproperty_transp v); +enum icalproperty_transp icalvalue_get_transp(icalvalue* value); +void icalvalue_set_transp(icalvalue* value, enum icalproperty_transp v); + + + /* CLASS */ +icalvalue* icalvalue_new_class(enum icalproperty_class v); +enum icalproperty_class icalvalue_get_class(icalvalue* value); +void icalvalue_set_class(icalvalue* value, enum icalproperty_class v); + + + /* DATE */ +icalvalue* icalvalue_new_date(struct icaltimetype v); +struct icaltimetype icalvalue_get_date(icalvalue* value); +void icalvalue_set_date(icalvalue* value, struct icaltimetype v); + + + /* STRING */ +icalvalue* icalvalue_new_string(const char* v); +const char* icalvalue_get_string(icalvalue* value); +void icalvalue_set_string(icalvalue* value, const char* v); + + + /* INTEGER */ +icalvalue* icalvalue_new_integer(int v); +int icalvalue_get_integer(icalvalue* value); +void icalvalue_set_integer(icalvalue* value, int v); + + + /* PERIOD */ +icalvalue* icalvalue_new_period(struct icalperiodtype v); +struct icalperiodtype icalvalue_get_period(icalvalue* value); +void icalvalue_set_period(icalvalue* value, struct icalperiodtype v); + + + /* TEXT */ +icalvalue* icalvalue_new_text(const char* v); +const char* icalvalue_get_text(icalvalue* value); +void icalvalue_set_text(icalvalue* value, const char* v); + + + /* DURATION */ +icalvalue* icalvalue_new_duration(struct icaldurationtype v); +struct icaldurationtype icalvalue_get_duration(icalvalue* value); +void icalvalue_set_duration(icalvalue* value, struct icaldurationtype v); + + + /* BOOLEAN */ +icalvalue* icalvalue_new_boolean(int v); +int icalvalue_get_boolean(icalvalue* value); +void icalvalue_set_boolean(icalvalue* value, int v); + + + /* URI */ +icalvalue* icalvalue_new_uri(const char* v); +const char* icalvalue_get_uri(icalvalue* value); +void icalvalue_set_uri(icalvalue* value, const char* v); + + + /* GEO */ +icalvalue* icalvalue_new_geo(struct icalgeotype v); +struct icalgeotype icalvalue_get_geo(icalvalue* value); +void icalvalue_set_geo(icalvalue* value, struct icalgeotype v); + + + /* DATE-TIME */ +icalvalue* icalvalue_new_datetime(struct icaltimetype v); +struct icaltimetype icalvalue_get_datetime(icalvalue* value); +void icalvalue_set_datetime(icalvalue* value, struct icaltimetype v); + + + /* UTC-OFFSET */ +icalvalue* icalvalue_new_utcoffset(int v); +int icalvalue_get_utcoffset(icalvalue* value); +void icalvalue_set_utcoffset(icalvalue* value, int v); + + + /* ACTION */ +icalvalue* icalvalue_new_action(enum icalproperty_action v); +enum icalproperty_action icalvalue_get_action(icalvalue* value); +void icalvalue_set_action(icalvalue* value, enum icalproperty_action v); + + + /* CAL-ADDRESS */ +icalvalue* icalvalue_new_caladdress(const char* v); +const char* icalvalue_get_caladdress(icalvalue* value); +void icalvalue_set_caladdress(icalvalue* value, const char* v); + + + /* FLOAT */ +icalvalue* icalvalue_new_float(float v); +float icalvalue_get_float(icalvalue* value); +void icalvalue_set_float(icalvalue* value, float v); + + + /* REQUEST-STATUS */ +icalvalue* icalvalue_new_requeststatus(struct icalreqstattype v); +struct icalreqstattype icalvalue_get_requeststatus(icalvalue* value); +void icalvalue_set_requeststatus(icalvalue* value, struct icalreqstattype v); + + + /* METHOD */ +icalvalue* icalvalue_new_method(enum icalproperty_method v); +enum icalproperty_method icalvalue_get_method(icalvalue* value); +void icalvalue_set_method(icalvalue* value, enum icalproperty_method v); + + + /* BINARY */ +icalvalue* icalvalue_new_binary(const char* v); +const char* icalvalue_get_binary(icalvalue* value); +void icalvalue_set_binary(icalvalue* value, const char* v); + +#endif /*ICALVALUE_H*/ diff --git a/libical/src/libical/icalduration.c b/libical/src/libical/icalduration.c new file mode 100644 index 0000000..4468e0f --- a/dev/null +++ b/libical/src/libical/icalduration.c @@ -0,0 +1,323 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icaltime.c + CREATOR: eric 02 June 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalduration.h" + +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#ifdef ICAL_NO_LIBICAL +#define icalerror_set_errno(x) +#define icalerror_check_arg_rv(x,y) +#define icalerror_check_arg_re(x,y,z) +#else +#include "icalerror.h" +#include "icalmemory.h" +#endif + + + + +/* From Seth Alves, <alves@hungry.com> */ +struct icaldurationtype icaldurationtype_from_int(int t) +{ + struct icaldurationtype dur; + int used = 0; + + dur = icaldurationtype_null_duration(); + + if(t < 0){ + dur.is_neg = 1; + t = -t; + } + + if (t % (60 * 60 * 24 * 7) == 0) { + dur.weeks = t / (60 * 60 * 24 * 7); + } else { + used += dur.weeks * (60 * 60 * 24 * 7); + dur.days = (t - used) / (60 * 60 * 24); + used += dur.days * (60 * 60 * 24); + dur.hours = (t - used) / (60 * 60); + used += dur.hours * (60 * 60); + dur.minutes = (t - used) / (60); + used += dur.minutes * (60); + dur.seconds = (t - used); + } + + return dur; +} + +#ifndef ICAL_NO_LIBICAL +#include "icalvalue.h" +struct icaldurationtype icaldurationtype_from_string(const char* str) +{ + + int i; + int begin_flag = 0; + int time_flag = 0; + int date_flag = 0; + int week_flag = 0; + int digits=-1; + int scan_size = -1; + int size = strlen(str); + char p; + struct icaldurationtype d; + + memset(&d, 0, sizeof(struct icaldurationtype)); + + for(i=0;i != size;i++){ + p = str[i]; + + switch(p) + { + case '-': { + if(i != 0 || begin_flag == 1) goto error; + + d.is_neg = 1; + break; + } + + case 'P': { + if (i != 0 && i !=1 ) goto error; + begin_flag = 1; + break; + } + + case 'T': { + time_flag = 1; + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + + /* HACK. Skip any more digits if the l;ast one + read has not been assigned */ + if(digits != -1){ + break; + } + + if (begin_flag == 0) goto error; + /* Get all of the digits, not one at a time */ + scan_size = sscanf((char*)(str+i),"%d",&digits); + if(scan_size == 0) goto error; + break; + } + + case 'H': { + if (time_flag == 0||week_flag == 1||d.hours !=0||digits ==-1) + goto error; + d.hours = digits; digits = -1; + break; + } + case 'M': { + if (time_flag == 0||week_flag==1||d.minutes != 0||digits ==-1) + goto error; + d.minutes = digits; digits = -1; + break; + } + case 'S': { + if (time_flag == 0||week_flag==1||d.seconds!=0||digits ==-1) + goto error; + d.seconds = digits; digits = -1; + break; + } + case 'W': { + if (time_flag==1||date_flag==1||d.weeks!=0||digits ==-1) + goto error; + week_flag = 1; + d.weeks = digits; digits = -1; + break; + } + case 'D': { + if (time_flag==1||week_flag==1||d.days!=0||digits ==-1) + goto error; + date_flag = 1; + d.days = digits; digits = -1; + break; + } + default: { + goto error; + } + + } + } + + return d; + + + error: + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + memset(&d, 0, sizeof(struct icaldurationtype)); + return d; + +} + +#define TMP_BUF_SIZE 1024 +void append_duration_segment(char** buf, char** buf_ptr, size_t* buf_size, + char* sep, unsigned int value) { + + char temp[TMP_BUF_SIZE]; + + sprintf(temp,"%d",value); + + icalmemory_append_string(buf, buf_ptr, buf_size, temp); + icalmemory_append_string(buf, buf_ptr, buf_size, sep); + +} + +char* icaldurationtype_as_ical_string(struct icaldurationtype d) +{ + + char *buf, *output_line; + size_t buf_size = 256; + char* buf_ptr = 0; + int seconds; + + buf = (char*)icalmemory_new_buffer(buf_size); + buf_ptr = buf; + + + seconds = icaldurationtype_as_int(d); + + if(seconds !=0){ + + if(d.is_neg == 1){ + icalmemory_append_char(&buf, &buf_ptr, &buf_size, '-'); + } + + icalmemory_append_char(&buf, &buf_ptr, &buf_size, 'P'); + + if (d.weeks != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "W", d.weeks); + } + + if (d.days != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "D", d.days); + } + + if (d.hours != 0 || d.minutes != 0 || d.seconds != 0) { + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T"); + + if (d.hours != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "H", d.hours); + } + if (d.minutes != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "M", + d.minutes); + } + if (d.seconds != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "S", + d.seconds); + } + + } + } else { + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "PTS0"); + } + + output_line = icalmemory_tmp_copy(buf); + icalmemory_free_buffer(buf); + + return output_line; + +} + +#endif + + +/* From Russel Steinthal */ +int icaldurationtype_as_int(struct icaldurationtype dur) +{ + return (int)( (dur.seconds + + (60 * dur.minutes) + + (60 * 60 * dur.hours) + + (60 * 60 * 24 * dur.days) + + (60 * 60 * 24 * 7 * dur.weeks)) + * (dur.is_neg==1? -1 : 1) ) ; +} + +struct icaldurationtype icaldurationtype_null_duration() +{ + struct icaldurationtype d; + + memset(&d,0,sizeof(struct icaldurationtype)); + + return d; +} + +int icaldurationtype_is_null_duration(struct icaldurationtype d) +{ + if(icaldurationtype_as_int(d) == 0){ + return 1; + } else { + return 0; + } +} + + + +struct icaltimetype icaltime_add(struct icaltimetype t, + struct icaldurationtype d) +{ + int dt = icaldurationtype_as_int(d); + + t.second += dt; + + t = icaltime_normalize(t); + + return t; +} + +struct icaldurationtype icaltime_subtract(struct icaltimetype t1, + struct icaltimetype t2) +{ + + time_t t1t = icaltime_as_timet(t1); + time_t t2t = icaltime_as_timet(t2); + + return icaldurationtype_from_int(t1t-t2t); + + +} + diff --git a/libical/src/libical/icalduration.h b/libical/src/libical/icalduration.h new file mode 100644 index 0000000..dd6e311 --- a/dev/null +++ b/libical/src/libical/icalduration.h @@ -0,0 +1,60 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalduration.h + CREATOR: eric 26 Jan 2001 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALDURATION_H +#define ICALDURATION_H + +#include "icaltime.h" + +struct icaldurationtype +{ + int is_neg; + unsigned int days; + unsigned int weeks; + unsigned int hours; + unsigned int minutes; + unsigned int seconds; +}; + +struct icaldurationtype icaldurationtype_from_int(int t); +struct icaldurationtype icaldurationtype_from_string(const char*); +int icaldurationtype_as_int(struct icaldurationtype duration); +char* icaldurationtype_as_ical_string(struct icaldurationtype d); +struct icaldurationtype icaldurationtype_null_duration(); +int icaldurationtype_is_null_duration(struct icaldurationtype d); + +struct icaltimetype icaltime_add(struct icaltimetype t, + struct icaldurationtype d); + +struct icaldurationtype icaltime_subtract(struct icaltimetype t1, + struct icaltimetype t2); + +#endif /* !ICALDURATION_H */ + + + diff --git a/libical/src/libical/icalenums.c b/libical/src/libical/icalenums.c new file mode 100644 index 0000000..6751933 --- a/dev/null +++ b/libical/src/libical/icalenums.c @@ -0,0 +1,135 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalenum.c + CREATOR: eric 29 April 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalenum.c + + ======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalenums.h" + +#include <stdio.h> /* For fprintf */ +#include <stdio.h> /* For stderr */ +#include <string.h> /* For strncmp */ +#include <assert.h> + + + +struct { + enum icalrequeststatus kind; + int major; + int minor; + const char* str; +} request_status_map[] = { + {ICAL_2_0_SUCCESS_STATUS, 2,0,"Success."}, + {ICAL_2_1_FALLBACK_STATUS, 2,1,"Success but fallback taken on one or more property values."}, + {ICAL_2_2_IGPROP_STATUS, 2,2,"Success, invalid property ignored."}, + {ICAL_2_3_IGPARAM_STATUS, 2,3,"Success, invalid property parameter ignored."}, + {ICAL_2_4_IGXPROP_STATUS, 2,4,"Success, unknown non-standard property ignored."}, + {ICAL_2_5_IGXPARAM_STATUS, 2,5,"Success, unknown non standard property value ignored."}, + {ICAL_2_6_IGCOMP_STATUS, 2,6,"Success, invalid calendar component ignored."}, + {ICAL_2_7_FORWARD_STATUS, 2,7,"Success, request forwarded to Calendar User."}, + {ICAL_2_8_ONEEVENT_STATUS, 2,8,"Success, repeating event ignored. Scheduled as a single component."}, + {ICAL_2_9_TRUNC_STATUS, 2,9,"Success, truncated end date time to date boundary."}, + {ICAL_2_10_ONETODO_STATUS, 2,10,"Success, repeating VTODO ignored. Scheduled as a single VTODO."}, + {ICAL_2_11_TRUNCRRULE_STATUS, 2,11,"Success, unbounded RRULE clipped at some finite number of instances "}, + {ICAL_3_0_INVPROPNAME_STATUS, 3,0,"Invalid property name."}, + {ICAL_3_1_INVPROPVAL_STATUS, 3,1,"Invalid property value."}, + {ICAL_3_2_INVPARAM_STATUS, 3,2,"Invalid property parameter."}, + {ICAL_3_3_INVPARAMVAL_STATUS, 3,3,"Invalid property parameter value."}, + {ICAL_3_4_INVCOMP_STATUS, 3,4,"Invalid calendar component."}, + {ICAL_3_5_INVTIME_STATUS, 3,5,"Invalid date or time."}, + {ICAL_3_6_INVRULE_STATUS, 3,6,"Invalid rule."}, + {ICAL_3_7_INVCU_STATUS, 3,7,"Invalid Calendar User."}, + {ICAL_3_8_NOAUTH_STATUS, 3,8,"No authority."}, + {ICAL_3_9_BADVERSION_STATUS, 3,9,"Unsupported version."}, + {ICAL_3_10_TOOBIG_STATUS, 3,10,"Request entity too large."}, + {ICAL_3_11_MISSREQCOMP_STATUS, 3,11,"Required component or property missing."}, + {ICAL_3_12_UNKCOMP_STATUS, 3,12,"Unknown component or property found."}, + {ICAL_3_13_BADCOMP_STATUS, 3,13,"Unsupported component or property found"}, + {ICAL_3_14_NOCAP_STATUS, 3,14,"Unsupported capability."}, + {ICAL_4_0_BUSY_STATUS, 4,0,"Event conflict. Date/time is busy."}, + {ICAL_5_0_MAYBE_STATUS, 5,0,"Request MAY supported."}, + {ICAL_5_1_UNAVAIL_STATUS, 5,1,"Service unavailable."}, + {ICAL_5_2_NOSERVICE_STATUS, 5,2,"Invalid calendar service."}, + {ICAL_5_3_NOSCHED_STATUS, 5,3,"No scheduling support for user."}, + {ICAL_UNKNOWN_STATUS, 0,0,"Error: Unknown request status"} +}; + + +const char* icalenum_reqstat_desc(icalrequeststatus stat) +{ + + int i; + + for (i=0; request_status_map[i].kind != ICAL_UNKNOWN_STATUS; i++) { + if ( request_status_map[i].kind == stat) { + return request_status_map[i].str; + } + } + + return 0; +} + + +short icalenum_reqstat_major(icalrequeststatus stat) +{ + int i; + + for (i=0; request_status_map[i].kind != ICAL_UNKNOWN_STATUS; i++) { + if ( request_status_map[i].kind == stat) { + return request_status_map[i].major; + } + } + return -1; +} + +short icalenum_reqstat_minor(icalrequeststatus stat) +{ + int i; + + for (i=0; request_status_map[i].kind != ICAL_UNKNOWN_STATUS; i++) { + if ( request_status_map[i].kind == stat) { + return request_status_map[i].minor; + } + } + return -1; +} + + +icalrequeststatus icalenum_num_to_reqstat(short major, short minor) +{ + int i; + + for (i=0; request_status_map[i].kind != ICAL_UNKNOWN_STATUS; i++) { + if ( request_status_map[i].major == major && request_status_map[i].minor == minor) { + return request_status_map[i].kind; + } + } + return 0; +} + + + diff --git a/libical/src/libical/icalenums.h b/libical/src/libical/icalenums.h new file mode 100644 index 0000000..21031dd --- a/dev/null +++ b/libical/src/libical/icalenums.h @@ -0,0 +1,157 @@ + +/* -*- Mode: C -*-*/ +/*====================================================================== + FILE: icalenums.h + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalenums.h + + Contributions from: + Graham Davison (g.m.davison@computer.org) + +======================================================================*/ + +#ifndef ICALENUMS_H +#define ICALENUMS_H + + + +/*********************************************************************** + * Component enumerations +**********************************************************************/ + +typedef enum icalcomponent_kind { + ICAL_NO_COMPONENT, + ICAL_ANY_COMPONENT, /* Used to select all components*/ + ICAL_XROOT_COMPONENT, + ICAL_XATTACH_COMPONENT, /* MIME attached data, returned by parser. */ + ICAL_VEVENT_COMPONENT, + ICAL_VTODO_COMPONENT, + ICAL_VJOURNAL_COMPONENT, + ICAL_VCALENDAR_COMPONENT, + ICAL_VFREEBUSY_COMPONENT, + ICAL_VALARM_COMPONENT, + ICAL_XAUDIOALARM_COMPONENT, + ICAL_XDISPLAYALARM_COMPONENT, + ICAL_XEMAILALARM_COMPONENT, + ICAL_XPROCEDUREALARM_COMPONENT, + ICAL_VTIMEZONE_COMPONENT, + ICAL_XSTANDARD_COMPONENT, + ICAL_XDAYLIGHT_COMPONENT, + ICAL_X_COMPONENT, + ICAL_VSCHEDULE_COMPONENT, + ICAL_VQUERY_COMPONENT, + ICAL_VCAR_COMPONENT, + ICAL_VCOMMAND_COMPONENT, + ICAL_XLICINVALID_COMPONENT, + ICAL_XLICMIMEPART_COMPONENT /* a non-stardard component that mirrors + structure of MIME data */ + +} icalcomponent_kind; + + + +/*********************************************************************** + * Request Status codes + **********************************************************************/ + +typedef enum icalrequeststatus { + ICAL_UNKNOWN_STATUS, + ICAL_2_0_SUCCESS_STATUS, + ICAL_2_1_FALLBACK_STATUS, + ICAL_2_2_IGPROP_STATUS, + ICAL_2_3_IGPARAM_STATUS, + ICAL_2_4_IGXPROP_STATUS, + ICAL_2_5_IGXPARAM_STATUS, + ICAL_2_6_IGCOMP_STATUS, + ICAL_2_7_FORWARD_STATUS, + ICAL_2_8_ONEEVENT_STATUS, + ICAL_2_9_TRUNC_STATUS, + ICAL_2_10_ONETODO_STATUS, + ICAL_2_11_TRUNCRRULE_STATUS, + ICAL_3_0_INVPROPNAME_STATUS, + ICAL_3_1_INVPROPVAL_STATUS, + ICAL_3_2_INVPARAM_STATUS, + ICAL_3_3_INVPARAMVAL_STATUS, + ICAL_3_4_INVCOMP_STATUS, + ICAL_3_5_INVTIME_STATUS, + ICAL_3_6_INVRULE_STATUS, + ICAL_3_7_INVCU_STATUS, + ICAL_3_8_NOAUTH_STATUS, + ICAL_3_9_BADVERSION_STATUS, + ICAL_3_10_TOOBIG_STATUS, + ICAL_3_11_MISSREQCOMP_STATUS, + ICAL_3_12_UNKCOMP_STATUS, + ICAL_3_13_BADCOMP_STATUS, + ICAL_3_14_NOCAP_STATUS, + ICAL_4_0_BUSY_STATUS, + ICAL_5_0_MAYBE_STATUS, + ICAL_5_1_UNAVAIL_STATUS, + ICAL_5_2_NOSERVICE_STATUS, + ICAL_5_3_NOSCHED_STATUS +} icalrequeststatus; + + +const char* icalenum_reqstat_desc(icalrequeststatus stat); +short icalenum_reqstat_major(icalrequeststatus stat); +short icalenum_reqstat_minor(icalrequeststatus stat); +icalrequeststatus icalenum_num_to_reqstat(short major, short minor); + +/*********************************************************************** + * Conversion functions +**********************************************************************/ + + +/* Thse routines used to be in icalenums.c, but were moved into the + icalproperty, icalparameter, icalvalue, or icalcomponent modules. */ + +/* const char* icalproperty_kind_to_string(icalproperty_kind kind);*/ +#define icalenum_property_kind_to_string(x) icalproperty_kind_to_string(x) + +/*icalproperty_kind icalproperty_string_to_kind(const char* string)*/ +#define icalenum_string_to_property_kind(x) icalproperty_string_to_kind(x) + +/*icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind);*/ +#define icalenum_property_kind_to_value_kind(x) icalproperty_kind_to_value_kind(x) + +/*const char* icalenum_method_to_string(icalproperty_method);*/ +#define icalenum_method_to_string(x) icalproperty_method_to_string(x) + +/*icalproperty_method icalenum_string_to_method(const char* string);*/ +#define icalenum_string_to_method(x) icalproperty_string_to_method(x) + +/*const char* icalenum_status_to_string(icalproperty_status);*/ +#define icalenum_status_to_string(x) icalproperty_status_to_string(x) + +/*icalproperty_status icalenum_string_to_status(const char* string);*/ +#define icalenum_string_to_status(x) icalproperty_string_to_status(x) + +/*icalvalue_kind icalenum_string_to_value_kind(const char* str);*/ +#define icalenum_string_to_value_kind(x) icalvalue_string_to_kind(x) + +/*const char* icalenum_value_kind_to_string(icalvalue_kind kind);*/ +#define icalenum_value_kind_to_string(x) icalvalue_kind_to_string(x) + +/*const char* icalenum_component_kind_to_string(icalcomponent_kind kind);*/ +#define icalenum_component_kind_to_string(x) icalcomponent_kind_to_string(x) + +/*icalcomponent_kind icalenum_string_to_component_kind(const char* string);*/ +#define icalenum_string_to_component_kind(x) icalcomponent_string_to_kind(x) + + +#endif /* !ICALENUMS_H */ + diff --git a/libical/src/libical/icalerror.c b/libical/src/libical/icalerror.c new file mode 100644 index 0000000..d44d37a --- a/dev/null +++ b/libical/src/libical/icalerror.c @@ -0,0 +1,209 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalerror.c + CREATOR: eric 16 May 1999 + + $Id$ + $Locker$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalerror.c + + ======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalerror.h" + +#include <string.h> + +icalerrorenum icalerrno; + +int foo; +void icalerror_stop_here(void) +{ + foo++; /* Keep optimizers from removing routine */ +} + +void icalerror_crash_here(void) +{ + int *p=0; + *p = 1; + + assert( *p); +} + +#ifdef ICAL_SETERROR_ISFUNC +void icalerror_set_errno(icalerrorenum x) +{ + icalerrno = x; + if(icalerror_get_error_state(x)==ICAL_ERROR_FATAL || + (icalerror_get_error_state(x)==ICAL_ERROR_DEFAULT && + icalerror_errors_are_fatal == 1 )){ + icalerror_warn(icalerror_strerror(x)); + assert(0); + } + +} +#endif + +void icalerror_clear_errno() { + + icalerrno = ICAL_NO_ERROR; +} + +#ifdef ICAL_ERRORS_ARE_FATAL +int icalerror_errors_are_fatal = 1; +#else +int icalerror_errors_are_fatal = 0; +#endif + +struct icalerror_state { + icalerrorenum error; + icalerrorstate state; +}; + +struct icalerror_state error_state_map[] = +{ + { ICAL_BADARG_ERROR,ICAL_ERROR_DEFAULT}, + { ICAL_NEWFAILED_ERROR,ICAL_ERROR_DEFAULT}, + { ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_DEFAULT}, + { ICAL_PARSE_ERROR,ICAL_ERROR_DEFAULT}, + { ICAL_INTERNAL_ERROR,ICAL_ERROR_DEFAULT}, + { ICAL_FILE_ERROR,ICAL_ERROR_DEFAULT}, + { ICAL_USAGE_ERROR,ICAL_ERROR_DEFAULT}, + { ICAL_UNIMPLEMENTED_ERROR,ICAL_ERROR_DEFAULT}, + { ICAL_UNKNOWN_ERROR,ICAL_ERROR_DEFAULT}, + { ICAL_NO_ERROR,ICAL_ERROR_DEFAULT} + +}; + +struct icalerror_string_map { + const char* str; + icalerrorenum error; + char name[160]; +}; + +static struct icalerror_string_map string_map[] = +{ + {"BADARG",ICAL_BADARG_ERROR,"BADARG: Bad argument to function"}, + { "NEWFAILED",ICAL_NEWFAILED_ERROR,"NEWFAILED: Failed to create a new object via a *_new() routine"}, + {"MALFORMEDDATA",ICAL_MALFORMEDDATA_ERROR,"MALFORMEDDATA: An input string was not correctly formed or a component has missing or extra properties"}, + { "PARSE",ICAL_PARSE_ERROR,"PARSE: Failed to parse a part of an iCal component"}, + {"INTERNAL",ICAL_INTERNAL_ERROR,"INTERNAL: Random internal error. This indicates an error in the library code, not an error in use"}, + { "FILE",ICAL_FILE_ERROR,"FILE: An operation on a file failed. Check errno for more detail."}, + { "USAGE",ICAL_USAGE_ERROR,"USAGE: Failed to propertyl sequence calls to a set of interfaces"}, + { "UNIMPLEMENTED",ICAL_UNIMPLEMENTED_ERROR,"UNIMPLEMENTED: This feature has not been implemented"}, + { "NO",ICAL_NO_ERROR,"NO: No error"}, + {"UNKNOWN",ICAL_UNKNOWN_ERROR,"UNKNOWN: Unknown error type -- icalerror_strerror() was probably given bad input"} +}; + + +icalerrorenum icalerror_error_from_string(const char* str){ + + icalerrorenum e; + int i = 0; + + for( i = 0; string_map[i].error != ICAL_NO_ERROR; i++){ + if (strcmp(string_map[i].str,str) == 0){ + e = string_map[i].error; + } + } + + return e; +} + +icalerrorstate icalerror_supress(const char* error){ + + icalerrorenum e = icalerror_error_from_string(error); + icalerrorstate es; + + if (e == ICAL_NO_ERROR){ + return ICAL_ERROR_UNKNOWN; + } + + + es = icalerror_get_error_state(e); + icalerror_set_error_state(e,ICAL_ERROR_NONFATAL); + + return es; +} + +char* icalerror_perror() +{ + return icalerror_strerror(icalerrno); +} + +void icalerror_restore(const char* error, icalerrorstate es){ + + + icalerrorenum e = icalerror_error_from_string(error); + + if (e != ICAL_NO_ERROR){ + icalerror_set_error_state(e,es); + } + +} + + + +void icalerror_set_error_state( icalerrorenum error, + icalerrorstate state) +{ + int i; + + for(i = ICAL_BADARG_ERROR; error_state_map[i].error!= ICAL_NO_ERROR;i++){ + if(error_state_map[i].error == error){ + error_state_map[i].state = state; + } + } +} + +icalerrorstate icalerror_get_error_state( icalerrorenum error) +{ + int i; + + for(i = ICAL_BADARG_ERROR; error_state_map[i].error!= ICAL_NO_ERROR;i++){ + if(error_state_map[i].error == error){ + return error_state_map[i].state; + } + } + + return ICAL_ERROR_UNKNOWN; +} + + + + +char* icalerror_strerror(icalerrorenum e) { + + int i; + + for (i=0; string_map[i].error != ICAL_UNKNOWN_ERROR; i++) { + if (string_map[i].error == e) { + return string_map[i].name; + } + } + + return string_map[i].name; /* Return string for ICAL_UNKNOWN_ERROR*/ + +} + + + diff --git a/libical/src/libical/icalerror.h b/libical/src/libical/icalerror.h new file mode 100644 index 0000000..52f5ba9 --- a/dev/null +++ b/libical/src/libical/icalerror.h @@ -0,0 +1,156 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalerror.h + CREATOR: eric 09 May 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalerror.h + +======================================================================*/ + + +#ifndef ICALERROR_H +#define ICALERROR_H + +#include <assert.h> +#include <stdio.h> /* For icalerror_warn() */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define ICAL_SETERROR_ISFUNC + + +/* This routine is called before any error is triggered. It is called + by icalerror_set_errno, so it does not appear in all of the macros + below */ +void icalerror_stop_here(void); + +void icalerror_crash_here(void); + +typedef enum icalerrorenum { + + ICAL_BADARG_ERROR, + ICAL_NEWFAILED_ERROR, + ICAL_ALLOCATION_ERROR, + ICAL_MALFORMEDDATA_ERROR, + ICAL_PARSE_ERROR, + ICAL_INTERNAL_ERROR, /* Like assert --internal consist. prob */ + ICAL_FILE_ERROR, + ICAL_USAGE_ERROR, + ICAL_UNIMPLEMENTED_ERROR, + ICAL_UNKNOWN_ERROR, /* Used for problems in input to icalerror_strerror()*/ + ICAL_NO_ERROR + +} icalerrorenum; + +/* The libical error enumeration, like errno*/ +extern icalerrorenum icalerrno; + +/* If true, libicl aborts after a call to icalerror_set_error*/ +extern int icalerror_errors_are_fatal; + +/* Warning messages */ + +#ifdef __GNUC__ca +#define icalerror_warn(message) {fprintf(stderr,"%s(), %s:%d: %s\n",__FUNCTION__,__FILE__,__LINE__,message);} +#else /* __GNU_C__ */ +#define icalerror_warn(message) {fprintf(stderr,"%s:%d: %s\n",__FILE__,__LINE__,message);} +#endif /* __GNU_C__ */ + + +void icalerror_clear_errno(void); + +/* Make an individual error fatal or non-fatal. */ +typedef enum icalerrorstate { + ICAL_ERROR_FATAL, /* Not fata */ + ICAL_ERROR_NONFATAL, /* Fatal */ + ICAL_ERROR_DEFAULT, /* Use the value of icalerror_errors_are_fatal*/ + ICAL_ERROR_UNKNOWN /* Asked state for an unknown error type */ +} icalerrorstate ; + +char* icalerror_strerror(icalerrorenum e); +char* icalerror_perror(); +void icalerror_set_error_state( icalerrorenum error, icalerrorstate); +icalerrorstate icalerror_get_error_state( icalerrorenum error); + +#ifndef ICAL_SETERROR_ISFUNC +#define icalerror_set_errno(x) \ +icalerrno = x; \ +if(icalerror_get_error_state(x)==ICAL_ERROR_FATAL || \ + (icalerror_get_error_state(x)==ICAL_ERROR_DEFAULT && \ + icalerror_errors_are_fatal == 1 )){ \ + icalerror_warn(icalerror_strerror(x)); \ + assert(0); \ +} +#else +void icalerror_set_errno(icalerrorenum); +#endif + +#ifdef ICAL_ERRORS_ARE_FATAL +#undef NDEBUG +#endif + +#define icalerror_check_value_type(value,type); +#define icalerror_check_property_type(value,type); +#define icalerror_check_parameter_type(value,type); +#define icalerror_check_component_type(value,type); + +/* Assert with a message */ +#ifdef ICAL_ERRORS_ARE_FATAL + +#ifdef __GNUC__ +#define icalerror_assert(test,message) if(!(test)){fprintf(stderr,"%s(), %s:%d: %s\n",__FUNCTION__,__FILE__,__LINE__,message);icalerror_stop_here(); abort();} +#else /*__GNUC__*/ +#define icalerror_assert(test,message) if(!(test)){fprintf(stderr,"%s:%d: %s\n",__FILE__,__LINE__,message);icalerror_stop_here(); abort();} +#endif /*__GNUC__*/ + +#else /* ICAL_ERRORS_ARE_FATAL */ +#define icalerror_assert(test,message) +#endif /* ICAL_ERRORS_ARE_FATAL */ + +/* Check & abort if check fails */ +#define icalerror_check_arg(test,arg) if(!(test)) { icalerror_set_errno(ICAL_BADARG_ERROR); } + +/* Check & return void if check fails*/ +#define icalerror_check_arg_rv(test,arg) if(!(test)) {icalerror_set_errno(ICAL_BADARG_ERROR); return; } + +/* Check & return 0 if check fails*/ +#define icalerror_check_arg_rz(test,arg) if(!(test)) { icalerror_set_errno(ICAL_BADARG_ERROR); return 0;} + +/* Check & return an error if check fails*/ +#define icalerror_check_arg_re(test,arg,error) if(!(test)) { icalerror_stop_here(); assert(0); return error;} + +/* Check & return something*/ +#define icalerror_check_arg_rx(test,arg,x) if(!(test)) { icalerror_set_errno(ICAL_BADARG_ERROR); return x;} + + + +/* String interfaces to set an error to NONFATAL and restore it to its + original value */ + +icalerrorstate icalerror_supress(const char* error); +void icalerror_restore(const char* error, icalerrorstate es); + + +#endif /* !ICALERROR_H */ + + + diff --git a/libical/src/libical/icallangbind.c b/libical/src/libical/icallangbind.c new file mode 100644 index 0000000..c079034 --- a/dev/null +++ b/libical/src/libical/icallangbind.c @@ -0,0 +1,275 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icallangbind.c + CREATOR: eric 15 dec 2000 + + DESCRIPTION: + + $Id$ + $Locker$ + + (C) COPYRIGHT 1999 Eric Busboom + http://www.softwarestudio.org + + This package is free software and is provided "as is" without + express or implied warranty. It may be used, redistributed and/or + modified under the same terms as perl itself. ( Either the Artistic + License or the GPL. ) + + ======================================================================*/ + +#include "icalcomponent.h" +#include "icalproperty.h" +#include "icalerror.h" +#include "icalmemory.h" +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +int snprintf(char *str, size_t n, char const *fmt, ...); + +int* icallangbind_new_array(int size){ + int* p = (int*)malloc(size*sizeof(int)); + return p; /* Caller handles failures */ +} + +void icallangbind_free_array(int* array){ + free(array); +} + +int icallangbind_access_array(int* array, int index) { + return array[index]; +} + + + +/* LIke icalcomponent_get_first_component, buut takes a string for the + kind and can iterate over X properties as if each X name was a + seperate kind */ +icalproperty* icallangbind_get_first_property(icalcomponent *c, + const char* prop) +{ + icalproperty_kind kind = icalproperty_string_to_kind(prop); + icalproperty *p; + + if (kind == ICAL_NO_PROPERTY){ + return 0; + } + + if(kind == ICAL_X_PROPERTY){ + for(p = icalcomponent_get_first_property(c,kind); + p !=0; + p = icalcomponent_get_next_property(c,kind)){ + + if(strcmp(icalproperty_get_x_name(p),prop) == 0){ + return p; + } + } + } else { + p=icalcomponent_get_first_property(c,kind); + + return p; + } + + return 0; + +} + +icalproperty* icallangbind_get_next_property(icalcomponent *c, + const char* prop) +{ + icalproperty_kind kind = icalenum_string_to_property_kind(prop); + icalproperty *p; + + if (kind == ICAL_NO_PROPERTY){ + return 0; + } + + if(kind == ICAL_X_PROPERTY){ + for(p = icalcomponent_get_next_property(c,kind); + p !=0; + p = icalcomponent_get_next_property(c,kind)){ + + if(strcmp(icalproperty_get_x_name(p),prop) == 0){ + return p; + } + } + } else { + p=icalcomponent_get_next_property(c,kind); + + return p; + } + + return 0; + +} + + +icalcomponent* icallangbind_get_first_component(icalcomponent *c, + const char* comp) +{ + icalcomponent_kind kind = icalenum_string_to_component_kind(comp); + + if (kind == ICAL_NO_COMPONENT){ + return 0; + } + return icalcomponent_get_first_component(c,kind); +} + +icalcomponent* icallangbind_get_next_component(icalcomponent *c, + const char* comp) +{ + icalcomponent_kind kind = icalenum_string_to_component_kind(comp); + + if (kind == ICAL_NO_COMPONENT){ + return 0; + } + return icalcomponent_get_next_component(c,kind); +} + + +#define APPENDS(x) icalmemory_append_string(&buf, &buf_ptr, &buf_size, x); + +#define APPENDC(x) icalmemory_append_char(&buf, &buf_ptr, &buf_size, x); + +const char* icallangbind_property_eval_string(icalproperty* prop, char* sep) +{ + char tmp[25]; + size_t buf_size = 1024; + char* buf = icalmemory_new_buffer(buf_size); + char* buf_ptr = buf; + icalparameter *param; + + icalvalue* value; + + if( prop == 0){ + return 0; + } + + APPENDS("{ "); + + value = icalproperty_get_value(prop); + + APPENDS(" 'name' "); + APPENDS(sep); + APPENDC('\''); + APPENDS(icalenum_property_kind_to_string(icalproperty_isa(prop))); + APPENDC('\''); + + if(value){ + APPENDS(", 'value_type' "); + APPENDS(sep); + APPENDC('\''); + APPENDS(icalenum_value_kind_to_string(icalvalue_isa(value))); + APPENDC('\''); + } + + APPENDS(", 'pid' "); + APPENDS(sep); + APPENDC('\''); + snprintf(tmp,25,"%p",prop); + APPENDS(tmp); + APPENDC('\''); + + + if(value){ + switch (icalvalue_isa(value)){ + + case ICAL_ATTACH_VALUE: + case ICAL_BINARY_VALUE: + case ICAL_NO_VALUE: { + icalerror_set_errno(ICAL_INTERNAL_ERROR); + break; + } + + default: + { + const char* str = icalvalue_as_ical_string(value); + char* copy = (char*) malloc(strlen(str)+1); + + const char *i; + char *j; + + if(copy ==0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + break; + } + /* Remove any newlines */ + + for(j=copy, i = str; *i != 0; j++,i++){ + if(*i=='\n'){ + i++; + } + *j = *i; + } + + *j = 0; + + APPENDS(", 'value'"); + APPENDS(sep); + APPENDC('\''); + APPENDS(copy); + APPENDC('\''); + + free(copy); + break; + + } + } + } + + /* Add Parameters */ + + for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER); + param != 0; + param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)){ + + const char* str = icalparameter_as_ical_string(param); + char *copy = icalmemory_tmp_copy(str); + char *v; + + if(copy == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + continue; + } + + v = strchr(copy,'='); + + + if(v == 0){ + continue; + } + + *v = 0; + + v++; + + APPENDS(", "); + APPENDC('\''); + APPENDS(copy); + APPENDC('\''); + APPENDS(sep); + APPENDC('\''); + APPENDS(v); + APPENDC('\''); + + } + + + APPENDC('}'); + + icalmemory_add_tmp_buffer(buf); + return buf; + +} + +#include "fcntl.h" +int icallangbind_string_to_open_flag(const char* str) +{ + if (strcmp(str,"r") == 0) {return O_RDONLY;} + else if (strcmp(str,"r+") == 0) {return O_RDWR;} + else if (strcmp(str,"w") == 0) {return O_WRONLY;} + else if (strcmp(str,"a") == 0) {return O_WRONLY|O_APPEND;} + else return -1; +} + diff --git a/libical/src/libical/icallangbind.h b/libical/src/libical/icallangbind.h new file mode 100644 index 0000000..2ed5003 --- a/dev/null +++ b/libical/src/libical/icallangbind.h @@ -0,0 +1,49 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icallangbind.h + CREATOR: eric 25 jan 2001 + + DESCRIPTION: + + $Id$ + $Locker$ + + (C) COPYRIGHT 1999 Eric Busboom + http://www.softwarestudio.org + + This package is free software and is provided "as is" without + express or implied warranty. It may be used, redistributed and/or + modified under the same terms as perl itself. ( Either the Artistic + License or the GPL. ) + + ======================================================================*/ + +#ifndef __ICALLANGBIND_H__ +#define __ICALLANGBIND_H__ + +int* icallangbind_new_array(int size); +void icallangbind_free_array(int* array); +int icallangbind_access_array(int* array, int index); +icalproperty* icallangbind_get_property(icalcomponent *c, int n, const char* prop); +const char* icallangbind_get_property_val(icalproperty* p); +const char* icallangbind_get_parameter(icalproperty *p, const char* parameter); +icalcomponent* icallangbind_get_component(icalcomponent *c, const char* comp); + +icalproperty* icallangbind_get_first_property(icalcomponent *c, + const char* prop); + +icalproperty* icallangbind_get_next_property(icalcomponent *c, + const char* prop); + +icalcomponent* icallangbind_get_first_component(icalcomponent *c, + const char* comp); + +icalcomponent* icallangbind_get_next_component(icalcomponent *c, + const char* comp); + + +const char* icallangbind_property_eval_string(icalproperty* prop, char* sep); + + +int icallangbind_string_to_open_flag(const char* str); +#endif /*__ICALLANGBIND_H__*/ diff --git a/libical/src/libical/icallexer.c b/libical/src/libical/icallexer.c new file mode 100644 index 0000000..4dd26c3 --- a/dev/null +++ b/libical/src/libical/icallexer.c @@ -0,0 +1,1793 @@ +#define yy_create_buffer ical_yy_create_buffer +#define yy_delete_buffer ical_yy_delete_buffer +#define yy_scan_buffer ical_yy_scan_buffer +#define yy_scan_string ical_yy_scan_string +#define yy_scan_bytes ical_yy_scan_bytes +#define yy_flex_debug ical_yy_flex_debug +#define yy_init_buffer ical_yy_init_buffer +#define yy_flush_buffer ical_yy_flush_buffer +#define yy_load_buffer_state ical_yy_load_buffer_state +#define yy_switch_to_buffer ical_yy_switch_to_buffer +#define yyin ical_yyin +#define yyleng ical_yyleng +#define yylex ical_yylex +#define yyout ical_yyout +#define yyrestart ical_yyrestart +#define yytext ical_yytext +#define yywrap ical_yywrap + +#line 20 "lex.yy.c" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header$ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + + +#include <stdlib.h> +// Eugen C. <eug@thekompany.com> +#ifndef _WIN32 +#include <unistd.h> +#else +#include <io.h> +#include <stdio.h> + +#endif +// Eugen C. <eug@thekompany.com> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char yytext[]; + + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + if ( yyleng >= YYLMAX ) \ + YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \ + yy_flex_strncpy( yytext, yytext_ptr, yyleng + 1 ); \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 12 +#define YY_END_OF_BUFFER 13 +static yyconst short int yy_accept[67] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 12, 5, 12, 4, 1, + 2, 3, 6, 12, 7, 12, 9, 10, 9, 11, + 5, 1, 6, 8, 10, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 4, 5, 6, 1, 7, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 7, 1, 1, + 1, 7, 1, 1, 1, 1, 7, 1, 1, 7, + 1, 1, 7, 9, 1, 1, 7, 1, 1, 10, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, + + 1, 1, 1, 7, 1, 1, 1, 1, 7, 1, + 1, 7, 1, 1, 7, 9, 1, 1, 7, 1, + 1, 10, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[11] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + } ; + +static yyconst short int yy_base[69] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 16, 18, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 25, 24, 0, 0, + 0, 0, 0, 0, 28, 31, 31, 25, 31, 18, + 31, 31, 31, 23, 31, 16, 31, 31, 21, 31, + 31, 14, 31, 31, 31, 31, 15, 13 + } ; + +static yyconst short int yy_def[69] = + { 0, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 66, 11, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 23, 68, 68, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 0, 66, 66 + } ; + +static yyconst short int yy_nxt[42] = + { 0, + 46, 47, 48, 49, 46, 49, 49, 50, 51, 52, + 53, 54, 55, 57, 55, 46, 56, 58, 59, 58, + 59, 62, 65, 64, 63, 62, 61, 66, 60, 60, + 45, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66 + } ; + +static yyconst short int yy_chk[42] = + { 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 23, 23, 23, 68, 23, 67, 23, 25, 25, 26, + 26, 62, 59, 56, 54, 50, 48, 45, 38, 37, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#ifndef YYLMAX +#define YYLMAX 8192 +#endif + +char yytext[YYLMAX]; +char *yytext_ptr; +#line 1 "../../../../libical/src/libical/icallexer.l" +#define INITIAL 0 +#line 2 "../../../../libical/src/libical/icallexer.l" +/* -*- Mode: C -*- + ====================================================================== + FILE: icallexer.l + CREATOR: eric 10 June 1999 + + DESCRIPTION: + + $Id$ + $Locker$ + + (C) COPYRIGHT 1999 Eric Busboom + http://www.softwarestudio.org + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + The original author is Eric Busboom + The original code is icalitip.y + + + + ======================================================================*/ +#include "icalparser.h" +#include "icalenums.h" +#include "icalmemory.h" +#include "assert.h" +#include "icalyacc.h" + +#ifdef _WIN32 +#include <stdio.h> +#include <stdlib.h> +#endif + +#include <string.h> /* For strdup() */ + +int icalparser_flex_input(char* buf, int max_size); +void icalparser_clear_flex_input(void); + + +#define ICAL_MAX_STR_CONST 1024 + +#undef YY_INPUT +#define YY_INPUT(b,r,ms) ( r= icalparser_flex_input(b,ms)) +#undef yywrap + +#undef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) ical_yyerror(msg) + +icalvalue_kind value_kind=ICAL_NO_VALUE; +void set_parser_value_state(icalvalue_kind kind); +extern int yydebug; + +void ical_yyerror(char *s); + +void init_str_buf(void); + +int last_state; + +char *str_buf; +char *str_buf_p; +size_t buf_sz; /* = ICAL_MAX_STR_CONST;*/ + +/* Define routines that were not propertly defined because of the +renaming hack applied in icalyacc.y */ +YY_BUFFER_STATE ical_yy_scan_buffer ( char *base, yy_size_t size ); +YY_BUFFER_STATE ical_yy_scan_string ( yyconst char *yy_str ); +YY_BUFFER_STATE ical_yy_scan_bytes ( yyconst char *bytes, int len ); + +#define quoted_string 1 + +#define binary_value 2 +#define boolean_value 3 +#define uri_value 4 +#define time_value 5 +#define duration_value 6 +#define number_value 7 +#define period_value 8 +#define recur_value 9 +#define text_value 10 +#define utcoffset_value 11 + +#define enum_param_value 12 +#define string_param_value 13 +#define stringlist_param_value 14 +#define keyword 15 +#define line_start 16 +#define component 17 +#define seperator 18 +#define parameter 19 +#define end_of_value 20 +#define paramtext 21 + +#line 511 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 97 "../../../../libical/src/libical/icallexer.l" + + + + + + + +#line 670 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 67 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 31 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + + +case 1: +YY_RULE_SETUP +#line 105 "../../../../libical/src/libical/icallexer.l" +{ ical_yylval.v_string =icalmemory_tmp_copy(yytext) ; + return DIGITS; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 107 "../../../../libical/src/libical/icallexer.l" +{ return TIME_CHAR; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 108 "../../../../libical/src/libical/icallexer.l" +{ return UTC_CHAR; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 109 "../../../../libical/src/libical/icallexer.l" +{ return yytext[0]; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 110 "../../../../libical/src/libical/icallexer.l" +{ return EOL;} + YY_BREAK + + +case 6: +YY_RULE_SETUP +#line 115 "../../../../libical/src/libical/icallexer.l" +{ return EOL;} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 116 "../../../../libical/src/libical/icallexer.l" +{ return yytext[0]; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 117 "../../../../libical/src/libical/icallexer.l" +{ ical_yylval.v_int=atoi(yytext); return INTNUMBER; } + YY_BREAK + + +case 9: +YY_RULE_SETUP +#line 122 "../../../../libical/src/libical/icallexer.l" +{ return CHARACTER; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 123 "../../../../libical/src/libical/icallexer.l" +{ return EOL;} + YY_BREAK + + +case 11: +YY_RULE_SETUP +#line 128 "../../../../libical/src/libical/icallexer.l" +{ BEGIN(last_state); return COMMA; } + YY_BREAK + +case 12: +YY_RULE_SETUP +#line 132 "../../../../libical/src/libical/icallexer.l" +ECHO; + YY_BREAK +#line 822 "lex.yy.c" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(quoted_string): +case YY_STATE_EOF(binary_value): +case YY_STATE_EOF(boolean_value): +case YY_STATE_EOF(uri_value): +case YY_STATE_EOF(time_value): +case YY_STATE_EOF(duration_value): +case YY_STATE_EOF(number_value): +case YY_STATE_EOF(period_value): +case YY_STATE_EOF(recur_value): +case YY_STATE_EOF(text_value): +case YY_STATE_EOF(utcoffset_value): +case YY_STATE_EOF(enum_param_value): +case YY_STATE_EOF(string_param_value): +case YY_STATE_EOF(stringlist_param_value): +case YY_STATE_EOF(keyword): +case YY_STATE_EOF(line_start): +case YY_STATE_EOF(component): +case YY_STATE_EOF(seperator): +case YY_STATE_EOF(parameter): +case YY_STATE_EOF(end_of_value): +case YY_STATE_EOF(paramtext): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 67 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 67 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 66); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE + +#ifndef _WIN32 +#include <unistd.h> +#else +#include <io.h> +#include <stdio.h> + +#endif + +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + +#ifdef _WIN32 + b->yy_is_interactive = file ? (_isatty( fileno(file) ) > 0) : 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif + +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 132 "../../../../libical/src/libical/icallexer.l" + + +int yywrap() +{ + return 1; +} + + +void set_parser_value_state(icalvalue_kind kind) +{ + + switch (kind){ + + case ICAL_UTCOFFSET_VALUE: + {BEGIN(utcoffset_value);break;} + + case ICAL_DATETIMEPERIOD_VALUE: + case ICAL_DURATION_VALUE: + case ICAL_PERIOD_VALUE: + {BEGIN(time_value);break;} + + default: + { + assert(1==0); + } + } +} + +void init_str_buf(void) +{ + str_buf = icalmemory_tmp_buffer(ICAL_MAX_STR_CONST); + str_buf_p = str_buf; + buf_sz = ICAL_MAX_STR_CONST; + + +} + diff --git a/libical/src/libical/icallexer.l b/libical/src/libical/icallexer.l new file mode 100644 index 0000000..53b396a --- a/dev/null +++ b/libical/src/libical/icallexer.l @@ -0,0 +1,170 @@ +%{ +/* -*- Mode: C -*- + ====================================================================== + FILE: icallexer.l + CREATOR: eric 10 June 1999 + + DESCRIPTION: + + $Id$ + $Locker$ + + (C) COPYRIGHT 1999 Eric Busboom + http://www.softwarestudio.org + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + The original author is Eric Busboom + The original code is icalitip.y + + + + ======================================================================*/ +#include "icalparser.h" +#include "icalenums.h" +#include "icalmemory.h" +#include "assert.h" +#include "icalyacc.h" + +#include <string.h> /* For strdup() */ +#include <stdlib.h> +#include <math.h> + +int icalparser_flex_input(char* buf, int max_size); +void icalparser_clear_flex_input(void); + + +#define ICAL_MAX_STR_CONST 1024 + +#undef YY_INPUT +#define YY_INPUT(b,r,ms) ( r= icalparser_flex_input(b,ms)) +#undef yywrap + +#undef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) ical_yyerror(msg) + +icalvalue_kind value_kind=ICAL_NO_VALUE; +void set_parser_value_state(icalvalue_kind kind); +extern int yydebug; + +void ical_yyerror(char *s); + +void init_str_buf(void); + +int last_state; + +char *str_buf; +char *str_buf_p; +size_t buf_sz; /* = ICAL_MAX_STR_CONST;*/ + +/* Define routines that were not propertly defined because of the +renaming hack applied in icalyacc.y */ +YY_BUFFER_STATE ical_yy_scan_buffer ( char *base, yy_size_t size ); +YY_BUFFER_STATE ical_yy_scan_string ( yyconst char *yy_str ); +YY_BUFFER_STATE ical_yy_scan_bytes ( yyconst char *bytes, int len ); + +%} + +crlf \x0D?\x0A +space [ ] +qsafechar [^\x00-\x1F\"] +safechar [^\x00-\x1F\"\:\;\,] +tsafechar [\x20-\x21\x23-\x2B\x2D-\x39\x3C-\x5B\x5D-\x7E] +valuechar [^\x00-\x08\x10-\x1F] +xname X-[a-zA-Z0-9\-]+ +xname2 [a-zA-Z0-9\-\ ] +paramtext {safechar}+ +value {valuechar}+ +quotedstring \"{qsafechar}+\" +digit [0-9] + +%array /* Make yytext an array. Slow, but handy. HACK */ + +%option caseless + +%s quoted_string +%s binary_value boolean_value uri_value time_value duration_value number_value period_value recur_value text_value utcoffset_value +%s enum_param_value string_param_value stringlist_param_value keyword line_start component seperator parameter end_of_value paramtext + + + +%% + +%{ +%} + + + +<time_value>{ +{digit}+ { ical_yylval.v_string =icalmemory_tmp_copy(yytext) ; + return DIGITS; } +T { return TIME_CHAR; } +Z { return UTC_CHAR; } +[\/\+\-PWHMSD] { return yytext[0]; } +{crlf} { return EOL;} + +} + +<utcoffset_value>{ +{crlf} { return EOL;} +\-|\+ { return yytext[0]; } +{digit}{digit} { ical_yylval.v_int=atoi(yytext); return INTNUMBER; } + +} + +<enum_param_value>{ +. { return CHARACTER; } +{crlf} { return EOL;} + +} + +<seperator>{ +, { BEGIN(last_state); return COMMA; } +} + + +%% + +int yywrap() +{ + return 1; +} + + +void set_parser_value_state(icalvalue_kind kind) +{ + + switch (kind){ + + case ICAL_UTCOFFSET_VALUE: + {BEGIN(utcoffset_value);break;} + + case ICAL_DATETIMEPERIOD_VALUE: + case ICAL_DURATION_VALUE: + case ICAL_PERIOD_VALUE: + {BEGIN(time_value);break;} + + default: + { + assert(1==0); + } + } +} + +void init_str_buf(void) +{ + str_buf = icalmemory_tmp_buffer(ICAL_MAX_STR_CONST); + str_buf_p = str_buf; + buf_sz = ICAL_MAX_STR_CONST; + + +} + diff --git a/libical/src/libical/icalmemory.c b/libical/src/libical/icalmemory.c new file mode 100644 index 0000000..297ead8 --- a/dev/null +++ b/libical/src/libical/icalmemory.c @@ -0,0 +1,287 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalmemory.c + CREATOR: eric 30 June 1999 + + $Id$ + $Locker$ + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is icalmemory.h + + ======================================================================*/ + +/* libical often passes strings back to the caller. To make these + * interfaces simple, I did not want the caller to have to pass in a + * memory buffer, but having libical pass out newly allocated memory + * makes it difficult to de-allocate the memory. + * + * The ring buffer in this scheme makes it possible for libical to pass + * out references to memory which the caller does not own, and be able + * to de-allocate the memory later. The ring allows libical to have + * several buffers active simultaneously, which is handy when creating + * string representations of components. */ + +#define ICALMEMORY_C + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#include "icalmemory.h" +#include "icalerror.h" + +#include <stdio.h> /* for printf (debugging) */ +#include <stdlib.h> /* for malloc, realloc */ +#include <string.h> /* for memset(), strdup */ + +#define BUFFER_RING_SIZE 25 +#define MIN_BUFFER_SIZE 200 + +void icalmemory_free_tmp_buffer (void* buf); + + +/* HACK. Not threadsafe */ +void* buffer_ring[BUFFER_RING_SIZE]; +int buffer_pos = -1; +int initialized = 0; + +/* Add an existing buffer to the buffer ring */ +void icalmemory_add_tmp_buffer(void* buf) +{ + /* I don't think I need this -- I think static arrays are + initialized to 0 as a standard part of C, but I am not sure. */ + if (initialized == 0){ + int i; + for(i=0; i<BUFFER_RING_SIZE; i++){ + buffer_ring[i] = 0; + } + initialized = 1; + } + + /* Wrap around the ring */ + if(++buffer_pos == BUFFER_RING_SIZE){ + buffer_pos = 0; + } + + /* Free buffers as their slots are overwritten */ + if ( buffer_ring[buffer_pos] != 0){ + free( buffer_ring[buffer_pos]); + buffer_ring[buffer_pos] = 0; + } + + /* Assign the buffer to a slot */ + buffer_ring[buffer_pos] = buf; +} + +/* Create a new temporary buffer on the ring. Libical owns these and + wil deallocate them. */ +void* +icalmemory_tmp_buffer (size_t size) +{ + char *buf; + + if (size < MIN_BUFFER_SIZE){ + size = MIN_BUFFER_SIZE; + } + + buf = (void*)malloc(size); + + if( buf == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + memset(buf,0,size); + + icalmemory_add_tmp_buffer(buf); + + return buf; +} + +void icalmemory_free_ring() +{ + + int i; + for(i=0; i<BUFFER_RING_SIZE; i++){ + if ( buffer_ring[i] != 0){ + free( buffer_ring[i]); + } + buffer_ring[i] = 0; + } + + initialized = 1; + +} + + + +/* Like strdup, but the buffer is on the ring. */ +char* +icalmemory_tmp_copy(const char* str) +{ + char* b = icalmemory_tmp_buffer(strlen(str)+1); + + strcpy(b,str); + + return b; +} + + +char* icalmemory_strdup(const char *s) +{ + return strdup(s); +} + +void +icalmemory_free_tmp_buffer (void* buf) +{ + if(buf == 0) + { + return; + } + + free(buf); +} + + +/* These buffer routines create memory the old fashioned way -- so the + caller will have to delocate the new memory */ + +void* icalmemory_new_buffer(size_t size) +{ + void *b = malloc(size); + + if( b == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + memset(b,0,size); + + return b; +} + +void* icalmemory_resize_buffer(void* buf, size_t size) +{ + void *b = realloc(buf, size); + + if( b == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + return b; +} + +void icalmemory_free_buffer(void* buf) +{ + free(buf); +} + +void +icalmemory_append_string(char** buf, char** pos, size_t* buf_size, + const char* string) +{ + char *new_buf; + char *new_pos; + + size_t data_length, final_length, string_length; + +#ifndef ICAL_NO_INTERNAL_DEBUG + icalerror_check_arg_rv( (buf!=0),"buf"); + icalerror_check_arg_rv( (*buf!=0),"*buf"); + icalerror_check_arg_rv( (pos!=0),"pos"); + icalerror_check_arg_rv( (*pos!=0),"*pos"); + icalerror_check_arg_rv( (buf_size!=0),"buf_size"); + icalerror_check_arg_rv( (*buf_size!=0),"*buf_size"); + icalerror_check_arg_rv( (string!=0),"string"); +#endif + + string_length = strlen(string); + data_length = (size_t)*pos - (size_t)*buf; + final_length = data_length + string_length; + + if ( final_length >= (size_t) *buf_size) { + + + *buf_size = (*buf_size) * 2 + final_length; + + new_buf = realloc(*buf,*buf_size); + + new_pos = (void*)((size_t)new_buf + data_length); + + *pos = new_pos; + *buf = new_buf; + } + + strcpy(*pos, string); + + *pos += string_length; +} + + +void +icalmemory_append_char(char** buf, char** pos, size_t* buf_size, + char ch) +{ + char *new_buf; + char *new_pos; + + size_t data_length, final_length; + +#ifndef ICAL_NO_INTERNAL_DEBUG + icalerror_check_arg_rv( (buf!=0),"buf"); + icalerror_check_arg_rv( (*buf!=0),"*buf"); + icalerror_check_arg_rv( (pos!=0),"pos"); + icalerror_check_arg_rv( (*pos!=0),"*pos"); + icalerror_check_arg_rv( (buf_size!=0),"buf_size"); + icalerror_check_arg_rv( (*buf_size!=0),"*buf_size"); +#endif + + data_length = (size_t)*pos - (size_t)*buf; + + final_length = data_length + 2; + + if ( final_length > (size_t) *buf_size ) { + + + *buf_size = (*buf_size) * 2 + final_length +1; + + new_buf = realloc(*buf,*buf_size); + + new_pos = (void*)((size_t)new_buf + data_length); + + *pos = new_pos; + *buf = new_buf; + } + + **pos = ch; + *pos += 1; + **pos = 0; +} diff --git a/libical/src/libical/icalmemory.h b/libical/src/libical/icalmemory.h new file mode 100644 index 0000000..f833c6c --- a/dev/null +++ b/libical/src/libical/icalmemory.h @@ -0,0 +1,85 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalmemory.h + CREATOR: eric 30 June 1999 + + + $Id$ + $Locker$ + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Initial Developer of the Original Code is Eric Busboom + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org +======================================================================*/ + +#ifndef ICALMEMORY_H +#define ICALMEMORY_H + +#include <sys/types.h> /* for size_t */ + +// Eugen C. <eug@thekompany.com> +#ifdef _WIN32 +#include <stddef.h> +#endif +// Eugen C. <eug@thekompany.com> + +/* Tmp buffers are managed by ical. References can be returned to the + caller, although the caller will not own the memory. */ + +void* icalmemory_tmp_buffer(size_t size); +char* icalmemory_tmp_copy(const char* str); + +/* Add an externally allocated buffer to the ring. */ +void icalmemory_add_tmp_buffer(void*); + + +/* Free all memory used in the ring */ +void icalmemory_free_ring(void); + +/* Non-tmp buffers must be freed. These are mostly wrappers around + * malloc, etc, but are used so the caller can change the memory + * allocators in a future version of the library */ + +void* icalmemory_new_buffer(size_t size); +void* icalmemory_resize_buffer(void* buf, size_t size); +void icalmemory_free_buffer(void* buf); + +/* icalmemory_append_string will copy the string 'string' to the + buffer 'buf' starting at position 'pos', reallocing 'buf' if it is + too small. 'buf_size' is the size of 'buf' and will be changed if + 'buf' is reallocated. 'pos' will point to the last byte of the new + string in 'buf', usually a '\0' */ + +/* THESE ROUTINES CAN NOT BE USED ON TMP BUFFERS. Only use them on + normally allocated memory, or on buffers created from + icalmemory_new_buffer, never with buffers created by + icalmemory_tmp_buffer. If icalmemory_append_string has to resize a + buffer on the ring, the ring will loose track of it an you will + have memory problems. */ + +void icalmemory_append_string(char** buf, char** pos, size_t* buf_size, + const char* string); + +/* icalmemory_append_char is similar, but is appends a character instead of a string */ +void icalmemory_append_char(char** buf, char** pos, size_t* buf_size, + char ch); + +/* A wrapper around strdup. Partly to trap calls to strdup, partly + because in -ansi, gcc on Red Hat claims that strudup is undeclared */ +char* icalmemory_strdup(const char *s); + +#endif /* !ICALMEMORY_H */ + + + diff --git a/libical/src/libical/icalmime.c b/libical/src/libical/icalmime.c new file mode 100644 index 0000000..7021746 --- a/dev/null +++ b/libical/src/libical/icalmime.c @@ -0,0 +1,388 @@ +/* -*- Mode: C -*-*/ +/*====================================================================== + FILE: icalmime.c + CREATOR: eric 26 July 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#include "icalmime.h" +#include "icalerror.h" +#include "icalmemory.h" +#include "sspm.h" +#include "stdlib.h" +#include <string.h> /* For strdup */ +#include <stdio.h> /* for snprintf*/ + +int snprintf(char *str, size_t n, char const *fmt, ...); + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +/* These *_part routines are called by the MIME parser via the + local_action_map */ + +struct text_part +{ + char* buf; + char* buf_pos; + size_t buf_size; +}; + +void* icalmime_text_new_part() +{ + +#define BUF_SIZE 2048 + + struct text_part* impl; + + if ( ( impl = (struct text_part*) + malloc(sizeof(struct text_part))) == 0) { + return 0; + } + + impl->buf = icalmemory_new_buffer(BUF_SIZE); + impl->buf_pos = impl->buf; + impl->buf_size = BUF_SIZE; + + return impl; +} +void icalmime_text_add_line(void *part, + struct sspm_header *header, + char* line, size_t size) +{ + struct text_part* impl = (struct text_part*) part; + + icalmemory_append_string(&(impl->buf),&(impl->buf_pos), + &(impl->buf_size),line); + +} + +void* icalmime_textcalendar_end_part(void* part) +{ + + struct text_part* impl = (struct text_part*) part; + icalcomponent *c = icalparser_parse_string(impl->buf); + + icalmemory_free_buffer(impl->buf); + free(impl); + + return c; + +} + +void* icalmime_text_end_part(void* part) +{ + struct text_part* impl = ( struct text_part*) part; + + icalmemory_add_tmp_buffer(impl->buf); + free(impl); + + return impl->buf; +} + +void icalmime_text_free_part(void *part) +{ + part = part; +} + + +/* Ignore Attachments for now */ + +void* icalmime_attachment_new_part() +{ + return 0; +} +void icalmime_attachment_add_line(void *part, struct sspm_header *header, + char* line, size_t size) +{ + part = part; + header = header; + line = line; + size = size; +} + +void* icalmime_attachment_end_part(void* part) +{ + return 0; +} + +void icalmime_attachment_free_part(void *part) +{ +} + + + + +struct sspm_action_map icalmime_local_action_map[] = +{ + {SSPM_TEXT_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_textcalendar_end_part,icalmime_text_free_part}, + {SSPM_TEXT_MAJOR_TYPE,SSPM_ANY_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part}, + {SSPM_TEXT_MAJOR_TYPE,SSPM_PLAIN_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part}, + {SSPM_APPLICATION_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, + {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, + {SSPM_AUDIO_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, + {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part}, + {SSPM_UNKNOWN_MAJOR_TYPE,SSPM_UNKNOWN_MINOR_TYPE,0,0,0,0} +}; + +#define NUM_PARTS 100 /* HACK. Hard Limit */ + + + +struct sspm_part* icalmime_make_part(icalcomponent* comp) +{ + comp = comp; + return 0; +} + +char* icalmime_as_mime_string(char* icalcomponent); + +icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size, + void *d), + void *data) +{ + struct sspm_part *parts; + int i, last_level=0; + icalcomponent *root=0, *parent=0, *comp=0, *last = 0; + + if ( (parts = (struct sspm_part *) + malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + memset(parts,0,sizeof(parts)); + + sspm_parse_mime(parts, + NUM_PARTS, /* Max parts */ + icalmime_local_action_map, /* Actions */ + get_string, + data, /* data for get_string*/ + 0 /* First header */); + + + + for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; i++){ + +#define TMPSZ 1024 + char mimetype[TMPSZ]; + char* major = sspm_major_type_string(parts[i].header.major); + char* minor = sspm_minor_type_string(parts[i].header.minor); + + if(parts[i].header.minor == SSPM_UNKNOWN_MINOR_TYPE ){ + assert(parts[i].header.minor_text !=0); + minor = parts[i].header.minor_text; + } + + sprintf(mimetype,"%s/%s",major,minor); + + comp = icalcomponent_new(ICAL_XLICMIMEPART_COMPONENT); + + if(comp == 0){ + /* HACK Handle Error */ + assert(0); + } + + if(parts[i].header.error!=SSPM_NO_ERROR){ + char *str; + char* temp[256]; + + if(parts[i].header.error==SSPM_UNEXPECTED_BOUNDARY_ERROR){ + str = "Got an unexpected boundary, possibly due to a MIME header for a MULTIPART part that is missing the Content-Type line"; + } + + if(parts[i].header.error==SSPM_WRONG_BOUNDARY_ERROR){ + str = "Got the wrong boundary for the opening of a MULTIPART part."; + } + + if(parts[i].header.error==SSPM_NO_BOUNDARY_ERROR){ + str = "Got a multipart header that did not specify a boundary"; + } + + if(parts[i].header.error==SSPM_NO_HEADER_ERROR){ + str = "Did not get a header for the part. Is there a blank\ +line between the header and the previous boundary\?"; + + } + + if(parts[i].header.error_text != 0){ + snprintf((char*)temp,256, + "%s: %s",str,parts[i].header.error_text); + } else { + strcpy((char*)temp,str); + } + + icalcomponent_add_property + (comp, + icalproperty_vanew_xlicerror( + (char*)temp, + icalparameter_new_xlicerrortype( + ICAL_XLICERRORTYPE_MIMEPARSEERROR), + 0)); + } + + if(parts[i].header.major != SSPM_NO_MAJOR_TYPE && + parts[i].header.major != SSPM_UNKNOWN_MAJOR_TYPE){ + + icalcomponent_add_property(comp, + icalproperty_new_xlicmimecontenttype((char*) + icalmemory_strdup(mimetype))); + + } + + if (parts[i].header.encoding != SSPM_NO_ENCODING){ + + icalcomponent_add_property(comp, + icalproperty_new_xlicmimeencoding( + sspm_encoding_string(parts[i].header.encoding))); + } + + if (parts[i].header.filename != 0){ + icalcomponent_add_property(comp, + icalproperty_new_xlicmimefilename(parts[i].header.filename)); + } + + if (parts[i].header.content_id != 0){ + icalcomponent_add_property(comp, + icalproperty_new_xlicmimecid(parts[i].header.content_id)); + } + + if (parts[i].header.charset != 0){ + icalcomponent_add_property(comp, + icalproperty_new_xlicmimecharset(parts[i].header.charset)); + } + + /* Add iCal components as children of the component */ + if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE && + parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE && + parts[i].data != 0){ + + icalcomponent_add_component(comp, + (icalcomponent*)parts[i].data); + parts[i].data = 0; + + } else if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE && + parts[i].header.minor != SSPM_CALENDAR_MINOR_TYPE && + parts[i].data != 0){ + + /* Add other text components as "DESCRIPTION" properties */ + + icalcomponent_add_property(comp, + icalproperty_new_description( + (char*)icalmemory_strdup((char*)parts[i].data))); + + parts[i].data = 0; + } + + + if(root!= 0 && parts[i].level == 0){ + /* We've already assigned the root, but there is another + part at the root level. This is probably a parse + error*/ + icalcomponent_free(comp); + continue; + } + + if(parts[i].level == last_level && last_level != 0){ + icalerror_assert(parent!=0,"No parent for adding component"); + + icalcomponent_add_component(parent,comp); + + } else if (parts[i].level == last_level && last_level == 0 && + root == 0) { + + root = comp; + parent = comp; + + } else if (parts[i].level > last_level){ + + parent = last; + icalcomponent_add_component(parent,comp); + + last_level = parts[i].level; + + } else if (parts[i].level < last_level){ + + parent = icalcomponent_get_parent(parent); + icalcomponent_add_component(parent,comp); + + last_level = parts[i].level; + } else { + assert(0); + } + + last = comp; + last_level = parts[i].level; + assert(parts[i].data == 0); + } + + sspm_free_parts(parts,NUM_PARTS); + free(parts); + + return root; +} + + + +int icalmime_test(char* (*get_string)(char *s, size_t size, void *d), + void *data) +{ + char *out; + struct sspm_part *parts; + int i; + + if ( (parts = (struct sspm_part *) + malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + memset(parts,0,sizeof(parts)); + + sspm_parse_mime(parts, + NUM_PARTS, /* Max parts */ + icalmime_local_action_map, /* Actions */ + get_string, + data, /* data for get_string*/ + 0 /* First header */); + + for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; + i++){ + if(parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE){ + parts[i].data = icalmemory_strdup( + icalcomponent_as_ical_string((icalcomponent*)parts[i].data)); + } + } + + sspm_write_mime(parts,NUM_PARTS,&out,"To: bob@bob.org"); + + printf("%s\n",out); + + return 0; + +} + + diff --git a/libical/src/libical/icalmime.h b/libical/src/libical/icalmime.h new file mode 100644 index 0000000..b222888 --- a/dev/null +++ b/libical/src/libical/icalmime.h @@ -0,0 +1,43 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalmime.h + CREATOR: eric 26 July 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + +======================================================================*/ + +#ifndef ICALMIME_H +#define ICALMIME_H + +#include "icalcomponent.h" +#include "icalparser.h" + +icalcomponent* icalmime_parse( char* (*line_gen_func)(char *s, size_t size, + void *d), + void *data); + +/* The inverse of icalmime_parse, not implemented yet. Use sspm.h directly. */ +char* icalmime_as_mime_string(char* component); + + + +#endif /* !ICALMIME_H */ + + + diff --git a/libical/src/libical/icalparameter.c b/libical/src/libical/icalparameter.c new file mode 100644 index 0000000..156ecdb --- a/dev/null +++ b/libical/src/libical/icalparameter.c @@ -0,0 +1,382 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalderivedparameters.{c,h} + CREATOR: eric 09 May 1999 + + $Id$ + $Locker$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalderivedparameters.{c,h} + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + ======================================================================*/ +/*#line 29 "icalparameter.c.in"*/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +#include "icalparameter.h" +#include "icalproperty.h" +#include "icalerror.h" +#include "icalmemory.h" +#include "icalparameterimpl.h" + +#include <stdlib.h> /* for malloc() */ +#include <errno.h> +#include <string.h> /* for memset() */ + +/* In icalderivedparameter */ +icalparameter* icalparameter_new_from_value_string(icalparameter_kind kind,const char* val); + + +struct icalparameter_impl* icalparameter_new_impl(icalparameter_kind kind) +{ + struct icalparameter_impl* v; + + if ( ( v = (struct icalparameter_impl*) + malloc(sizeof(struct icalparameter_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + strcpy(v->id,"para"); + + v->kind = kind; + v->size = 0; + v->string = 0; + v->x_name = 0; + v->parent = 0; + v->data = 0; + + return v; +} + +icalparameter* +icalparameter_new (icalparameter_kind kind) +{ + struct icalparameter_impl* v = icalparameter_new_impl(kind); + + return (icalparameter*) v; + +} + +void +icalparameter_free (icalparameter* parameter) +{ + struct icalparameter_impl * impl; + + impl = (struct icalparameter_impl*)parameter; + +/* HACK. This always triggers, even when parameter is non-zero + icalerror_check_arg_rv((parameter==0),"parameter");*/ + + +#ifdef ICAL_FREE_ON_LIST_IS_ERROR + icalerror_assert( (impl->parent ==0),"Tried to free a parameter that is still attached to a component. "); + +#else + if(impl->parent !=0){ + return; + } +#endif + + + if (impl->string != 0){ + free ((void*)impl->string); + } + + if (impl->x_name != 0){ + free ((void*)impl->x_name); + } + + memset(impl,0,sizeof(impl)); + + impl->parent = 0; + impl->id[0] = 'X'; + free(impl); +} + + + +icalparameter* +icalparameter_new_clone(icalparameter* param) +{ + struct icalparameter_impl *old; + struct icalparameter_impl *new; + + old = (struct icalparameter_impl *)param; + new = icalparameter_new_impl(old->kind); + + icalerror_check_arg_rz((param!=0),"param"); + + if (new == 0){ + return 0; + } + + memcpy(new,old,sizeof(struct icalparameter_impl)); + + if (old->string != 0){ + new->string = icalmemory_strdup(old->string); + if (new->string == 0){ + icalparameter_free(new); + return 0; + } + } + + if (old->x_name != 0){ + new->x_name = icalmemory_strdup(old->x_name); + if (new->x_name == 0){ + icalparameter_free(new); + return 0; + } + } + + return new; +} + +icalparameter* icalparameter_new_from_string(const char *str) +{ + char* eq; + char* cpy; + icalparameter_kind kind; + icalparameter *param; + + icalerror_check_arg_rz(str != 0,"str"); + + cpy = icalmemory_strdup(str); + + if (cpy == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + eq = strchr(cpy,'='); + + if(eq == 0){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + *eq = '\0'; + + eq++; + + kind = icalparameter_string_to_kind(cpy); + + if(kind == ICAL_NO_PARAMETER){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + param = icalparameter_new_from_value_string(kind,eq); + + if(kind == ICAL_X_PARAMETER){ + icalparameter_set_xname(param,cpy); + } + + free(cpy); + + return param; + +} + +char* +icalparameter_as_ical_string (icalparameter* parameter) +{ + struct icalparameter_impl* impl; + size_t buf_size = 1024; + char* buf; + char* buf_ptr; + char *out_buf; + const char *kind_string; + + icalerror_check_arg_rz( (parameter!=0), "parameter"); + + /* Create new buffer that we can append names, parameters and a + value to, and reallocate as needed. Later, this buffer will be + copied to a icalmemory_tmp_buffer, which is managed internally + by libical, so it can be given to the caller without fear of + the caller forgetting to free it */ + + buf = icalmemory_new_buffer(buf_size); + buf_ptr = buf; + impl = (struct icalparameter_impl*)parameter; + + if(impl->kind == ICAL_X_PARAMETER) { + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, + icalparameter_get_xname(impl)); + + } else { + + kind_string = icalparameter_kind_to_string(impl->kind); + + if (impl->kind == ICAL_NO_PARAMETER || + impl->kind == ICAL_ANY_PARAMETER || + kind_string == 0) + { + icalerror_set_errno(ICAL_BADARG_ERROR); + return 0; + } + + + /* Put the parameter name into the string */ + icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string); + + } + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "="); + + if(impl->string !=0){ + icalmemory_append_string(&buf, &buf_ptr, &buf_size, impl->string); + } else if (impl->data != 0){ + const char* str = icalparameter_enum_to_string(impl->data); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, str); + } else { + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + /* Now, copy the buffer to a tmp_buffer, which is safe to give to + the caller without worring about de-allocating it. */ + + out_buf = icalmemory_tmp_buffer(strlen(buf)); + strcpy(out_buf, buf); + + icalmemory_free_buffer(buf); + + return out_buf; + +} + + +int +icalparameter_is_valid (icalparameter* parameter); + + +icalparameter_kind +icalparameter_isa (icalparameter* parameter) +{ + if(parameter == 0){ + return ICAL_NO_PARAMETER; + } + + return ((struct icalparameter_impl *)parameter)->kind; +} + + +int +icalparameter_isa_parameter (void* parameter) +{ + struct icalparameter_impl *impl = (struct icalparameter_impl *)parameter; + + if (parameter == 0){ + return 0; + } + + if (strcmp(impl->id,"para") == 0) { + return 1; + } else { + return 0; + } +} + + +void +icalparameter_set_xname (icalparameter* param, const char* v) +{ + struct icalparameter_impl *impl = (struct icalparameter_impl*)param; + icalerror_check_arg_rv( (param!=0),"param"); + icalerror_check_arg_rv( (v!=0),"v"); + + if (impl->x_name != 0){ + free((void*)impl->x_name); + } + + impl->x_name = icalmemory_strdup(v); + + if (impl->x_name == 0){ + errno = ENOMEM; + } + +} + +const char* +icalparameter_get_xname (icalparameter* param) +{ + struct icalparameter_impl *impl = (struct icalparameter_impl*)param; + icalerror_check_arg_rz( (param!=0),"param"); + + return impl->x_name; +} + +void +icalparameter_set_xvalue (icalparameter* param, const char* v) +{ + struct icalparameter_impl *impl = (struct icalparameter_impl*)param; + + icalerror_check_arg_rv( (param!=0),"param"); + icalerror_check_arg_rv( (v!=0),"v"); + + if (impl->string != 0){ + free((void*)impl->string); + } + + impl->string = icalmemory_strdup(v); + + if (impl->string == 0){ + errno = ENOMEM; + } + +} + +const char* +icalparameter_get_xvalue (icalparameter* param) +{ + struct icalparameter_impl *impl = (struct icalparameter_impl*)param; + + icalerror_check_arg_rz( (param!=0),"param"); + + return impl->string; + +} + +void icalparameter_set_parent(icalparameter* param, + icalproperty* property) +{ + struct icalparameter_impl *impl = (struct icalparameter_impl*)param; + + icalerror_check_arg_rv( (param!=0),"param"); + + impl->parent = property; +} + +icalproperty* icalparameter_get_parent(icalparameter* param) +{ + struct icalparameter_impl *impl = (struct icalparameter_impl*)param; + + icalerror_check_arg_rz( (param!=0),"param"); + + return impl->parent; +} + + +/* Everything below this line is machine generated. Do not edit. */ +/* ALTREP */ diff --git a/libical/src/libical/icalparameter.h b/libical/src/libical/icalparameter.h new file mode 100644 index 0000000..3f3b59f --- a/dev/null +++ b/libical/src/libical/icalparameter.h @@ -0,0 +1,69 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalparam.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalparam.h + + ======================================================================*/ + +#ifndef ICALPARAM_H +#define ICALPARAM_H + +#include "icalderivedparameter.h" + +/* Declared in icalderivedparameter.h */ +/*typedef void icalparameter;*/ + +icalparameter* icalparameter_new(icalparameter_kind kind); +icalparameter* icalparameter_new_clone(icalparameter* p); + +/* Create from string of form "PARAMNAME=VALUE" */ +icalparameter* icalparameter_new_from_string(const char* value); + +/* Create from just the value, the part after the "=" */ +icalparameter* icalparameter_new_from_value_string(icalparameter_kind kind, const char* value); + +void icalparameter_free(icalparameter* parameter); + +char* icalparameter_as_ical_string(icalparameter* parameter); + +int icalparameter_is_valid(icalparameter* parameter); + +icalparameter_kind icalparameter_isa(icalparameter* parameter); + +int icalparameter_isa_parameter(void* param); + +/* Acess the name of an X parameer */ +void icalparameter_set_xname (icalparameter* param, const char* v); +const char* icalparameter_get_xname(icalparameter* param); +void icalparameter_set_xvalue (icalparameter* param, const char* v); +const char* icalparameter_get_xvalue(icalparameter* param); + +/* Convert enumerations */ + +const char* icalparameter_kind_to_string(icalparameter_kind kind); +icalparameter_kind icalparameter_string_to_kind(const char* string); + + + +#endif diff --git a/libical/src/libical/icalparameterimpl.h b/libical/src/libical/icalparameterimpl.h new file mode 100644 index 0000000..2d0fdd6 --- a/dev/null +++ b/libical/src/libical/icalparameterimpl.h @@ -0,0 +1,52 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalparameterimpl.h + CREATOR: eric 09 May 1999 + + $Id$ + $Locker$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalderivedparameters.{c,h} + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + ======================================================================*/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef ICALPARAMETER_IMPL +#define ICALPARAMETER_IMPL + +#include "icalparameter.h" +#include "icalproperty.h" + +struct icalparameter_impl +{ + icalparameter_kind kind; + char id[5]; + int size; + const char* string; + const char* x_name; + icalproperty* parent; + + int data; +}; + + +#endif /*ICALPARAMETER_IMPL*/ diff --git a/libical/src/libical/icalparser.c b/libical/src/libical/icalparser.c new file mode 100644 index 0000000..b5824d5 --- a/dev/null +++ b/libical/src/libical/icalparser.c @@ -0,0 +1,1111 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalparser.c + CREATOR: eric 04 August 1999 + + $Id$ + $Locker$ + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Initial Developer of the Original Code is Eric Busboom + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include "icalparser.h" +#include "pvl.h" +#include "icalmemory.h" +#include "icalerror.h" +#include "icalvalue.h" +#include "icalderivedparameter.h" +#include "icalparameter.h" +#include "icalproperty.h" +#include "icalcomponent.h" + +#include <string.h> /* For strncpy & size_t */ +#include <stdio.h> /* For FILE and fgets and sprintf */ +#include <stdlib.h> /* for free */ + +int snprintf(char *str, size_t n, char const *fmt, ...); + +extern icalvalue* icalparser_yy_value; +void set_parser_value_state(icalvalue_kind kind); +int ical_yyparse(void); + +char* icalparser_get_next_char(char c, char *str); +char* icalparser_get_next_parameter(char* line,char** end); +char* icalparser_get_next_value(char* line, char **end, icalvalue_kind kind); +char* icalparser_get_prop_name(char* line, char** end); +char* icalparser_get_param_name(char* line, char **end); + +#define TMP_BUF_SIZE 80 + +struct icalparser_impl +{ + int buffer_full; /* flag indicates that temp is smaller that + data being read into it*/ + int continuation_line; /* last line read was a continuation line */ + size_t tmp_buf_size; + char temp[TMP_BUF_SIZE]; + icalcomponent *root_component; + int version; + int level; + int lineno; + icalparser_state state; + pvl_list components; + + void *line_gen_data; + +}; + + +icalparser* icalparser_new(void) +{ + struct icalparser_impl* impl = 0; + if ( ( impl = (struct icalparser_impl*) + malloc(sizeof(struct icalparser_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + impl->root_component = 0; + impl->components = pvl_newlist(); + impl->level = 0; + impl->state = ICALPARSER_SUCCESS; + impl->tmp_buf_size = TMP_BUF_SIZE; + impl->buffer_full = 0; + impl->lineno = 0; + impl->continuation_line = 0; + memset(impl->temp,0, TMP_BUF_SIZE); + + return (icalparser*)impl; +} + + +void icalparser_free(icalparser* parser) +{ + struct icalparser_impl* impl = (struct icalparser_impl*)parser; + icalcomponent *c; + + if (impl->root_component != 0){ + icalcomponent_free(impl->root_component); + } + + while( (c=pvl_pop(impl->components)) != 0){ + icalcomponent_free(c); + } + + pvl_free(impl->components); + + free(impl); +} + +void icalparser_set_gen_data(icalparser* parser, void* data) +{ + struct icalparser_impl* impl = (struct icalparser_impl*)parser; + + impl->line_gen_data = data; +} + + +icalvalue* icalvalue_new_From_string_with_error(icalvalue_kind kind, + char* str, + icalproperty **error); + + + +char* icalparser_get_next_char(char c, char *str) +{ + int quote_mode = 0; + char* p; + + + for(p=str; *p!=0; p++){ + + if ( quote_mode == 0 && *p=='"' && *(p-1) != '\\' ){ + quote_mode =1; + continue; + } + + if ( quote_mode == 1 && *p=='"' && *(p-1) != '\\' ){ + quote_mode =0; + continue; + } + + if (quote_mode == 0 && *p== c && *(p-1) != '\\' ){ + return p; + } + + } + + return 0; +} + +/* make a new tmp buffer out of a substring */ +char* make_segment(char* start, char* end) +{ + char *buf; + size_t size = (size_t)end - (size_t)start; + + buf = icalmemory_tmp_buffer(size+1); + + + strncpy(buf,start,size); + *(buf+size) = 0; + + return buf; + +} + +const char* input_buffer; +const char* input_buffer_p; +//#define min(a,b) ((a) < (b) ? (a) : (b)) + +int icalparser_flex_input(char* buf, int max_size) +{ + int n = max_size; // = min(max_size,strlen(input_buffer_p)); + if ( n < ((int )strlen(input_buffer_p)) ) + n = strlen(input_buffer_p); + if (n > 0){ + memcpy(buf, input_buffer_p, n); + input_buffer_p += n; + return n; + } else { + return 0; + } +} + +void icalparser_clear_flex_input(void) +{ + input_buffer_p = input_buffer+strlen(input_buffer); +} + +/* Call the flex/bison parser to parse a complex value */ + +icalvalue* icalparser_parse_value(icalvalue_kind kind, + const char* str, icalproperty** error) +{ + int r; + input_buffer_p = input_buffer = str; + + set_parser_value_state(kind); + icalparser_yy_value = 0; + + r = ical_yyparse(); + + /* Error. Parse failed */ + if( icalparser_yy_value == 0 || r != 0){ + + if(icalparser_yy_value !=0){ + icalvalue_free(icalparser_yy_value); + icalparser_yy_value = 0; + } + + return 0; + } + + if (error != 0){ + *error = 0; + } + + return icalparser_yy_value; +} + +char* icalparser_get_prop_name(char* line, char** end) +{ + char* p; + char* v; + char *str; + + p = icalparser_get_next_char(';',line); + v = icalparser_get_next_char(':',line); + if (p== 0 && v == 0) { + return 0; + } + + /* There is no ';' or, it is after the ';' that marks the beginning of + the value */ + if (v!=0 && ( p == 0 || p > v)){ + str = make_segment(line,v); + *end = v+1; + } else { + str = make_segment(line,p); + *end = p+1; + } + + return str; +} + +char* icalparser_get_param_name(char* line, char **end) +{ + + char* next; + char *str; + + next = icalparser_get_next_char('=',line); + + if (next == 0) { + return 0; + } + + str = make_segment(line,next); + *end = next+1; + return str; + +} + +char* icalparser_get_next_paramvalue(char* line, char **end) +{ + + char* next; + char *str; + + next = icalparser_get_next_char(',',line); + + if (next == 0){ + next = (char*)(size_t)line+(size_t)strlen(line);\ + } + + if (next == line){ + return 0; + } else { + str = make_segment(line,next); + *end = next+1; + return str; + } + +} + +/* A property may have multiple values, if the values are seperated by + commas in the content line. This routine will look for the next + comma after line and will set the next place to start searching in + end. */ + +char* icalparser_get_next_value(char* line, char **end, icalvalue_kind kind) +{ + + char* next; + char *p; + char *str; + size_t length = strlen(line); + + p = line; + while(1){ + + next = icalparser_get_next_char(',',p); + + /* Unforunately, RFC2445 says that for the RECUR value, COMMA + can both seperate digits in a list, and it can seperate + multiple recurrence specifications. This is not a friendly + part of the spec. This weirdness tries to + distinguish the two uses. it is probably a HACK*/ + + if( kind == ICAL_RECUR_VALUE ) { + if ( next != 0 && + (*end+length) > next+5 && + strncmp(next,"FREQ",4) == 0 + ) { + /* The COMMA was followed by 'FREQ', is it a real seperator*/ + /* Fall through */ + } else if (next != 0){ + /* Not real, get the next COMMA */ + p = next+1; + next = 0; + continue; + } + } + + /* If the comma is preceeded by a '\', then it is a literal and + not a value seperator*/ + + if ( (next!=0 && *(next-1) == '\\') || + (next!=0 && *(next-3) == '\\') + ) + /*second clause for '/' is on prev line. HACK may be out of bounds */ + { + p = next+1; + } else { + break; + } + + } + + if (next == 0){ + next = (char*)(size_t)line+length; + *end = next; + } else { + *end = next+1; + } + + if (next == line){ + return 0; + } + + + str = make_segment(line,next); + return str; + +} + +char* icalparser_get_next_parameter(char* line,char** end) +{ + char *next; + char *v; + char *str; + + v = icalparser_get_next_char(':',line); + next = icalparser_get_next_char(';', line); + + /* There is no ';' or, it is after the ':' that marks the beginning of + the value */ + + if (next == 0 || next > v) { + next = icalparser_get_next_char(':', line); + } + + if (next != 0) { + str = make_segment(line,next); + *end = next+1; + return str; + } else { + *end = line; + return 0; + } +} + +/* Get a single property line, from the property name through the + final new line, and include any continuation lines */ + +char* icalparser_get_line(icalparser *parser, + char* (*line_gen_func)(char *s, size_t size, void *d)) +{ + char *line; + char *line_p; + struct icalparser_impl* impl = (struct icalparser_impl*)parser; + size_t buf_size = impl->tmp_buf_size; + + + line_p = line = icalmemory_new_buffer(buf_size); + line[0] = '\0'; + + /* Read lines by calling line_gen_func and putting the data into + impl->temp. If the line is a continuation line ( begins with a + space after a newline ) then append the data onto line and read + again. Otherwise, exit the loop. */ + + while(1) { + + /* The first part of the loop deals with the temp buffer, + which was read on he last pass through the loop. The + routine is split like this because it has to read lone line + ahead to determine if a line is a continuation line. */ + + + /* The tmp buffer is not clear, so transfer the data in it to the + output. This may be left over from a previous call */ + if (impl->temp[0] != '\0' ) { + + /* If the last position in the temp buffer is occupied, + mark the buffer as full. The means we will do another + read later, because the line is not finished */ + if (impl->temp[impl->tmp_buf_size-1] == 0 && + impl->temp[impl->tmp_buf_size-2] != '\n'&& + impl->temp[impl->tmp_buf_size-2] != 0 ){ + impl->buffer_full = 1; + } else { + impl->buffer_full = 0; + } + + /* Copy the temp to the output and clear the temp buffer. */ + if(impl->continuation_line==1){ + /* back up the pointer to erase the continuation characters */ + impl->continuation_line = 0; + line_p--; + + if ( *(line_p-1) == '\r'){ + line_p--; + } + + /* copy one space up to eliminate the leading space*/ + icalmemory_append_string(&line,&line_p,&buf_size, + impl->temp+1); + + } else { + icalmemory_append_string(&line,&line_p,&buf_size,impl->temp); + } + + impl->temp[0] = '\0' ; + } + + impl->temp[impl->tmp_buf_size-1] = 1; /* Mark end of buffer */ + + /****** Here is where the routine gets string data ******************/ + if ((*line_gen_func)(impl->temp,impl->tmp_buf_size,impl->line_gen_data) + ==0){/* Get more data */ + + /* If the first position is clear, it means we didn't get + any more data from the last call to line_ge_func*/ + if (impl->temp[0] == '\0'){ + + if(line[0] != '\0'){ + /* There is data in the output, so fall trhough and process it*/ + break; + } else { + /* No data in output; return and signal that there + is no more input*/ + free(line); + return 0; + } + } + } + + + /* If the output line ends in a '\n' and the temp buffer + begins with a ' ', then the buffer holds a continuation + line, so keep reading. */ + + if ( line_p > line+1 && *(line_p-1) == '\n' + && (impl->temp[0] == ' ' || impl->temp[0] == '\t') ) { + + impl->continuation_line = 1; + + } else if ( impl->buffer_full == 1 ) { + + /* The buffer was filled on the last read, so read again */ + + } else { + + /* Looks like the end of this content line, so break */ + break; + } + + + } + + /* Erase the final newline and/or carriage return*/ + if ( line_p > line+1 && *(line_p-1) == '\n') { + *(line_p-1) = '\0'; + if ( *(line_p-2) == '\r'){ + *(line_p-2) = '\0'; + } + + } else { + *(line_p) = '\0'; + } + + return line; + +} + +void insert_error(icalcomponent* comp, char* text, + char* message, icalparameter_xlicerrortype type) +{ + char temp[1024]; + + if (text == 0){ + snprintf(temp,1024,"%s:",message); + } else { + snprintf(temp,1024,"%s: %s",message,text); + } + + icalcomponent_add_property + (comp, + icalproperty_vanew_xlicerror( + temp, + icalparameter_new_xlicerrortype(type), + 0)); +} + +int line_is_blank(char* line){ + int i=0; + + for(i=0; *(line+i)!=0; i++){ + char c = *(line+i); + + if(c != ' ' && c != '\n' && c != '\t'){ + return 0; + } + } + + return 1; +} + +icalcomponent* icalparser_parse(icalparser *parser, + char* (*line_gen_func)(char *s, size_t size, + void* d)) +{ + + char* line; + icalcomponent *c=0; + icalcomponent *root=0; + struct icalparser_impl *impl = (struct icalparser_impl*)parser; + icalerrorstate es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR); + + icalerror_check_arg_rz((parser !=0),"parser"); + + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL); + + do{ + line = icalparser_get_line(parser, line_gen_func); + + if ((c = icalparser_add_line(parser,line)) != 0){ + + if(icalcomponent_get_parent(c) !=0){ + /* This is bad news... assert? */ + } + + assert(impl->root_component == 0); + assert(pvl_count(impl->components) ==0); + + if (root == 0){ + /* Just one component */ + root = c; + } else if(icalcomponent_isa(root) != ICAL_XROOT_COMPONENT) { + /*Got a second component, so move the two components under + an XROOT container */ + icalcomponent *tempc = icalcomponent_new(ICAL_XROOT_COMPONENT); + icalcomponent_add_component(tempc, root); + icalcomponent_add_component(tempc, c); + root = tempc; + } else if(icalcomponent_isa(root) == ICAL_XROOT_COMPONENT) { + /* Already have an XROOT container, so add the component + to it*/ + icalcomponent_add_component(root, c); + + } else { + /* Badness */ + assert(0); + } + + c = 0; + + } + if(line != 0){ + free(line); + } + } while ( line != 0); + + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es); + + return root; + +} + + +icalcomponent* icalparser_add_line(icalparser* parser, + char* line) +{ + char *p; + char *str; + char *end; + int vcount = 0; + icalproperty *prop; + icalproperty_kind prop_kind; + icalvalue *value; + icalvalue_kind value_kind = ICAL_NO_VALUE; + + + struct icalparser_impl *impl = (struct icalparser_impl*)parser; + icalerror_check_arg_rz((parser != 0),"parser"); + + + if (line == 0) + { + impl->state = ICALPARSER_ERROR; + return 0; + } + + if(line_is_blank(line) == 1){ + return 0; + } + + /* Begin by getting the property name at the start of the line. The + property name may end up being "BEGIN" or "END" in which case it + is not really a property, but the marker for the start or end of + a component */ + + end = 0; + str = icalparser_get_prop_name(line, &end); + + if (str == 0 || strlen(str) == 0 ){ + /* Could not get a property name */ + icalcomponent *tail = pvl_data(pvl_tail(impl->components)); + + if (tail){ + insert_error(tail,line, + "Got a data line, but could not find a property name or component begin tag", + ICAL_XLICERRORTYPE_COMPONENTPARSEERROR); + } + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } + + /********************************************************************** + * Handle begin and end of components + **********************************************************************/ + /* If the property name is BEGIN or END, we are actually + starting or ending a new component */ + + if(strcmp(str,"BEGIN") == 0){ + icalcomponent *c; + icalcomponent_kind comp_kind; + + impl->level++; + str = icalparser_get_next_value(end,&end, value_kind); + + + comp_kind = icalenum_string_to_component_kind(str); + + if (comp_kind == ICAL_NO_COMPONENT){ + c = icalcomponent_new(ICAL_XLICINVALID_COMPONENT); + insert_error(c,str,"Parse error in component name", + ICAL_XLICERRORTYPE_COMPONENTPARSEERROR); + } + + c = icalcomponent_new(comp_kind); + + if (c == 0){ + c = icalcomponent_new(ICAL_XLICINVALID_COMPONENT); + insert_error(c,str,"Parse error in component name", + ICAL_XLICERRORTYPE_COMPONENTPARSEERROR); + } + + pvl_push(impl->components,c); + + impl->state = ICALPARSER_BEGIN_COMP; + return 0; + + } else if (strcmp(str,"END") == 0 ) { + icalcomponent* tail; + + impl->level--; + str = icalparser_get_next_value(end,&end, value_kind); + + /* Pop last component off of list and add it to the second-to-last*/ + impl->root_component = pvl_pop(impl->components); + + tail = pvl_data(pvl_tail(impl->components)); + + if(tail != 0){ + icalcomponent_add_component(tail,impl->root_component); + } + + tail = 0; + + /* Return the component if we are back to the 0th level */ + if (impl->level == 0){ + icalcomponent *rtrn; + + if(pvl_count(impl->components) != 0){ + /* There are still components on the stack -- this means + that one of them did not have a proper "END" */ + pvl_push(impl->components,impl->root_component); + icalparser_clean(parser); /* may reset impl->root_component*/ + } + + assert(pvl_count(impl->components) == 0); + + impl->state = ICALPARSER_SUCCESS; + rtrn = impl->root_component; + impl->root_component = 0; + return rtrn; + + } else { + impl->state = ICALPARSER_END_COMP; + return 0; + } + } + + + /* There is no point in continuing if we have not seen a + component yet */ + + if(pvl_data(pvl_tail(impl->components)) == 0){ + impl->state = ICALPARSER_ERROR; + return 0; + } + + + /********************************************************************** + * Handle property names + **********************************************************************/ + + /* At this point, the property name really is a property name, + (Not a component name) so make a new property and add it to + the component */ + + + prop_kind = icalproperty_string_to_kind(str); + + prop = icalproperty_new(prop_kind); + + if (prop != 0){ + icalcomponent *tail = pvl_data(pvl_tail(impl->components)); + + if(prop_kind==ICAL_X_PROPERTY){ + icalproperty_set_x_name(prop,str); + } + + icalcomponent_add_property(tail, prop); + + /* Set the value kind for the default for this type of + property. This may be re-set by a VALUE parameter */ + value_kind = icalproperty_kind_to_value_kind(icalproperty_isa(prop)); + + } else { + icalcomponent* tail = pvl_data(pvl_tail(impl->components)); + + insert_error(tail,str,"Parse error in property name", + ICAL_XLICERRORTYPE_PROPERTYPARSEERROR); + + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } + + /********************************************************************** + * Handle parameter values + **********************************************************************/ + + /* Now, add any parameters to the last property */ + + p = 0; + while(1) { + + if (*(end-1) == ':'){ + /* if the last seperator was a ":" and the value is a + URL, icalparser_get_next_parameter will find the + ':' in the URL, so better break now. */ + break; + } + + str = icalparser_get_next_parameter(end,&end); + + if (str != 0){ + char* name; + char* pvalue; + + icalparameter *param = 0; + icalparameter_kind kind; + icalcomponent *tail = pvl_data(pvl_tail(impl->components)); + + name = icalparser_get_param_name(str,&pvalue); + + if (name == 0){ + /* 'tail' defined above */ + insert_error(tail, str, "Cant parse parameter name", + ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR); + tail = 0; + break; + } + + kind = icalparameter_string_to_kind(name); + + if(kind == ICAL_X_PARAMETER){ + param = icalparameter_new(ICAL_X_PARAMETER); + + if(param != 0){ + icalparameter_set_xname(param,name); + icalparameter_set_xvalue(param,pvalue); + } + + + } else if (kind != ICAL_NO_PARAMETER){ + param = icalparameter_new_from_value_string(kind,pvalue); + } else { + /* Error. Failed to parse the parameter*/ + /* 'tail' defined above */ + insert_error(tail, str, "Cant parse parameter name", + ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR); + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } + + if (param == 0){ + /* 'tail' defined above */ + insert_error(tail,str,"Cant parse parameter value", + ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR); + + tail = 0; + impl->state = ICALPARSER_ERROR; + continue; + } + + /* If it is a VALUE parameter, set the kind of value*/ + if (icalparameter_isa(param)==ICAL_VALUE_PARAMETER){ + + value_kind = (icalvalue_kind) + icalparameter_value_to_value_kind( + icalparameter_get_value(param) + ); + + if (value_kind == ICAL_NO_VALUE){ + + /* Ooops, could not parse the value of the + parameter ( it was not one of the defined + values ), so reset the value_kind */ + + insert_error( + tail, str, + "Got a VALUE parameter with an unknown type", + ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR); + icalparameter_free(param); + + value_kind = + icalproperty_kind_to_value_kind( + icalproperty_isa(prop)); + + icalparameter_free(param); + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } + } + + /* Everything is OK, so add the parameter */ + icalproperty_add_parameter(prop,param); + tail = 0; + + } else { /* if ( str != 0) */ + /* If we did not get a param string, go on to looking + for a value */ + break; + } /* if ( str != 0) */ + + } /* while(1) */ + + /********************************************************************** + * Handle values + **********************************************************************/ + + /* Look for values. If there are ',' characters in the values, + then there are multiple values, so clone the current + parameter and add one part of the value to each clone */ + + vcount=0; + while(1) { + str = icalparser_get_next_value(end,&end, value_kind); + + if (str != 0){ + + if (vcount > 0){ + /* Actually, only clone after the second value */ + icalproperty* clone = icalproperty_new_clone(prop); + icalcomponent* tail = pvl_data(pvl_tail(impl->components)); + + icalcomponent_add_property(tail, clone); + prop = clone; + tail = 0; + } + + value = icalvalue_new_from_string(value_kind, str); + + /* Don't add properties without value */ + if (value == 0){ + char temp[200]; /* HACK */ + + icalproperty_kind prop_kind = icalproperty_isa(prop); + icalcomponent* tail = pvl_data(pvl_tail(impl->components)); + + sprintf(temp,"Cant parse as %s value in %s property. Removing entire property", + icalvalue_kind_to_string(value_kind), + icalproperty_kind_to_string(prop_kind)); + + insert_error(tail, str, temp, + ICAL_XLICERRORTYPE_VALUEPARSEERROR); + + /* Remove the troublesome property */ + icalcomponent_remove_property(tail,prop); + icalproperty_free(prop); + prop = 0; + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + + } else { + vcount++; + icalproperty_set_value(prop, value); + } + + + } else { + if (vcount == 0){ + char temp[200]; /* HACK */ + + icalproperty_kind prop_kind = icalproperty_isa(prop); + icalcomponent *tail = pvl_data(pvl_tail(impl->components)); + + sprintf(temp,"No value for %s property. Removing entire property", + icalproperty_kind_to_string(prop_kind)); + + insert_error(tail, str, temp, + ICAL_XLICERRORTYPE_VALUEPARSEERROR); + + /* Remove the troublesome property */ + icalcomponent_remove_property(tail,prop); + icalproperty_free(prop); + prop = 0; + tail = 0; + impl->state = ICALPARSER_ERROR; + return 0; + } else { + + break; + } + } + } + + /**************************************************************** + * End of component parsing. + *****************************************************************/ + + if (pvl_data(pvl_tail(impl->components)) == 0 && + impl->level == 0){ + /* HACK. Does this clause ever get executed? */ + impl->state = ICALPARSER_SUCCESS; + assert(0); + return impl->root_component; + } else { + impl->state = ICALPARSER_IN_PROGRESS; + return 0; + } + +} + +icalparser_state icalparser_get_state(icalparser* parser) +{ + struct icalparser_impl* impl = (struct icalparser_impl*) parser; + return impl->state; + +} + +icalcomponent* icalparser_clean(icalparser* parser) +{ + struct icalparser_impl* impl = (struct icalparser_impl*) parser; + icalcomponent *tail; + + icalerror_check_arg_rz((parser != 0 ),"parser"); + + /* We won't get a clean exit if some components did not have an + "END" tag. Clear off any component that may be left in the list */ + + while((tail=pvl_data(pvl_tail(impl->components))) != 0){ + + insert_error(tail," ", + "Missing END tag for this component. Closing component at end of input.", + ICAL_XLICERRORTYPE_COMPONENTPARSEERROR); + + + impl->root_component = pvl_pop(impl->components); + tail=pvl_data(pvl_tail(impl->components)); + + if(tail != 0){ + if(icalcomponent_get_parent(impl->root_component)!=0){ + icalerror_warn("icalparser_clean is trying to attach a component for the second time"); + } else { + icalcomponent_add_component(tail,impl->root_component); + } + } + + } + + return impl->root_component; + +} + +struct slg_data { + const char* pos; + const char* str; +}; + +char* string_line_generator(char *out, size_t buf_size, void *d) +{ + char *n; + size_t size; + struct slg_data* data = (struct slg_data*)d; + + if(data->pos==0){ + data->pos=data->str; + } + + /* If the pointer is at the end of the string, we are done */ + if (*(data->pos)==0){ + return 0; + } + + n = strchr(data->pos,'\n'); + + if (n == 0){ + size = strlen(data->pos); + } else { + n++; /* include newline in output */ + size = (n-data->pos); + } + + if (size > buf_size-1){ + size = buf_size-1; + } + + + strncpy(out,data->pos,size); + + *(out+size) = '\0'; + + data->pos += size; + + return out; +} + +icalcomponent* icalparser_parse_string(const char* str) +{ + icalcomponent *c; + struct slg_data d; + icalparser *p; + + icalerrorstate es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR); + + d.pos = 0; + d.str = str; + + p = icalparser_new(); + icalparser_set_gen_data(p,&d); + + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL); + + c = icalparser_parse(p,string_line_generator); + + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es); + + icalparser_free(p); + + return c; + +} diff --git a/libical/src/libical/icalparser.h b/libical/src/libical/icalparser.h new file mode 100644 index 0000000..5e1c88f --- a/dev/null +++ b/libical/src/libical/icalparser.h @@ -0,0 +1,93 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalparser.h + CREATOR: eric 20 April 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalparser.h + +======================================================================*/ + + +#ifndef ICALPARSER_H +#define ICALPARSER_H + +#include "icalenums.h" +#include "icaltypes.h" +#include"icalcomponent.h" + +#include <stdio.h> /* For FILE* */ + +typedef void* icalparser; + + +/*********************************************************************** + * Line-oriented parsing. + * + * Create a new parser via icalparse_new_parser, then add ines one at + * a time with icalparse_add_line(). icalparser_add_line() will return + * non-zero when it has finished with a component. + ***********************************************************************/ + +typedef enum icalparser_state { + ICALPARSER_ERROR, + ICALPARSER_SUCCESS, + ICALPARSER_BEGIN_COMP, + ICALPARSER_END_COMP, + ICALPARSER_IN_PROGRESS +} icalparser_state; + +icalparser* icalparser_new(void); +icalcomponent* icalparser_add_line(icalparser* parser, char* str ); +icalcomponent* icalparser_clean(icalparser* parser); +icalparser_state icalparser_get_state(icalparser* parser); +void icalparser_free(icalparser* parser); + + +/*********************************************************************** + * Message oriented parsing. icalparser_parse takes a string that + * holds the text ( in RFC 2445 format ) and returns a pointer to an + * icalcomponent. The caller owns the memory. line_gen_func is a + * pointer to a function that returns one content line per invocation + **********************************************************************/ + +icalcomponent* icalparser_parse(icalparser *parser, + char* (*line_gen_func)(char *s, size_t size, void *d)); + +/* Set the data that icalparser_parse will give to the line_gen_func + as the parameter 'd'*/ +void icalparser_set_gen_data(icalparser* parser, void* data); + + +icalcomponent* icalparser_parse_string(const char* str); + + +/*********************************************************************** + * Parser support functions + ***********************************************************************/ + +/* Use the flex/bison parser to turn a string into a value type */ +icalvalue* icalparser_parse_value(icalvalue_kind kind, + const char* str, icalcomponent** errors); + +/* Given a line generator function, return a single iCal content line.*/ +char* icalparser_get_line(icalparser* parser, char* (*line_gen_func)(char *s, size_t size, void *d)); + +char* string_line_generator(char *out, size_t buf_size, void *d); + +#endif /* !ICALPARSE_H */ diff --git a/libical/src/libical/icalperiod.c b/libical/src/libical/icalperiod.c new file mode 100644 index 0000000..c74c157 --- a/dev/null +++ b/libical/src/libical/icalperiod.c @@ -0,0 +1,170 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalperiod.c + CREATOR: eric 02 June 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalperiod.h" + +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#ifdef ICAL_NO_LIBICAL +#define icalerror_set_errno(x) +#define icalerror_check_arg_rv(x,y) +#define icalerror_check_arg_re(x,y,z) +#else +#include "icalerror.h" +#include "icalmemory.h" +#endif + + + + +struct icalperiodtype icalperiodtype_from_string (const char* str) +{ + + struct icalperiodtype p, null_p; + char *s = icalmemory_strdup(str); + char *start, *end = s; + icalerrorstate es; + + /* Errors are normally generated in the following code, so save + the error state for resoration later */ + + icalerrorenum e = icalerrno; + + p.start = p.end = icaltime_null_time(); + p.duration = icaldurationtype_from_int(0); + + null_p = p; + + if(s == 0) goto error; + + start = s; + end = strchr(s, '/'); + + if(end == 0) goto error; + + *end = 0; + end++; + + p.start = icaltime_from_string(start); + + if (icaltime_is_null_time(p.start)) goto error; + + es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR); + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL); + + p.end = icaltime_from_string(end); + + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es); + + + if (icaltime_is_null_time(p.end)){ + + p.duration = icaldurationtype_from_string(end); + + if(icaldurationtype_as_int(p.duration) == 0) goto error; + } + + icalerrno = e; + + return p; + + error: + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return null_p; +} + + +const char* icalperiodtype_as_ical_string(struct icalperiodtype p) +{ + + const char* start; + const char* end; + + char *buf; + size_t buf_size = 40; + char* buf_ptr = 0; + + buf = (char*)icalmemory_new_buffer(buf_size); + buf_ptr = buf; + + + start = icaltime_as_ical_string(p.start); + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, start); + + if(!icaltime_is_null_time(p.end)){ + end = icaltime_as_ical_string(p.end); + } else { + end = icaldurationtype_as_ical_string(p.duration); + } + + icalmemory_append_char(&buf, &buf_ptr, &buf_size, '/'); + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, end); + + + return buf; +} + + + +struct icalperiodtype icalperiodtype_null_period() { + struct icalperiodtype p; + p.start = icaltime_null_time(); + p.end = icaltime_null_time(); + p.duration = icaldurationtype_null_duration(); + + return p; +} +int icalperiodtype_is_null_period(struct icalperiodtype p){ + + if(icaltime_is_null_time(p.start) && + icaltime_is_null_time(p.end) && + icaldurationtype_is_null_duration(p.duration)){ + return 1; + } else { + return 0; + } +} + +int icalperiodtype_is_valid_period(struct icalperiodtype p){ + if(icaltime_is_valid_time(p.start) && + (icaltime_is_valid_time(p.end) || icaltime_is_null_time(p.end)) ) + { + return 1; + } + + return 0; +} + diff --git a/libical/src/libical/icalperiod.h b/libical/src/libical/icalperiod.h new file mode 100644 index 0000000..64d5323 --- a/dev/null +++ b/libical/src/libical/icalperiod.h @@ -0,0 +1,55 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalperiod.h + CREATOR: eric 26 Jan 2001 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALPERIOD_H +#define ICALPERIOD_H + +#include "icaltime.h" +#include "icalduration.h" + +struct icalperiodtype +{ + struct icaltimetype start; + struct icaltimetype end; + struct icaldurationtype duration; +}; + +struct icalperiodtype icalperiodtype_from_string (const char* str); + +const char* icalperiodtype_as_ical_string(struct icalperiodtype p); +struct icalperiodtype icalperiodtype_null_period(); +int icalperiodtype_is_null_period(struct icalperiodtype p); +int icalperiodtype_is_valid_period(struct icalperiodtype p); + + + + +#endif /* !ICALTIME_H */ + + + diff --git a/libical/src/libical/icalproperty.c b/libical/src/libical/icalproperty.c new file mode 100644 index 0000000..7f2cfa5 --- a/dev/null +++ b/libical/src/libical/icalproperty.c @@ -0,0 +1,810 @@ +/* -*- Mode: C -*- */ + +/*====================================================================== + FILE: icalproperty.c + CREATOR: eric 28 April 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalproperty.c + +======================================================================*/ +/*#line 27 "icalproperty.c.in"*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalproperty.h" +#include "icalparameter.h" +#include "icalcomponent.h" +#include "pvl.h" +#include "icalenums.h" +#include "icalerror.h" +#include "icalmemory.h" +#include "icalparser.h" + +#include <string.h> /* For icalmemory_strdup, rindex */ +#include <assert.h> +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> /* for printf */ +#include <stdarg.h> /* for va_list, va_start, etc. */ + +int snprintf(char *str, size_t n, char const *fmt, ...); + +#define TMP_BUF_SIZE 1024 + +/* Private routines for icalproperty */ +void icalvalue_set_parent(icalvalue* value, + icalproperty* property); +icalproperty* icalvalue_get_parent(icalvalue* value); + +void icalparameter_set_parent(icalparameter* param, + icalproperty* property); +icalproperty* icalparameter_get_parent(icalparameter* value); + + +void icalproperty_set_x_name(icalproperty* prop, const char* name); + +struct icalproperty_impl +{ + char id[5]; + icalproperty_kind kind; + char* x_name; + pvl_list parameters; + pvl_elem parameter_iterator; + icalvalue* value; + icalcomponent *parent; +}; + +void icalproperty_add_parameters(struct icalproperty_impl *prop,va_list args) +{ + + void* vp; + + struct icalproperty_impl *impl = (struct icalproperty_impl*)prop; + + while((vp = va_arg(args, void*)) != 0) { + + if (icalvalue_isa_value(vp) != 0 ){ + } else if (icalparameter_isa_parameter(vp) != 0 ){ + + icalproperty_add_parameter((icalproperty*)impl, + (icalparameter*)vp); + } else { + assert(0); + } + + } + + +} + + +struct icalproperty_impl* +icalproperty_new_impl (icalproperty_kind kind) +{ + struct icalproperty_impl* prop; + + if ( ( prop = (struct icalproperty_impl*) + malloc(sizeof(struct icalproperty_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + strcpy(prop->id,"prop"); + + prop->kind = kind; + prop->parameters = pvl_newlist(); + prop->parameter_iterator = 0; + prop->value = 0; + prop->x_name = 0; + prop->parent = 0; + + return prop; +} + + +icalproperty* +icalproperty_new (icalproperty_kind kind) +{ + if(kind == ICAL_NO_PROPERTY){ + return 0; + } + + return (icalproperty*)icalproperty_new_impl(kind); +} + + +icalproperty* +icalproperty_new_clone(icalproperty* prop) +{ + struct icalproperty_impl *old = (struct icalproperty_impl*)prop; + struct icalproperty_impl *new = icalproperty_new_impl(old->kind); + pvl_elem p; + + icalerror_check_arg_rz((prop!=0),"Prop"); + icalerror_check_arg_rz((old!=0),"old"); + icalerror_check_arg_rz((new!=0),"new"); + + if (old->value !=0) { + new->value = icalvalue_new_clone(old->value); + } + + if (old->x_name != 0) { + + new->x_name = icalmemory_strdup(old->x_name); + + if (new->x_name == 0) { + icalproperty_free(new); + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + } + + for(p=pvl_head(old->parameters);p != 0; p = pvl_next(p)){ + icalparameter *param = icalparameter_new_clone(pvl_data(p)); + + if (param == 0){ + icalproperty_free(new); + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + pvl_push(new->parameters,param); + + } + + return new; + +} + +icalproperty* icalproperty_new_from_string(const char* str) +{ + + size_t buf_size = 1024; + char* buf = icalmemory_new_buffer(buf_size); + char* buf_ptr = buf; + icalproperty *prop; + icalcomponent *comp; + int errors = 0; + + icalerror_check_arg_rz( (str!=0),"str"); + + /* Is this a HACK or a crafty reuse of code? */ + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:VCALENDAR\n"); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, str); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "\n"); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:VCALENDAR\n"); + + comp = icalparser_parse_string(buf); + + if(comp == 0){ + icalerror_set_errno(ICAL_PARSE_ERROR); + return 0; + } + + errors = icalcomponent_count_errors(comp); + + prop = icalcomponent_get_first_property(comp,ICAL_ANY_PROPERTY); + + icalcomponent_remove_property(comp,prop); + + icalcomponent_free(comp); + free(buf); + + if(errors > 0){ + icalproperty_free(prop); + return 0; + } else { + return prop; + } + +} + +void +icalproperty_free (icalproperty* prop) +{ + struct icalproperty_impl *p; + + icalparameter* param; + + icalerror_check_arg_rv((prop!=0),"prop"); + + p = (struct icalproperty_impl*)prop; + +#ifdef ICAL_FREE_ON_LIST_IS_ERROR + icalerror_assert( (p->parent ==0),"Tried to free a property that is still attached to a component. "); + +#else + if(p->parent !=0){ + return; + } +#endif + + if (p->value != 0){ + icalvalue_set_parent(p->value,0); + icalvalue_free(p->value); + } + + while( (param = pvl_pop(p->parameters)) != 0){ + icalparameter_free(param); + } + + pvl_free(p->parameters); + + if (p->x_name != 0) { + free(p->x_name); + } + + p->kind = ICAL_NO_PROPERTY; + p->parameters = 0; + p->parameter_iterator = 0; + p->value = 0; + p->x_name = 0; + p->id[0] = 'X'; + + free(p); + +} + + +const char* +icalproperty_as_ical_string (icalproperty* prop) +{ + icalparameter *param; + + /* Create new buffer that we can append names, parameters and a + value to, and reallocate as needed. Later, this buffer will be + copied to a icalmemory_tmp_buffer, which is managed internally + by libical, so it can be given to the caller without fear of + the caller forgetting to free it */ + + const char* property_name = 0; + size_t buf_size = 1024; + char* buf = icalmemory_new_buffer(buf_size); + char* buf_ptr = buf; + icalvalue* value; + char *out_buf; + + char newline[] = "\n"; + + struct icalproperty_impl *impl = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rz( (prop!=0),"prop"); + + + /* Append property name */ + + if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){ + property_name = impl->x_name; + } else { + property_name = icalproperty_kind_to_string(impl->kind); + } + + if (property_name == 0 ) { + icalerror_warn("Got a property of an unknown kind."); + icalmemory_free_buffer(buf); + return 0; + + } + + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline); + + + + /* Determine what VALUE parameter to include. The VALUE parameters + are ignored in the normal parameter printing ( the block after + this one, so we need to do it here */ + { + const char* kind_string = 0; + + icalparameter *orig_val_param + = icalproperty_get_first_parameter(prop,ICAL_VALUE_PARAMETER); + + icalvalue *value = icalproperty_get_value(impl); + + icalvalue_kind orig_kind = ICAL_NO_VALUE; + + icalvalue_kind this_kind = ICAL_NO_VALUE; + + icalvalue_kind default_kind + = icalproperty_kind_to_value_kind(impl->kind); + + if(orig_val_param){ + orig_kind = (icalvalue_kind)icalparameter_get_value(orig_val_param); + } + + if(value != 0){ + this_kind = icalvalue_isa(value); + } + + + if(this_kind == default_kind && + orig_kind != ICAL_NO_VALUE){ + /* The kind is the default, so it does not need to be + included, but do it anyway, since it was explicit in + the property. But, use the default, not the one + specified in the property */ + + kind_string = icalvalue_kind_to_string(default_kind); + + } else if (this_kind != default_kind && this_kind != ICAL_NO_VALUE){ + /* Not the default, so it must be specified */ + kind_string = icalvalue_kind_to_string(this_kind); + } else { + /* Don'tinclude the VALUE parameter at all */ + } + + if(kind_string!=0){ + icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;"); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "VALUE="); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline); + } + + + } + + /* Append parameters */ + for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER); + param != 0; + param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)) { + + char* kind_string = icalparameter_as_ical_string(param); + icalparameter_kind kind = icalparameter_isa(param); + + if(kind==ICAL_VALUE_PARAMETER){ + continue; + } + + if (kind_string == 0 ) { + char temp[TMP_BUF_SIZE]; + snprintf(temp, TMP_BUF_SIZE,"Got a parameter of unknown kind in %s property",property_name); + icalerror_warn(temp); + continue; + } + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;"); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline); + + } + + /* Append value */ + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, " :"); + + value = icalproperty_get_value(prop); + + if (value != 0){ + const char *str = icalvalue_as_ical_string(value); + icalerror_assert((str !=0),"Could not get string representation of a value"); + icalmemory_append_string(&buf, &buf_ptr, &buf_size, str); + } else { + icalmemory_append_string(&buf, &buf_ptr, &buf_size,"ERROR: No Value"); + + } + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline); + + /* Now, copy the buffer to a tmp_buffer, which is safe to give to + the caller without worring about de-allocating it. */ + + + out_buf = icalmemory_tmp_buffer(strlen(buf)+1); + strcpy(out_buf, buf); + + icalmemory_free_buffer(buf); + + return out_buf; +} + + + +icalproperty_kind +icalproperty_isa (icalproperty* property) +{ + struct icalproperty_impl *p = (struct icalproperty_impl*)property; + + if(property != 0){ + return p->kind; + } + + return ICAL_NO_PROPERTY; +} + +int +icalproperty_isa_property (void* property) +{ + struct icalproperty_impl *impl = (struct icalproperty_impl*)property; + + icalerror_check_arg_rz( (property!=0), "property"); + + if (strcmp(impl->id,"prop") == 0) { + return 1; + } else { + return 0; + } +} + + +void +icalproperty_add_parameter (icalproperty* prop,icalparameter* parameter) +{ + struct icalproperty_impl *p = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalerror_check_arg_rv( (parameter!=0),"parameter"); + + pvl_push(p->parameters, parameter); + +} + +void +icalproperty_set_parameter (icalproperty* prop,icalparameter* parameter) +{ + icalparameter_kind kind; + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalerror_check_arg_rv( (parameter!=0),"parameter"); + + kind = icalparameter_isa(parameter); + + icalproperty_remove_parameter(prop,kind); + + icalproperty_add_parameter(prop,parameter); +} + +void icalproperty_set_parameter_from_string(icalproperty* prop, + const char* name, const char* value) +{ + + icalparameter_kind kind; + icalparameter *param; + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalerror_check_arg_rv( (name!=0),"name"); + icalerror_check_arg_rv( (value!=0),"value"); + + kind = icalparameter_string_to_kind(name); + + if(kind == ICAL_NO_PARAMETER){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return; + } + + param = icalparameter_new_from_value_string(kind,value); + + if (param == 0){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return; + } + + icalproperty_set_parameter(prop,param); + +} + +const char* icalproperty_get_parameter_as_string(icalproperty* prop, + const char* name) +{ + icalparameter_kind kind; + icalparameter *param; + char* str; + char* pv; + + icalerror_check_arg_rz( (prop!=0),"prop"); + icalerror_check_arg_rz( (name!=0),"name"); + + kind = icalparameter_string_to_kind(name); + + if(kind == ICAL_NO_PROPERTY){ + /* icalenum_string_to_parameter_kind will set icalerrno */ + return 0; + } + + param = icalproperty_get_first_parameter(prop,kind); + + if (param == 0){ + return 0; + } + + str = icalparameter_as_ical_string(param); + + pv = strchr(str,'='); + + if(pv == 0){ + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return 0; + } + + return pv+1; + +} + +void +icalproperty_remove_parameter (icalproperty* prop, icalparameter_kind kind) +{ + pvl_elem p; + struct icalproperty_impl *impl = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rv((prop!=0),"prop"); + + for(p=pvl_head(impl->parameters);p != 0; p = pvl_next(p)){ + icalparameter* param = (icalparameter *)pvl_data (p); + if (icalparameter_isa(param) == kind) { + pvl_remove (impl->parameters, p); + icalparameter_free (param); + break; + } + } +} + + +int +icalproperty_count_parameters (icalproperty* prop) +{ + struct icalproperty_impl *p = (struct icalproperty_impl*)prop; + + if(prop != 0){ + return pvl_count(p->parameters); + } + + icalerror_set_errno(ICAL_USAGE_ERROR); + return -1; +} + + +icalparameter* +icalproperty_get_first_parameter (icalproperty* prop, icalparameter_kind kind) +{ + struct icalproperty_impl *p = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rz( (prop!=0),"prop"); + + p->parameter_iterator = pvl_head(p->parameters); + + if (p->parameter_iterator == 0) { + return 0; + } + + for( p->parameter_iterator = pvl_head(p->parameters); + p->parameter_iterator !=0; + p->parameter_iterator = pvl_next(p->parameter_iterator)){ + + icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator); + + if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){ + return param; + } + } + + return 0; +} + + +icalparameter* +icalproperty_get_next_parameter (icalproperty* prop, icalparameter_kind kind) +{ + struct icalproperty_impl *p = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rz( (prop!=0),"prop"); + + if (p->parameter_iterator == 0) { + return 0; + } + + for( p->parameter_iterator = pvl_next(p->parameter_iterator); + p->parameter_iterator !=0; + p->parameter_iterator = pvl_next(p->parameter_iterator)){ + + icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator); + + if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){ + return param; + } + } + + return 0; + +} + +void +icalproperty_set_value (icalproperty* prop, icalvalue* value) +{ + struct icalproperty_impl *p = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rv((prop !=0),"prop"); + icalerror_check_arg_rv((value !=0),"value"); + + if (p->value != 0){ + icalvalue_set_parent(p->value,0); + icalvalue_free(p->value); + p->value = 0; + } + + p->value = value; + + icalvalue_set_parent(value,prop); +} + + +void icalproperty_set_value_from_string(icalproperty* prop,const char* str, + const char* type) +{ + icalvalue *oval,*nval; + icalvalue_kind kind = ICAL_NO_VALUE; + + icalerror_check_arg_rv( (prop!=0),"prop"); + icalerror_check_arg_rv( (str!=0),"str"); + icalerror_check_arg_rv( (type!=0),"type"); + + if(strcmp(type,"NO")==0){ + /* Get the type from the value the property already has, if it exists */ + oval = icalproperty_get_value(prop); + if(oval != 0){ + /* Use the existing value kind */ + kind = icalvalue_isa(oval); + } else { + /* Use the default kind for the property */ + kind = icalproperty_kind_to_value_kind(icalproperty_isa(prop)); + } + } else { + /* Use the given kind string */ + kind = icalvalue_string_to_kind(type); + } + + if(kind == ICAL_NO_VALUE){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return; + } + + nval = icalvalue_new_from_string(kind, str); + + if(nval == 0){ + /* icalvalue_new_from_string sets errno */ + assert(icalerrno != ICAL_NO_ERROR); + return; + } + + icalproperty_set_value(prop,nval); + + +} + +icalvalue* +icalproperty_get_value (icalproperty* prop) +{ + struct icalproperty_impl *p = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rz( (prop!=0),"prop"); + + return p->value; +} + +const char* icalproperty_get_value_as_string(icalproperty* prop) +{ + icalvalue *value; + + struct icalproperty_impl *impl = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rz( (prop!=0),"prop"); + + value = impl->value; + + return icalvalue_as_ical_string(value); +} + + +void icalproperty_set_x_name(icalproperty* prop, const char* name) +{ + struct icalproperty_impl *impl = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rv( (name!=0),"name"); + icalerror_check_arg_rv( (prop!=0),"prop"); + + if (impl->x_name != 0) { + free(impl->x_name); + } + + impl->x_name = icalmemory_strdup(name); + + if(impl->x_name == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + } + +} + +const char* icalproperty_get_x_name(icalproperty* prop){ + + struct icalproperty_impl *impl = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rz( (prop!=0),"prop"); + + return impl->x_name; +} + + +/* From Jonathan Yue <jonathan.yue@cp.net> */ +const char* icalproperty_get_name (icalproperty* prop) +{ + + const char* property_name = 0; + size_t buf_size = 256; + char* buf = icalmemory_new_buffer(buf_size); + char* buf_ptr = buf; + + struct icalproperty_impl *impl = (struct icalproperty_impl*)prop; + + icalerror_check_arg_rz( (prop!=0),"prop"); + + if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){ + property_name = impl->x_name; + } else { + property_name = icalproperty_kind_to_string(impl->kind); + } + + if (property_name == 0 ) { + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + + } else { + /* _append_string will automatically grow the buffer if + property_name is longer than the initial buffer size */ + icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name); + } + + /* Add the buffer to the temporary buffer ring -- the caller will + not have to free the memory. */ + icalmemory_add_tmp_buffer(buf); + + return buf; +} + + + + +void icalproperty_set_parent(icalproperty* property, + icalcomponent* component) +{ + struct icalproperty_impl *impl = (struct icalproperty_impl*)property; + + icalerror_check_arg_rv( (property!=0),"property"); + + impl->parent = component; +} + +icalcomponent* icalproperty_get_parent(icalproperty* property) +{ + struct icalproperty_impl *impl = (struct icalproperty_impl*)property; + + icalerror_check_arg_rz( (property!=0),"property"); + + return impl->parent; +} + + + + + + + +/* Everything below this line is machine generated. Do not edit. */ diff --git a/libical/src/libical/icalproperty.h b/libical/src/libical/icalproperty.h new file mode 100644 index 0000000..e39c6b5 --- a/dev/null +++ b/libical/src/libical/icalproperty.h @@ -0,0 +1,122 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalproperty.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalparam.h + + ======================================================================*/ + + +#ifndef ICALPROPERTY_H +#define ICALPROPERTY_H + +#include <time.h> + +#ifdef _WIN32 +#include <stdio.h> /* for printf */ +#include <stdarg.h> /* for va_list, va_start, etc. */ +#endif + +#include "icalderivedparameter.h" + +#include "icalvalue.h" +#include "icalrecur.h" + +/* Actually in icalderivedproperty.h: + typedef void icalproperty; */ + +#include "icalderivedproperty.h" /* To get icalproperty_kind enumerations */ + +// void icalproperty_add_parameters(struct icalproperty_impl *prop,va_list args); + +icalproperty* icalproperty_new(icalproperty_kind kind); + +icalproperty* icalproperty_new_clone(icalproperty * prop); + +icalproperty* icalproperty_new_from_string(const char* str); + +const char* icalproperty_as_ical_string(icalproperty* prop); + +void icalproperty_free(icalproperty* prop); + +icalproperty_kind icalproperty_isa(icalproperty* property); +int icalproperty_isa_property(void* property); + +void icalproperty_add_parameter(icalproperty* prop,icalparameter* parameter); +void icalproperty_set_parameter(icalproperty* prop,icalparameter* parameter); +void icalproperty_set_parameter_from_string(icalproperty* prop, + const char* name, const char* value); +const char* icalproperty_get_parameter_as_string(icalproperty* prop, + const char* name); + +void icalproperty_remove_parameter(icalproperty* prop, + icalparameter_kind kind); + +int icalproperty_count_parameters(icalproperty* prop); + +/* Iterate through the parameters */ +icalparameter* icalproperty_get_first_parameter(icalproperty* prop, + icalparameter_kind kind); +icalparameter* icalproperty_get_next_parameter(icalproperty* prop, + icalparameter_kind kind); +/* Access the value of the property */ +void icalproperty_set_value(icalproperty* prop, icalvalue* value); +void icalproperty_set_value_from_string(icalproperty* prop,const char* value, const char* kind); + +icalvalue* icalproperty_get_value(icalproperty* prop); +const char* icalproperty_get_value_as_string(icalproperty* prop); + +/* Deal with X properties */ + +void icalproperty_set_x_name(icalproperty* prop, const char* name); +const char* icalproperty_get_x_name(icalproperty* prop); + +/* Return the name of the property -- the type name converted to a + string, or the value of _get_x_name if the type is and X property */ +const char* icalproperty_get_name (icalproperty* prop); + +icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value); + +/* Convert kinds to string and get default value type */ + +icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind); +icalvalue_kind icalproperty_value_kind_to_kind(icalvalue_kind kind); +const char* icalproperty_kind_to_string(icalproperty_kind kind); +icalproperty_kind icalproperty_string_to_kind(const char* string); + +icalproperty_method icalproperty_string_to_method(const char* str); +const char* icalproperty_method_to_string(icalproperty_method method); + + +const char* icalproperty_enum_to_string(int e); +int icalproperty_string_to_enum(const char* str); + +const char* icalproperty_status_to_string(icalproperty_status); +icalproperty_status icalproperty_string_to_status(const char* string); + +int icalproperty_enum_belongs_to_property(icalproperty_kind kind, int e); + + + + +#endif /*ICALPROPERTY_H*/ diff --git a/libical/src/libical/icalrecur.c b/libical/src/libical/icalrecur.c new file mode 100644 index 0000000..203ce70 --- a/dev/null +++ b/libical/src/libical/icalrecur.c @@ -0,0 +1,2315 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalrecur.c + CREATOR: eric 16 May 2000 + + $Id$ + $Locker$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + How this code works: + + Processing starts when the caller generates a new recurrence + iterator via icalrecur_iterator_new(). This routine copies the + recurrence rule into the iterator and extracts things like start and + end dates. Then, it checks if the rule is legal, using some logic + from RFC2445 and some logic that probably should be in RFC2445. + + Then, icalrecur_iterator_new() re-writes some of the BY* + arrays. This involves ( via a call to setup_defaults() ) : + + 1) For BY rule parts with no data ( ie BYSECOND was not specified ) + copy the corresponding time part from DTSTART into the BY array. ( + So impl->by_ptrs[BY_SECOND] will then have one element if is + originally had none ) This only happens if the BY* rule part data + would expand the number of occurrences in the occurrence set. This + lets the code ignore DTSTART later on and still use it to get the + time parts that were not specified in any other way. + + 2) For the by rule part that are not the same interval as the + frequency -- for HOURLY anything but BYHOUR, for instance -- copy the + first data element from the rule part into the first occurrence. For + example, for "INTERVAL=MONTHLY and BYHOUR=10,30", initialize the + first time to be returned to have an hour of 10. + + Finally, for INTERVAL=YEARLY, the routine expands the rule to get + all of the days specified in the rule. The code will do this for + each new year, and this is the first expansion. This is a special + case for the yearly interval; no other frequency gets expanded this + way. The yearly interval is the most complex, so some special + processing is required. + + After creating a new iterator, the caller will make successive calls + to icalrecur_iterator_next() to get the next time specified by the + rule. The main part of this routine is a switch on the frequency of + the rule. Each different frequency is handled by a different + routine. + + For example, next_hour handles the case of INTERVAL=HOURLY, and it + is called by other routines to get the next hour. First, the routine + tries to get the next minute part of a time with a call to + next_minute(). If next_minute() returns 1, it has reached the end of + its data, usually the last element of the BYMINUTE array. Then, if + there is data in the BYHOUR array, the routine changes the hour to + the next one in the array. If INTERVAL=HOURLY, the routine advances + the hour by the interval. + + If the routine used the last hour in the BYHOUR array, and the + INTERVAL=HOURLY, then the routine calls increment_monthday() to set + the next month day. The increment_* routines may call higher routine + to increment the month or year also. + + The code for INTERVAL=DAILY is handled by next_day(). First, the + routine tries to get the next hour part of a time with a call to + next_hour. If next_hour() returns 1, it has reached the end of its + data, usually the last element of the BYHOUR array. This means that + next_day() should increment the time to the next day. If FREQUENCY==DAILY, + the routine increments the day by the interval; otherwise, it + increments the day by 1. + + Next_day() differs from next_hour because it does not use the BYDAY + array to select an appropriate day. Instead, it returns every day ( + incrementing by 1 if the frequency is not DAILY with INTERVAL!=1) + Any days that are not specified in an non-empty BYDAY array are + filtered out later. + + Generally, the flow of these routine is for a next_* call a next_* + routine of a lower interval ( next_day calls next_hour) and then to + possibly call an increment_* routine of an equal or higher + interval. ( next_day calls increment_monthday() ) + + When the call to the original next_* routine returns, + icalrecur_iterator_next() will check the returned data against other + BYrule parts to determine if is should be excluded by calling + check_contracting_rules. Generally, a contracting rule is any with a + larger time span than the interval. For instance, if + INTERVAL=DAILY, BYMONTH is a contracting rule part. + + Check_contracting_rules() uses icalrecur_check_rulepart() to do its + work. icalrecur_check_rulepart() uses expand_map[] to determine if a rule + is contracting, and if it is, and if the BY rule part has some data, + then the routine checks if the value of a component of the time is + part of the byrule part. For instance, for "INTERVAL=DAILY; + BYMONTH=6,10", icalrecur_check_rulepart() would check that the time value + given to it has a month of either 6 or 10. + + Finally, icalrecur_iterator_next() does a few other checks on the + time value, and if it passes, it returns the time. + + A note about the end_of_data flag. The flag indicates that the + routine is at the end of its data -- the last BY rule if the routine + is using by rules, or the last day of the week/month/year/etc if + not. + + This flag is usually set early in a next_* routine and returned in + the end. The way it is used allows the next_* routine to set the + last time back to the first element in a BYxx rule, and then signal + to the higer level routine to increment the next higher level. For + instance. WITH FREQ=MONTHLY;BYDAY=TU,FR, After next_weekday_by_month + runs though both TU and FR, it sets the week day back to TU and sets + end_of_data to 1x. This signals next_month to increment the month. + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalrecur.h" + +#ifdef ICAL_NO_LIBICAL +#define icalerror_set_errno(x) +#define icalerror_check_arg_rv(x,y) +#else +#include "icalerror.h" +#include "icalmemory.h" +#endif + +#include <stdlib.h> /* for malloc */ +#include <errno.h> /* for errno */ +#include <string.h> /* for strdup and strchr*/ +#include <assert.h> +#include <stddef.h> /* For offsetof() macro */ + +#include "pvl.h" + +#define TEMP_MAX 1024 + + +#define BYDAYIDX impl->by_indices[BY_DAY] +#define BYDAYPTR impl->by_ptrs[BY_DAY] + +#define BYMONIDX impl->by_indices[BY_MONTH] +#define BYMONPTR impl->by_ptrs[BY_MONTH] + +#define BYMDIDX impl->by_indices[BY_MONTH_DAY] +#define BYMDPTR impl->by_ptrs[BY_MONTH_DAY] + +#define BYWEEKIDX impl->by_indices[BY_WEEK_NO] +#define BYWEEKPTR impl->by_ptrs[BY_WEEK_NO] + +const char* icalrecur_freq_to_string(icalrecurrencetype_frequency kind); +icalrecurrencetype_frequency icalrecur_string_to_freq(const char* str); + +const char* icalrecur_weekday_to_string(icalrecurrencetype_weekday kind); +icalrecurrencetype_weekday icalrecur_string_to_weekday(const char* str); + + + +/*********************** Rule parsing routines ************************/ + +struct icalrecur_parser { + const char* rule; + char* copy; + char* this_clause; + char* next_clause; + + struct icalrecurrencetype rt; +}; + +const char* icalrecur_first_clause(struct icalrecur_parser *parser) +{ + char *idx; + parser->this_clause = parser->copy; + + idx = strchr(parser->this_clause,';'); + + if (idx == 0){ + parser->next_clause = 0; + return 0; + } + + *idx = 0; + idx++; + parser->next_clause = idx; + + return parser->this_clause; + +} + +const char* icalrecur_next_clause(struct icalrecur_parser *parser) +{ + char* idx; + + parser->this_clause = parser->next_clause; + + if(parser->this_clause == 0){ + return 0; + } + + idx = strchr(parser->this_clause,';'); + + if (idx == 0){ + parser->next_clause = 0; + } else { + + *idx = 0; + idx++; + parser->next_clause = idx; + } + + return parser->this_clause; + +} + +void icalrecur_clause_name_and_value(struct icalrecur_parser *parser, + char** name, char** value) +{ + char *idx; + + *name = parser->this_clause; + + idx = strchr(parser->this_clause,'='); + + if (idx == 0){ + *name = 0; + *value = 0; + return; + } + + *idx = 0; + idx++; + *value = idx; +} + +void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array, + int size, char* vals) +{ + char *t, *n; + int i=0; + int sign = 1; + short v; + + n = vals; + + while(n != 0){ + + if(i == size){ + return; + } + + t = n; + + n = strchr(t,','); + + if(n != 0){ + *n = 0; + n++; + } + + /* Get optional sign. HACK. sign is not allowed for all BYxxx + rule parts */ + if( *t == '-'){ + sign = -1; + t++; + } else if (*t == '+'){ + sign = 1; + t++; + } + + v = atoi(t) * sign ; + + + array[i++] = v; + array[i] = ICAL_RECURRENCE_ARRAY_MAX; + + } + +} + +void icalrecur_add_bydayrules(struct icalrecur_parser *parser, const char* vals) +{ + + char *t, *n; + int i=0; + int sign = 1; + int weekno = 0; + icalrecurrencetype_weekday wd; + short *array = parser->rt.by_day; + char* end; + char* vals_copy; + + vals_copy = icalmemory_strdup(vals); + + end = (char*)vals_copy+strlen(vals_copy); + n = vals_copy; + + while(n != 0){ + + + t = n; + + n = strchr(t,','); + + if(n != 0){ + *n = 0; + n++; + } + + /* Get optional sign. */ + if( *t == '-'){ + sign = -1; + t++; + } else if (*t == '+'){ + sign = 1; + t++; + } else { + sign = 1; + } + + weekno = 0; + /* Get Optional weekno */ + if( sscanf(t,"%d",&weekno) != 0){ + if (n != 0){ + int weeknolen = (n-t)-3; /* 3 -> one for \0, 2 for day name */ + /* could use abs(log10(weekno))+1, but that needs libm */ + t += weeknolen; + } else { + t = end -2; + } + } + + wd = icalrecur_string_to_weekday(t); + + array[i++] = sign* ((int)wd + 8*weekno); + array[i] = ICAL_RECURRENCE_ARRAY_MAX; + + } + + free(vals_copy); + +} + + +struct icalrecurrencetype icalrecurrencetype_from_string(const char* str) +{ + struct icalrecur_parser parser; + + memset(&parser,0,sizeof(parser)); + icalrecurrencetype_clear(&parser.rt); + + icalerror_check_arg_re(str!=0,"str",parser.rt); + + + /* Set up the parser struct */ + parser.rule = str; + parser.copy = icalmemory_strdup(parser.rule); + parser.this_clause = parser.copy; + + if(parser.copy == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return parser.rt; + } + + /* Loop through all of the clauses */ + for(icalrecur_first_clause(&parser); + parser.this_clause != 0; + icalrecur_next_clause(&parser)) + { + char *name, *value; + icalrecur_clause_name_and_value(&parser,&name,&value); + + if(name == 0){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + icalrecurrencetype_clear(&parser.rt); + return parser.rt; + } + + if (strcmp(name,"FREQ") == 0){ + parser.rt.freq = icalrecur_string_to_freq(value); + } else if (strcmp(name,"COUNT") == 0){ + parser.rt.count = atoi(value); + } else if (strcmp(name,"UNTIL") == 0){ + parser.rt.until = icaltime_from_string(value); + } else if (strcmp(name,"INTERVAL") == 0){ + parser.rt.interval = atoi(value); + } else if (strcmp(name,"WKST") == 0){ + parser.rt.week_start = icalrecur_string_to_weekday(value); + } else if (strcmp(name,"BYSECOND") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_second, + ICAL_BY_SECOND_SIZE,value); + } else if (strcmp(name,"BYMINUTE") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_minute, + ICAL_BY_MINUTE_SIZE,value); + } else if (strcmp(name,"BYHOUR") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_hour, + ICAL_BY_HOUR_SIZE,value); + } else if (strcmp(name,"BYDAY") == 0){ + icalrecur_add_bydayrules(&parser,value); + } else if (strcmp(name,"BYMONTHDAY") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_month_day, + ICAL_BY_MONTHDAY_SIZE,value); + } else if (strcmp(name,"BYYEARDAY") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_year_day, + ICAL_BY_YEARDAY_SIZE,value); + } else if (strcmp(name,"BYWEEKNO") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_week_no, + ICAL_BY_WEEKNO_SIZE,value); + } else if (strcmp(name,"BYMONTH") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_month, + ICAL_BY_MONTH_SIZE,value); + } else if (strcmp(name,"BYSETPOS") == 0){ + icalrecur_add_byrules(&parser,parser.rt.by_set_pos, + ICAL_BY_SETPOS_SIZE,value); + } else { + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + icalrecurrencetype_clear(&parser.rt); + return parser.rt; + } + + } + + free(parser.copy); + + return parser.rt; + +} + +#ifndef ICAL_NO_LIBICAL + +struct { char* str;size_t offset; short limit; } recurmap[] = +{ + {";BYSECOND=",offsetof(struct icalrecurrencetype,by_second),60}, + {";BYMINUTE=",offsetof(struct icalrecurrencetype,by_minute),60}, + {";BYHOUR=",offsetof(struct icalrecurrencetype,by_hour),24}, + {";BYDAY=",offsetof(struct icalrecurrencetype,by_day),7}, + {";BYMONTHDAY=",offsetof(struct icalrecurrencetype,by_month_day),31}, + {";BYYEARDAY=",offsetof(struct icalrecurrencetype,by_year_day),366}, + {";BYWEEKNO=",offsetof(struct icalrecurrencetype,by_week_no),52}, + {";BYMONTH=",offsetof(struct icalrecurrencetype,by_month),12}, + {";BYSETPOS=",offsetof(struct icalrecurrencetype,by_set_pos),366}, + {0,0,0}, +}; + +/* A private routine in icalvalue.c */ +void print_datetime_to_string(char* str, struct icaltimetype *data); + +char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur) +{ + char* str; + char *str_p; + size_t buf_sz = 200; + char temp[20]; + int i,j; + + if(recur->freq == ICAL_NO_RECURRENCE){ + return 0; + } + + str = (char*)icalmemory_tmp_buffer(buf_sz); + str_p = str; + + icalmemory_append_string(&str,&str_p,&buf_sz,"FREQ="); + icalmemory_append_string(&str,&str_p,&buf_sz, + icalrecur_freq_to_string(recur->freq)); + + if(recur->until.year != 0){ + + temp[0] = 0; + print_datetime_to_string(temp,&(recur->until)); + + icalmemory_append_string(&str,&str_p,&buf_sz,";UNTIL="); + icalmemory_append_string(&str,&str_p,&buf_sz, temp); + } + + if(recur->count != 0){ + sprintf(temp,"%d",recur->count); + icalmemory_append_string(&str,&str_p,&buf_sz,";COUNT="); + icalmemory_append_string(&str,&str_p,&buf_sz, temp); + } + + if(recur->interval != 0){ + sprintf(temp,"%d",recur->interval); + icalmemory_append_string(&str,&str_p,&buf_sz,";INTERVAL="); + icalmemory_append_string(&str,&str_p,&buf_sz, temp); + } + + for(j =0; recurmap[j].str != 0; j++){ + short* array = (short*)(recurmap[j].offset+ (size_t)recur); + short limit = recurmap[j].limit; + + /* Skip unused arrays */ + if( array[0] != ICAL_RECURRENCE_ARRAY_MAX ) { + + icalmemory_append_string(&str,&str_p,&buf_sz,recurmap[j].str); + + for(i=0; + i< limit && array[i] != ICAL_RECURRENCE_ARRAY_MAX; + i++){ + if (j == 3) { /* BYDAY */ + short dow = icalrecurrencetype_day_day_of_week(array[i]); + const char *daystr = icalrecur_weekday_to_string(dow); + short pos; + + pos = icalrecurrencetype_day_position(array[i]); + + if (pos == 0) + icalmemory_append_string(&str,&str_p,&buf_sz,daystr); + else { + sprintf(temp,"%d%s",pos,daystr); + icalmemory_append_string(&str,&str_p,&buf_sz,temp); + } + + } else { + sprintf(temp,"%d",array[i]); + icalmemory_append_string(&str,&str_p,&buf_sz, temp); + } + + if( (i+1)<limit &&array[i+1] + != ICAL_RECURRENCE_ARRAY_MAX){ + icalmemory_append_char(&str,&str_p,&buf_sz,','); + } + } + } + } + + return str; +} +#endif + + + +/************************* occurrence iteration routiens ******************/ + +enum byrule { + NO_CONTRACTION = -1, + BY_SECOND = 0, + BY_MINUTE = 1, + BY_HOUR = 2, + BY_DAY = 3, + BY_MONTH_DAY = 4, + BY_YEAR_DAY = 5, + BY_WEEK_NO = 6, + BY_MONTH = 7, + BY_SET_POS +}; + + + +struct icalrecur_iterator_impl { + + struct icaltimetype dtstart; /* Hack. Make into time_t */ + struct icaltimetype last; /* last time return from _iterator_next*/ + int occurrence_no; /* number of step made on t iterator */ + struct icalrecurrencetype rule; + + short days[366]; + short days_index; + + enum byrule byrule; + short by_indices[9]; + short orig_data[9]; /* 1 if there was data in the byrule */ + + + short *by_ptrs[9]; /* Pointers into the by_* array elements of the rule */ + +}; + +int icalrecur_iterator_sizeof_byarray(short* byarray) +{ + int array_itr; + + for(array_itr = 0; + byarray[array_itr] != ICAL_RECURRENCE_ARRAY_MAX; + array_itr++){ + } + + return array_itr; +} + +enum expand_table { + UNKNOWN = 0, + CONTRACT = 1, + EXPAND =2, + ILLEGAL=3 +}; + +/* The split map indicates, for a particular interval, wether a BY_* + rule part expands the number of instances in the occcurrence set or + contracts it. 1=> contract, 2=>expand, and 3 means the pairing is + not allowed. */ +struct expand_split_map_struct +{ + icalrecurrencetype_frequency frequency; + + /* Elements of the 'map' array correspond to the BYxxx rules: + Second,Minute,Hour,Day,Month Day,Year Day,Week No,Month*/ + + short map[8]; +}; + +struct expand_split_map_struct expand_map[] = +{ + {ICAL_SECONDLY_RECURRENCE,{1,1,1,1,1,1,1,1}}, + {ICAL_MINUTELY_RECURRENCE,{2,1,1,1,1,1,1,1}}, + {ICAL_HOURLY_RECURRENCE, {2,2,1,1,1,1,1,1}}, + {ICAL_DAILY_RECURRENCE, {2,2,2,1,1,1,1,1}}, + {ICAL_WEEKLY_RECURRENCE, {2,2,2,2,3,3,1,1}}, + {ICAL_MONTHLY_RECURRENCE, {2,2,2,2,2,3,3,1}}, + {ICAL_YEARLY_RECURRENCE, {2,2,2,2,2,2,2,2}}, + {ICAL_NO_RECURRENCE, {0,0,0,0,0,0,0,0}} + +}; + + + +/* Check that the rule has only the two given interday byrule parts. */ +int icalrecur_two_byrule(struct icalrecur_iterator_impl* impl, + enum byrule one,enum byrule two) +{ + short test_array[9]; + enum byrule itr; + int passes = 0; + + memset(test_array,0,9); + + test_array[one] = 1; + test_array[two] = 1; + + for(itr = BY_DAY; itr != BY_SET_POS; itr++){ + + if( (test_array[itr] == 0 && + impl->by_ptrs[itr][0] != ICAL_RECURRENCE_ARRAY_MAX + ) || + (test_array[itr] == 1 && + impl->by_ptrs[itr][0] == ICAL_RECURRENCE_ARRAY_MAX + ) + ) { + /* test failed */ + passes = 0; + } + } + + return passes; + +} + +/* Check that the rule has only the one given interdat byrule parts. */ +int icalrecur_one_byrule(struct icalrecur_iterator_impl* impl,enum byrule one) +{ + int passes = 1; + enum byrule itr; + + for(itr = BY_DAY; itr != BY_SET_POS; itr++){ + + if ((itr==one && impl->by_ptrs[itr][0] == ICAL_RECURRENCE_ARRAY_MAX) || + (itr!=one && impl->by_ptrs[itr][0] != ICAL_RECURRENCE_ARRAY_MAX)) { + passes = 0; + } + } + + return passes; +} + +int count_byrules(struct icalrecur_iterator_impl* impl) +{ + int count = 0; + enum byrule itr; + + for(itr = BY_DAY; itr <= BY_SET_POS; itr++){ + if(impl->by_ptrs[itr][0] != ICAL_RECURRENCE_ARRAY_MAX){ + count++; + } + } + + return count; +} + + +void setup_defaults(struct icalrecur_iterator_impl* impl, + enum byrule byrule, icalrecurrencetype_frequency req, + short deftime, int *timepart) +{ + + icalrecurrencetype_frequency freq; + freq = impl->rule.freq; + + /* Re-write the BY rule arrays with data from the DTSTART time so + we don't have to explicitly deal with DTSTART */ + + if(impl->by_ptrs[byrule][0] == ICAL_RECURRENCE_ARRAY_MAX && + expand_map[freq].map[byrule] != CONTRACT){ + impl->by_ptrs[byrule][0] = deftime; + } + + /* Initialize the first occurence */ + if( freq != req && expand_map[freq].map[byrule] != CONTRACT){ + *timepart = impl->by_ptrs[byrule][0]; + } + + +} + +int has_by_data(struct icalrecur_iterator_impl* impl, enum byrule byrule){ + + return (impl->orig_data[byrule] == 1); +} + + +int expand_year_days(struct icalrecur_iterator_impl* impl,short year); + + +icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, + struct icaltimetype dtstart) +{ + struct icalrecur_iterator_impl* impl; + icalrecurrencetype_frequency freq; + + short days_in_month; + + if ( ( impl = (struct icalrecur_iterator_impl *) + malloc(sizeof(struct icalrecur_iterator_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + memset(impl,0,sizeof(struct icalrecur_iterator_impl)); + + impl->rule = rule; + impl->last = dtstart; + impl->dtstart = dtstart; + impl->days_index =0; + impl->occurrence_no = 0; + freq = impl->rule.freq; + + /* Set up convienience pointers to make the code simpler. Allows + us to iterate through all of the BY* arrays in the rule. */ + + impl->by_ptrs[BY_MONTH]=impl->rule.by_month; + impl->by_ptrs[BY_WEEK_NO]=impl->rule.by_week_no; + impl->by_ptrs[BY_YEAR_DAY]=impl->rule.by_year_day; + impl->by_ptrs[BY_MONTH_DAY]=impl->rule.by_month_day; + impl->by_ptrs[BY_DAY]=impl->rule.by_day; + impl->by_ptrs[BY_HOUR]=impl->rule.by_hour; + impl->by_ptrs[BY_MINUTE]=impl->rule.by_minute; + impl->by_ptrs[BY_SECOND]=impl->rule.by_second; + impl->by_ptrs[BY_SET_POS]=impl->rule.by_set_pos; + + memset(impl->orig_data,0,9); + + /* Note which by rules had data in them when the iterator was + created. We can't use the actuall by_x arrays, because the + empty ones will be given default values later in this + routine. The orig_data array will be used later in has_by_data */ + + impl->orig_data[BY_MONTH] + = (impl->rule.by_month[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_WEEK_NO] + =(impl->rule.by_week_no[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_YEAR_DAY] + =(impl->rule.by_year_day[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_MONTH_DAY] + =(impl->rule.by_month_day[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_DAY] + = (impl->rule.by_day[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_HOUR] + = (impl->rule.by_hour[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_MINUTE] + = (impl->rule.by_minute[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_SECOND] + = (impl->rule.by_second[0]!=ICAL_RECURRENCE_ARRAY_MAX); + impl->orig_data[BY_SET_POS] + = (impl->rule.by_set_pos[0]!=ICAL_RECURRENCE_ARRAY_MAX); + + + /* Check if the recurrence rule is legal */ + + /* If the BYYEARDAY appears, no other date rule part may appear. */ + + if(icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_MONTH) || + icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_WEEK_NO) || + icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_MONTH_DAY) || + icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_DAY) ){ + + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + + return 0; + } + + /* BYWEEKNO and BYMONTH rule parts may not both appear.*/ + + if(icalrecur_two_byrule(impl,BY_WEEK_NO,BY_MONTH)){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + /* BYWEEKNO and BYMONTHDAY rule parts may not both appear.*/ + + if(icalrecur_two_byrule(impl,BY_WEEK_NO,BY_MONTH_DAY)){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + + /*For MONTHLY recurrences (FREQ=MONTHLY) neither BYYEARDAY nor + BYWEEKNO may appear. */ + + if(freq == ICAL_MONTHLY_RECURRENCE && + icalrecur_one_byrule(impl,BY_WEEK_NO)){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + + /*For WEEKLY recurrences (FREQ=WEEKLY) neither BYMONTHDAY nor + BYYEARDAY may appear. */ + + if(freq == ICAL_WEEKLY_RECURRENCE && + icalrecur_one_byrule(impl,BY_MONTH_DAY )) { + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + /* BYYEARDAY may only appear in YEARLY rules */ + if(freq != ICAL_YEARLY_RECURRENCE && + icalrecur_one_byrule(impl,BY_YEAR_DAY )) { + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + /* Rewrite some of the rules and set up defaults to make later + processing easier. Primarily, t involves copying an element + from the start time into the coresponding BY_* array when the + BY_* array is empty */ + + + setup_defaults(impl,BY_SECOND,ICAL_SECONDLY_RECURRENCE,impl->dtstart.second, + &(impl->last.second)); + + setup_defaults(impl,BY_MINUTE,ICAL_MINUTELY_RECURRENCE,impl->dtstart.minute, + &(impl->last.minute)); + + setup_defaults(impl,BY_HOUR,ICAL_HOURLY_RECURRENCE,impl->dtstart.hour, + &(impl->last.hour)); + + setup_defaults(impl,BY_MONTH_DAY,ICAL_DAILY_RECURRENCE,impl->dtstart.day, + &(impl->last.day)); + + setup_defaults(impl,BY_MONTH,ICAL_MONTHLY_RECURRENCE,impl->dtstart.month, + &(impl->last.month)); + + + if(impl->rule.freq == ICAL_WEEKLY_RECURRENCE ){ + + if(impl->by_ptrs[BY_DAY][0] == ICAL_RECURRENCE_ARRAY_MAX){ + + /* Weekly recurrences with no BY_DAY data should occur on the + same day of the week as the start time . */ + impl->by_ptrs[BY_DAY][0] = icaltime_day_of_week(impl->dtstart); + + } else { + /* If there is BY_DAY data, then we need to move the initial + time to the start of the BY_DAY data. That is if the + start time is on a Wednesday, and the rule has + BYDAY=MO,WE,FR, move the initial time back to + monday. Otherwise, jumping to the next week ( jumping 7 + days ahead ) will skip over some occurrences in the + second week. */ + + /* This is probably a HACK. There should be some more + general way to solve this problem */ + + short dow = impl->by_ptrs[BY_DAY][0]-icaltime_day_of_week(impl->last); + + if(dow < 0) { + /* initial time is after first day of BY_DAY data */ + + impl->last.day += dow; + impl->last = icaltime_normalize(impl->last); + } + } + + + } + + /* For YEARLY rule, begin by setting up the year days array */ + + if(impl->rule.freq == ICAL_YEARLY_RECURRENCE){ + expand_year_days(impl,impl->last.year); + } + + + /* If this is a monthly interval with by day data, then we need to + set the last value to the appropriate day of the month */ + + if(impl->rule.freq == ICAL_MONTHLY_RECURRENCE && + has_by_data(impl,BY_DAY)) { + + short dow = icalrecurrencetype_day_day_of_week( + impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]); + short pos = icalrecurrencetype_day_position( + impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]); + + short poscount = 0; + days_in_month = + icaltime_days_in_month(impl->last.month, impl->last.year); + + if(pos >= 0){ + /* Count up from the first day pf the month to find the + pos'th weekday of dow ( like the second monday. ) */ + + for(impl->last.day = 1; + impl->last.day <= days_in_month; + impl->last.day++){ + + if(icaltime_day_of_week(impl->last) == dow){ + if(++poscount == pos || pos == 0){ + break; + } + } + } + } else { + /* Count down from the last day pf the month to find the + pos'th weekday of dow ( like the second to last monday. ) */ + pos = -pos; + for(impl->last.day = days_in_month; + impl->last.day != 0; + impl->last.day--){ + + if(icaltime_day_of_week(impl->last) == dow){ + if(++poscount == pos ){ + break; + } + } + } + } + + + if(impl->last.day > days_in_month || impl->last.day == 0){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + } + + + + return impl; +} + + +void icalrecur_iterator_free(icalrecur_iterator* i) +{ + + struct icalrecur_iterator_impl* impl = + (struct icalrecur_iterator_impl*)i; + + icalerror_check_arg_rv((impl!=0),"impl"); + + free(impl); + +} + + +void increment_year(struct icalrecur_iterator_impl* impl, int inc) +{ + impl->last.year+=inc; +} + +/* Increment month is different that the other incement_* routines -- + it figures out the interval for itself, and uses BYMONTH data if + available. */ +void increment_month(struct icalrecur_iterator_impl* impl) +{ + int years; + + if(has_by_data(impl,BY_MONTH) ){ + /* Ignore the frequency and use the byrule data */ + + impl->by_indices[BY_MONTH]++; + + if (impl->by_ptrs[BY_MONTH][impl->by_indices[BY_MONTH]] + ==ICAL_RECURRENCE_ARRAY_MAX){ + impl->by_indices[BY_MONTH] = 0; + + increment_year(impl,1); + + } + + impl->last.month = + impl->by_ptrs[BY_MONTH][impl->by_indices[BY_MONTH]]; + + } else { + + int inc; + + if(impl->rule.freq == ICAL_MONTHLY_RECURRENCE){ + inc = impl->rule.interval; + } else { + inc = 1; + } + + impl->last.month+=inc; + + /* Months are offset by one */ + impl->last.month--; + + years = impl->last.month / 12; + + impl->last.month = impl->last.month % 12; + + impl->last.month++; + + if (years != 0){ + increment_year(impl,years); + } + } +} + +void increment_monthday(struct icalrecur_iterator_impl* impl, int inc) +{ + int i; + + for(i=0; i<inc; i++){ + + short days_in_month = + icaltime_days_in_month(impl->last.month,impl->last.year); + + impl->last.day++; + + if (impl->last.day > days_in_month){ + impl->last.day = impl->last.day-days_in_month; + increment_month(impl); + } + } +} + + +void increment_hour(struct icalrecur_iterator_impl* impl, int inc) +{ + short days; + + impl->last.hour+=inc; + + days = impl->last.hour / 24; + impl->last.hour = impl->last.hour % 24; + + if (impl->days != 0){ + increment_monthday(impl,days); + } +} + +void increment_minute(struct icalrecur_iterator_impl* impl, int inc) +{ + short hours; + + impl->last.minute+=inc; + + hours = impl->last.minute / 60; + impl->last.minute = impl->last.minute % 60; + + if (hours != 0){ + increment_hour(impl,hours); + } + +} + +void increment_second(struct icalrecur_iterator_impl* impl, int inc) +{ + short minutes; + + impl->last.second+=inc; + + minutes = impl->last.second / 60; + impl->last.second = impl->last.second % 60; + + if (minutes != 0) + { + increment_minute(impl, minutes); + } +} + +#if 0 +#include "ical.h" +void test_increment() +{ + struct icalrecur_iterator_impl impl; + + impl.last = icaltime_from_string("20000101T000000Z"); + + printf("Orig: %s\n",icaltime_as_ctime(impl.last)); + + increment_second(&impl,5); + printf("+ 5 sec : %s\n",icaltime_as_ctime(impl.last)); + + increment_second(&impl,355); + printf("+ 355 sec : %s\n",icaltime_as_ctime(impl.last)); + + increment_minute(&impl,5); + printf("+ 5 min : %s\n",icaltime_as_ctime(impl.last)); + + increment_minute(&impl,360); + printf("+ 360 min : %s\n",icaltime_as_ctime(impl.last)); + increment_hour(&impl,5); + printf("+ 5 hours : %s\n",icaltime_as_ctime(impl.last)); + increment_hour(&impl,43); + printf("+ 43 hours : %s\n",icaltime_as_ctime(impl.last)); + increment_monthday(&impl,3); + printf("+ 3 days : %s\n",icaltime_as_ctime(impl.last)); + increment_monthday(&impl,600); + printf("+ 600 days : %s\n",icaltime_as_ctime(impl.last)); + +} + +#endif + +short next_second(struct icalrecur_iterator_impl* impl) +{ + + short has_by_data = (impl->by_ptrs[BY_SECOND][0]!=ICAL_RECURRENCE_ARRAY_MAX); + short this_frequency = (impl->rule.freq == ICAL_SECONDLY_RECURRENCE); + + short end_of_data = 0; + + assert(has_by_data || this_frequency); + + if( has_by_data ){ + /* Ignore the frequency and use the byrule data */ + + impl->by_indices[BY_SECOND]++; + + if (impl->by_ptrs[BY_SECOND][impl->by_indices[BY_SECOND]] + ==ICAL_RECURRENCE_ARRAY_MAX){ + impl->by_indices[BY_SECOND] = 0; + + end_of_data = 1; + } + + + impl->last.second = + impl->by_ptrs[BY_SECOND][impl->by_indices[BY_SECOND]]; + + + } else if( !has_by_data && this_frequency ){ + /* Compute the next value from the last time and the frequency interval*/ + increment_second(impl, impl->rule.interval); + + } + + /* If we have gone through all of the seconds on the BY list, then we + need to move to the next minute */ + + if(has_by_data && end_of_data && this_frequency ){ + increment_minute(impl,1); + } + + return end_of_data; + +} + +int next_minute(struct icalrecur_iterator_impl* impl) +{ + + short has_by_data = (impl->by_ptrs[BY_MINUTE][0]!=ICAL_RECURRENCE_ARRAY_MAX); + short this_frequency = (impl->rule.freq == ICAL_MINUTELY_RECURRENCE); + + short end_of_data = 0; + + assert(has_by_data || this_frequency); + + + if (next_second(impl) == 0){ + return 0; + } + + if( has_by_data ){ + /* Ignore the frequency and use the byrule data */ + + impl->by_indices[BY_MINUTE]++; + + if (impl->by_ptrs[BY_MINUTE][impl->by_indices[BY_MINUTE]] + ==ICAL_RECURRENCE_ARRAY_MAX){ + + impl->by_indices[BY_MINUTE] = 0; + + end_of_data = 1; + } + + impl->last.minute = + impl->by_ptrs[BY_MINUTE][impl->by_indices[BY_MINUTE]]; + + } else if( !has_by_data && this_frequency ){ + /* Compute the next value from the last time and the frequency interval*/ + increment_minute(impl,impl->rule.interval); + } + +/* If we have gone through all of the minutes on the BY list, then we + need to move to the next hour */ + + if(has_by_data && end_of_data && this_frequency ){ + increment_hour(impl,1); + } + + return end_of_data; +} + +int next_hour(struct icalrecur_iterator_impl* impl) +{ + + short has_by_data = (impl->by_ptrs[BY_HOUR][0]!=ICAL_RECURRENCE_ARRAY_MAX); + short this_frequency = (impl->rule.freq == ICAL_HOURLY_RECURRENCE); + + short end_of_data = 0; + + assert(has_by_data || this_frequency); + + if (next_minute(impl) == 0){ + return 0; + } + + if( has_by_data ){ + /* Ignore the frequency and use the byrule data */ + + impl->by_indices[BY_HOUR]++; + + if (impl->by_ptrs[BY_HOUR][impl->by_indices[BY_HOUR]] + ==ICAL_RECURRENCE_ARRAY_MAX){ + impl->by_indices[BY_HOUR] = 0; + + end_of_data = 1; + } + + impl->last.hour = + impl->by_ptrs[BY_HOUR][impl->by_indices[BY_HOUR]]; + + } else if( !has_by_data && this_frequency ){ + /* Compute the next value from the last time and the frequency interval*/ + increment_hour(impl,impl->rule.interval); + + } + + /* If we have gone through all of the hours on the BY list, then we + need to move to the next day */ + + if(has_by_data && end_of_data && this_frequency ){ + increment_monthday(impl,1); + } + + return end_of_data; + +} + +int next_day(struct icalrecur_iterator_impl* impl) +{ + + short has_by_data = (impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX); + short this_frequency = (impl->rule.freq == ICAL_DAILY_RECURRENCE); + + assert(has_by_data || this_frequency); + + if (next_hour(impl) == 0){ + return 0; + } + + /* Always increment through the interval, since this routine is not + called by any other next_* routine, and the days that are + excluded will be taken care of by restriction filtering */ + + if(this_frequency){ + increment_monthday(impl,impl->rule.interval); + } else { + increment_monthday(impl,1); + } + + + return 0; + +} + + +int next_yearday(struct icalrecur_iterator_impl* impl) +{ + + short has_by_data = (impl->by_ptrs[BY_YEAR_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX); + + short end_of_data = 0; + + assert(has_by_data ); + + if (next_hour(impl) == 0){ + return 0; + } + + impl->by_indices[BY_YEAR_DAY]++; + + if (impl->by_ptrs[BY_YEAR_DAY][impl->by_indices[BY_YEAR_DAY]] + ==ICAL_RECURRENCE_ARRAY_MAX){ + impl->by_indices[BY_YEAR_DAY] = 0; + + end_of_data = 1; + } + + impl->last.day = + impl->by_ptrs[BY_YEAR_DAY][impl->by_indices[BY_YEAR_DAY]]; + + if(has_by_data && end_of_data){ + increment_year(impl,1); + } + + return end_of_data; + +} + +/* This routine is only called by next_week. It is certain that BY_DAY +has data */ + +int next_weekday_by_week(struct icalrecur_iterator_impl* impl) +{ + + short end_of_data = 0; + short start_of_week, dow; + struct icaltimetype next; + + if (next_hour(impl) == 0){ + return 0; + } + + assert( impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX); + + while(1) { + + impl->by_indices[BY_DAY]++; /* Look at next elem in BYDAY array */ + + /* Are we at the end of the BYDAY array? */ + if (impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]] + ==ICAL_RECURRENCE_ARRAY_MAX){ + + impl->by_indices[BY_DAY] = 0; /* Reset to 0 */ + end_of_data = 1; /* Signal that we're at the end */ + } + + /* Add the day of week offset to to the start of this week, and use + that to get the next day */ + dow = impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]; + start_of_week = icaltime_start_doy_of_week(impl->last); + + dow--; /*Sun is 1, not 0 */ + + if(dow+start_of_week <1 && !end_of_data){ + /* The selected date is in the previous year. */ + continue; + } + + next = icaltime_from_day_of_year(start_of_week + dow,impl->last.year); + + impl->last.day = next.day; + impl->last.month = next.month; + impl->last.year = next.year; + + return end_of_data; + } + +} + +int nth_weekday(short dow, short pos, struct icaltimetype t){ + + short days_in_month = icaltime_days_in_month(t.month,t.year); + short end_dow, start_dow; + short wd; + + if(pos >= 0){ + t.day = 1; + start_dow = icaltime_day_of_week(t); + + if (pos != 0) { + pos--; + } + + /* find month day of first occurrence of dow -- such as the + month day of the first monday */ + + wd = dow-start_dow+1; + + if (wd <= 0){ + wd = wd + 7; + } + + wd = wd + pos * 7; + + } else { + t.day = days_in_month; + end_dow = icaltime_day_of_week(t); + + pos++; + + /* find month day of last occurrence of dow -- such as the + month day of the last monday */ + + wd = (end_dow - dow); + + if (wd < 0){ + wd = wd+ 7; + } + + wd = days_in_month - wd; + + wd = wd + pos * 7; + } + + return wd; +} + + +int next_month(struct icalrecur_iterator_impl* impl) +{ + int data_valid = 1; + + short this_frequency = (impl->rule.freq == ICAL_MONTHLY_RECURRENCE); + + assert( has_by_data(impl,BY_MONTH) || this_frequency); + + /* Iterate through the occurrences within a day. If we don't get to + the end of the intra-day data, don't bother going to the next + month */ + + if (next_hour(impl) == 0){ + return data_valid; /* Signal that the data is valid */ + } + + + /* Now iterate through the occurrences within a month -- by days, + weeks or weekdays. */ + + if(has_by_data(impl,BY_DAY) && has_by_data(impl,BY_MONTH_DAY)){ + /* Cases like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR;BYMONTHDAY=13 */ + short day, idx,j; + short days_in_month = icaltime_days_in_month(impl->last.month, + impl->last.year); + /* Iterate through the remaining days in the month and check if + each day is listed in the BY_DAY array and in the BY_MONTHDAY + array. This seems very inneficient, but I think it is the + simplest way to account for both BYDAY=1FR (First friday in + month) and BYDAY=FR ( every friday in month ) */ + + for(day = impl->last.day+1; day <= days_in_month; day++){ + for(idx = 0; BYDAYPTR[idx] != ICAL_RECURRENCE_ARRAY_MAX; idx++){ + for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){ + short dow = + icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]); + short pos = icalrecurrencetype_day_position(BYDAYPTR[idx]); + short mday = BYMDPTR[j]; + short this_dow; + + impl->last.day = day; + this_dow = icaltime_day_of_week(impl->last); + + if( (pos == 0 && dow == this_dow && mday == day) || + (nth_weekday(dow,pos,impl->last) == day && mday==day)){ + goto MDEND; + } + } + } + } + + MDEND: + + if ( day > days_in_month){ + impl->last.day = 1; + increment_month(impl); + data_valid = 0; /* signal that impl->last is invalid */ + } + + + } else if(has_by_data(impl,BY_DAY)){ + /* Cases like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR */ + /* For this case, the weekdays are relative to the + month. BYDAY=FR -> First Friday in month, etc. */ + + short day, idx; + short days_in_month = icaltime_days_in_month(impl->last.month, + impl->last.year); + + assert( BYDAYPTR[0]!=ICAL_RECURRENCE_ARRAY_MAX); + + /* Iterate through the remaining days in the month and check if + each day is listed in the BY_DAY array. This seems very + inneficient, but I think it is the simplest way to account + for both BYDAY=1FR (First friday in month) and BYDAY=FR ( + every friday in month ) */ + + for(day = impl->last.day+1; day <= days_in_month; day++){ + for(idx = 0; BYDAYPTR[idx] != ICAL_RECURRENCE_ARRAY_MAX; idx++){ + short dow = icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]); + short pos = icalrecurrencetype_day_position(BYDAYPTR[idx]); + short this_dow; + + impl->last.day = day; + this_dow = icaltime_day_of_week(impl->last); + + if( (pos == 0 && dow == this_dow ) || + (nth_weekday(dow,pos,impl->last) == day)){ + goto DEND; + } + } + } + + DEND: + + if ( day > days_in_month){ + impl->last.day = 1; + increment_month(impl); + data_valid = 0; /* signal that impl->last is invalid */ + } + + } else if (has_by_data(impl,BY_MONTH_DAY)) { + /* Cases like: FREQ=MONTHLY;COUNT=10;BYMONTHDAY=-3 */ + short day; + + assert( BYMDPTR[0]!=ICAL_RECURRENCE_ARRAY_MAX); + + BYMDIDX++; + + /* Are we at the end of the BYDAY array? */ + if (BYMDPTR[BYMDIDX] ==ICAL_RECURRENCE_ARRAY_MAX){ + + BYMDIDX = 0; /* Reset to 0 */ + increment_month(impl); + } + + day = BYMDPTR[BYMDIDX]; + + if (day < 0) { + day = icaltime_days_in_month(impl->last.month,impl->last.year)+ + day + 1; + } + + impl->last.day = day; + + } else { + increment_month(impl); + } + + return data_valid; /* Signal that the data is valid */ + +} + + +int next_week(struct icalrecur_iterator_impl* impl) +{ + short has_by_data = (impl->by_ptrs[BY_WEEK_NO][0]!=ICAL_RECURRENCE_ARRAY_MAX); + short this_frequency = (impl->rule.freq == ICAL_WEEKLY_RECURRENCE); + short end_of_data = 0; + + /* Increment to the next week day */ + if (next_weekday_by_week(impl) == 0){ + return 0; /* Have not reached end of week yet */ + } + + /* If we get here, we have incremented through the entire week, and + can increment to the next week */ + + + if( has_by_data){ + /* Use the Week Number byrule data */ + int week_no; + struct icaltimetype t; + + impl->by_indices[BY_WEEK_NO]++; + + if (impl->by_ptrs[BY_WEEK_NO][impl->by_indices[BY_WEEK_NO]] + ==ICAL_RECURRENCE_ARRAY_MAX){ + impl->by_indices[BY_WEEK_NO] = 0; + + end_of_data = 1; + } + + t = impl->last; + t.month=1; /* HACK, should be setting to the date of the first week of year*/ + t.day=1; + + week_no = impl->by_ptrs[BY_WEEK_NO][impl->by_indices[BY_WEEK_NO]]; + + impl->last.day += week_no*7; + + impl->last = icaltime_normalize(impl->last); + + } else if( !has_by_data && this_frequency ){ + /* If there is no BY_WEEK_NO data, just jump forward 7 days. */ + increment_monthday(impl,7*impl->rule.interval); + } + + + if(has_by_data && end_of_data && this_frequency ){ + increment_year(impl,1); + } + + return end_of_data; + +} + +/* Expand the BYDAY rule part and return a pointer to a newly allocated list of days. */ +pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year) +{ + /* Try to calculate each of the occurrences. */ + int i; + pvl_list days_list = pvl_newlist(); + + short start_dow, end_dow, end_year_day, start_doy; + struct icaltimetype tmp = impl->last; + + tmp.year= year; + tmp.month = 1; + tmp.day = 1; + tmp.is_date = 1; + + start_dow = icaltime_day_of_week(tmp); + start_doy = icaltime_start_doy_of_week(tmp); + + /* Get the last day of the year*/ + tmp.year++; + tmp = icaltime_normalize(tmp); + tmp.day--; + tmp = icaltime_normalize(tmp); + + end_dow = icaltime_day_of_week(tmp); + end_year_day = icaltime_day_of_year(tmp); + + for(i = 0; BYDAYPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){ + short dow = + icalrecurrencetype_day_day_of_week(BYDAYPTR[i]); + short pos = icalrecurrencetype_day_position(BYDAYPTR[i]); + + if(pos == 0){ + /* The day was specified without a position -- it is just + a bare day of the week ( BYDAY=SU) so add all of the + days of the year with this day-of-week*/ + int week; + for(week = 0; week < 52 ; week ++){ + short doy = start_doy + (week * 7) + dow-1; + + if(doy > end_year_day){ + break; + } else { + pvl_push(days_list,(void*)(int)doy); + } + } + } else if ( pos > 0) { + int first; + /* First occurrence of dow in year */ + if( dow >= start_dow) { + first = dow - start_dow + 1; + } else { + first = dow - start_dow + 8; + } + + /* THen just multiple the position times 7 to get the pos'th day in the year */ + pvl_push(days_list,(void*)(first+ (pos-1) * 7)); + + } else { /* pos < 0 */ + int last; + pos = -pos; + + /* last occurrence of dow in year */ + if( dow <= end_dow) { + last = end_year_day - end_dow + dow; + } else { + last = end_year_day - end_dow + dow - 7; + } + + pvl_push(days_list,(void*)(last - (pos-1) * 7)); + } + } + return days_list; +} + + +/* For INTERVAL=YEARLY, set up the days[] array in the iterator to + list all of the days of the current year that are specified in this + rule. */ + +int expand_year_days(struct icalrecur_iterator_impl* impl,short year) +{ + int j,k; + int days_index=0; + struct icaltimetype t; + int flags; + + t = icaltime_null_time(); + +#define HBD(x) has_by_data(impl,x) + + t.is_date = 1; /* Needed to make day_of_year routines work property */ + + memset(&t,0,sizeof(t)); + memset(impl->days,ICAL_RECURRENCE_ARRAY_MAX_BYTE,sizeof(impl->days)); + + flags = (HBD(BY_DAY) ? 1<<BY_DAY : 0) + + (HBD(BY_WEEK_NO) ? 1<<BY_WEEK_NO : 0) + + (HBD(BY_MONTH_DAY) ? 1<<BY_MONTH_DAY : 0) + + (HBD(BY_MONTH) ? 1<<BY_MONTH : 0) + + (HBD(BY_YEAR_DAY) ? 1<<BY_YEAR_DAY : 0); + + + switch(flags) { + + case 0: { + /* FREQ=YEARLY; */ + + break; + } + case 1<<BY_MONTH: { + /* FREQ=YEARLY; BYMONTH=3,11*/ + + for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){ + struct icaltimetype t; + short month = impl->by_ptrs[BY_MONTH][j]; + short doy; + + t = impl->dtstart; + t.year = year; + t.month = month; + t.is_date = 1; + + doy = icaltime_day_of_year(t); + + impl->days[days_index++] = doy; + + } + break; + } + + case 1<<BY_MONTH_DAY: { + /* FREQ=YEARLY; BYMONTHDAY=1,15*/ + for(k=0;impl->by_ptrs[BY_MONTH_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++) + { + short month_day = impl->by_ptrs[BY_MONTH_DAY][k]; + short doy; + + t = impl->dtstart; + t.day = month_day; + t.year = year; + t.is_date = 1; + + doy = icaltime_day_of_year(t); + + impl->days[days_index++] = doy; + + } + break; + } + + case (1<<BY_MONTH_DAY) + (1<<BY_MONTH): { + /* FREQ=YEARLY; BYMONTHDAY=1,15; BYMONTH=10 */ + + for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){ + for(k=0;impl->by_ptrs[BY_MONTH_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++) + { + short month = impl->by_ptrs[BY_MONTH][j]; + short month_day = impl->by_ptrs[BY_MONTH_DAY][k]; + short doy; + + t.day = month_day; + t.month = month; + t.year = year; + t.is_date = 1; + + doy = icaltime_day_of_year(t); + + impl->days[days_index++] = doy; + + } + } + + break; + } + + case 1<<BY_WEEK_NO: { + /* FREQ=YEARLY; BYWEEKNO=20,50 */ + + struct icaltimetype t; + short dow; + + t.day = impl->dtstart.day; + t.month = impl->dtstart.month; + t.year = year; + t.is_date = 1; + + dow = icaltime_day_of_week(t); + /* HACK Not finished */ + + icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR); + + break; + } + + case (1<<BY_WEEK_NO) + (1<<BY_MONTH_DAY): { + /*FREQ=YEARLY; WEEKNO=20,50; BYMONTH= 6,11 */ + icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR); + break; + } + + case 1<<BY_DAY: { + /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR*/ + int days_index = 0; + pvl_elem i; + pvl_list days = expand_by_day(impl,year); + + + for(i=pvl_head(days);i!=0;i=pvl_next(i)){ + short day = (short)(int)pvl_data(i); + impl->days[days_index++] = day; + } + + pvl_free(days); + + break; + } + + case (1<<BY_DAY)+(1<<BY_MONTH): { + /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTH = 12*/ + + int days_index = 0; + pvl_elem itr; + pvl_list days = expand_by_day(impl,year); + + for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){ + short doy = (short)(int)pvl_data(itr); + struct icaltimetype tt; + short j; + + tt = icaltime_from_day_of_year(doy,year); + + for(j=0; + impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX; + j++){ + short month = impl->by_ptrs[BY_MONTH][j]; + + if(tt.month == month){ + impl->days[days_index++] = doy; + } + } + + } + + pvl_free(days); + + break; + } + + case (1<<BY_DAY) + (1<<BY_MONTH_DAY) : { + /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTHDAY=1,15*/ + + int days_index = 0; + pvl_elem itr; + pvl_list days = expand_by_day(impl,year); + + for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){ + short day = (short)(int)pvl_data(itr); + struct icaltimetype tt; + short j; + + tt = icaltime_from_day_of_year(day,year); + + for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){ + short mday = BYMDPTR[j]; + + if(tt.day == mday){ + impl->days[days_index++] = day; + } + } + + } + + pvl_free(days); + + break; + } + + case (1<<BY_DAY) + (1<<BY_MONTH_DAY) + (1<<BY_MONTH): { + /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTHDAY=10; MYMONTH=6,11*/ + + int days_index = 0; + pvl_elem itr; + pvl_list days = expand_by_day(impl,year); + + for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){ + short day = (short)(int)pvl_data(itr); + struct icaltimetype tt; + short i,j; + + tt = icaltime_from_day_of_year(day,year); + + for(i = 0; BYMONPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){ + for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){ + short mday = BYMDPTR[j]; + short month = BYMONPTR[i]; + + if(tt.month == month && tt.day == mday){ + impl->days[days_index++] = day; + } + } + } + + } + + pvl_free(days); + + break; + + } + + case (1<<BY_DAY) + (1<<BY_WEEK_NO) : { + /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; WEEKNO=20,50*/ + + int days_index = 0; + pvl_elem itr; + pvl_list days = expand_by_day(impl,year); + + for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){ + short day = (short)(int)pvl_data(itr); + struct icaltimetype tt; + short i; + + tt = icaltime_from_day_of_year(day,year); + + for(i = 0; BYWEEKPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){ + short weekno = BYWEEKPTR[i]; + + if(weekno== icaltime_week_number(tt)){ + impl->days[days_index++] = day; + } + } + + } + + pvl_free(days); + break; + } + + case (1<<BY_DAY) + (1<<BY_WEEK_NO) + (1<<BY_MONTH_DAY): { + /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; WEEKNO=20,50; BYMONTHDAY=1,15*/ + icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR); + break; + } + + case 1<<BY_YEAR_DAY: { + for(j=0;impl->by_ptrs[BY_YEAR_DAY][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){ + short doy = impl->by_ptrs[BY_YEAR_DAY][j]; + impl->days[days_index++] = doy; + } + break; + } + + default: { + icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR); + break; + } + + } + + return 0; +} + + +int next_year(struct icalrecur_iterator_impl* impl) +{ + struct icaltimetype next; + + /* Next_year does it's own interatio in days, so the next level down is hours */ + if (next_hour(impl) == 0){ + return 1; + } + + if (impl->days[++impl->days_index] == ICAL_RECURRENCE_ARRAY_MAX){ + impl->days_index = 0; + increment_year(impl,impl->rule.interval); + expand_year_days(impl,impl->last.year); + } + + if(impl->days[0] == ICAL_RECURRENCE_ARRAY_MAX) { + return 0; + } + + next = icaltime_from_day_of_year(impl->days[impl->days_index],impl->last.year); + + impl->last.day = next.day; + impl->last.month = next.month; + + return 1; +} + +int icalrecur_check_rulepart(struct icalrecur_iterator_impl* impl, + short v, enum byrule byrule) +{ + int itr; + + if(impl->by_ptrs[byrule][0]!=ICAL_RECURRENCE_ARRAY_MAX){ + for(itr=0; impl->by_ptrs[byrule][itr]!=ICAL_RECURRENCE_ARRAY_MAX;itr++){ + if(impl->by_ptrs[byrule][itr] == v){ + return 1; + } + } + } + + return 0; +} + +int check_contract_restriction(struct icalrecur_iterator_impl* impl, + enum byrule byrule, short v) +{ + int pass = 0; + int itr; + icalrecurrencetype_frequency freq = impl->rule.freq; + + if(impl->by_ptrs[byrule][0]!=ICAL_RECURRENCE_ARRAY_MAX && + expand_map[freq].map[byrule] == CONTRACT){ + for(itr=0; impl->by_ptrs[byrule][itr]!=ICAL_RECURRENCE_ARRAY_MAX;itr++){ + if(impl->by_ptrs[byrule][itr] == v){ + pass=1; + break; + } + } + + return pass; + } else { + /* This is not a contracting byrule, or it has no data, so the + test passes*/ + return 1; + } +} + + +int check_contracting_rules(struct icalrecur_iterator_impl* impl) +{ + + int day_of_week=0; + int week_no=0; + int year_day=0; + + if ( + check_contract_restriction(impl,BY_SECOND,impl->last.second) && + check_contract_restriction(impl,BY_MINUTE,impl->last.minute) && + check_contract_restriction(impl,BY_HOUR,impl->last.hour) && + check_contract_restriction(impl,BY_DAY,day_of_week) && + check_contract_restriction(impl,BY_WEEK_NO,week_no) && + check_contract_restriction(impl,BY_MONTH_DAY,impl->last.day) && + check_contract_restriction(impl,BY_MONTH,impl->last.month) && + check_contract_restriction(impl,BY_YEAR_DAY,year_day) ) + { + + return 1; + } else { + return 0; + } +} + +struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr) +{ + int valid = 1; + struct icalrecur_iterator_impl* impl = + (struct icalrecur_iterator_impl*)itr; + + if( (impl->rule.count!=0 &&impl->occurrence_no >= impl->rule.count) || + (!icaltime_is_null_time(impl->rule.until) && + icaltime_compare(impl->last,impl->rule.until) > 0)) { + return icaltime_null_time(); + } + + if(impl->occurrence_no == 0 + && icaltime_compare(impl->last,impl->dtstart) >= 0){ + + impl->occurrence_no++; + return impl->last; + } + + do { + valid = 1; + switch(impl->rule.freq){ + + case ICAL_SECONDLY_RECURRENCE: { + next_second(impl); + break; + } + case ICAL_MINUTELY_RECURRENCE: { + next_minute(impl); + break; + } + case ICAL_HOURLY_RECURRENCE: { + next_hour(impl); + break; + } + case ICAL_DAILY_RECURRENCE: { + next_day(impl); + break; + } + case ICAL_WEEKLY_RECURRENCE: { + next_week(impl); + break; + } + case ICAL_MONTHLY_RECURRENCE: { + valid = next_month(impl); + break; + } + case ICAL_YEARLY_RECURRENCE:{ + valid = next_year(impl); + break; + } + default:{ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return icaltime_null_time(); + } + } + + if(impl->last.year >= 2038 ){ + /* HACK */ + return icaltime_null_time(); + } + + } while(!check_contracting_rules(impl) + || icaltime_compare(impl->last,impl->dtstart) <= 0 + || valid == 0); + + +/* Ignore null times and times that are after the until time */ + if( !icaltime_is_null_time(impl->rule.until) && + icaltime_compare(impl->last,impl->rule.until) > 0 ) { + return icaltime_null_time(); + } + + impl->occurrence_no++; + + return impl->last; +} + + +/************************** Type Routines **********************/ + + +void icalrecurrencetype_clear(struct icalrecurrencetype *recur) +{ + memset(recur,ICAL_RECURRENCE_ARRAY_MAX_BYTE, + sizeof(struct icalrecurrencetype)); + + recur->week_start = ICAL_MONDAY_WEEKDAY; + recur->freq = ICAL_NO_RECURRENCE; + recur->interval = 1; + memset(&(recur->until),0,sizeof(struct icaltimetype)); + recur->count = 0; +} + +/* The 'day' element of icalrecurrencetype_weekday is encoded to allow +reporesentation of both the day of the week ( Monday, Tueday), but +also the Nth day of the week ( First tuesday of the month, last +thursday of the year) These routines decode the day values. + +The day's position in the period ( Nth-ness) and the numerical value +of the day are encoded together as: pos*7 + dow + +A position of 0 means 'any' or 'every' + + */ + +enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day) +{ + return abs(day)%8; +} + +short icalrecurrencetype_day_position(short day) +{ + short wd, pos; + + wd = icalrecurrencetype_day_day_of_week(day); + + pos = (abs(day)-wd)/8 * ((day<0)?-1:1); + + + return pos; +} + + +/****************** Enumeration Routines ******************/ + +struct {icalrecurrencetype_weekday wd; const char * str; } +wd_map[] = { + {ICAL_SUNDAY_WEEKDAY,"SU"}, + {ICAL_MONDAY_WEEKDAY,"MO"}, + {ICAL_TUESDAY_WEEKDAY,"TU"}, + {ICAL_WEDNESDAY_WEEKDAY,"WE"}, + {ICAL_THURSDAY_WEEKDAY,"TH"}, + {ICAL_FRIDAY_WEEKDAY,"FR"}, + {ICAL_SATURDAY_WEEKDAY,"SA"}, + {ICAL_NO_WEEKDAY,0} +}; + +const char* icalrecur_weekday_to_string(icalrecurrencetype_weekday kind) +{ + int i; + + for (i=0; wd_map[i].wd != ICAL_NO_WEEKDAY; i++) { + if ( wd_map[i].wd == kind) { + return wd_map[i].str; + } + } + + return 0; +} + +icalrecurrencetype_weekday icalrecur_string_to_weekday(const char* str) +{ + int i; + + for (i=0; wd_map[i].wd != ICAL_NO_WEEKDAY; i++) { + if ( strcmp(str,wd_map[i].str) == 0){ + return wd_map[i].wd; + } + } + + return ICAL_NO_WEEKDAY; +} + + + +struct { + icalrecurrencetype_frequency kind; + const char* str; +} freq_map[] = { + {ICAL_SECONDLY_RECURRENCE,"SECONDLY"}, + {ICAL_MINUTELY_RECURRENCE,"MINUTELY"}, + {ICAL_HOURLY_RECURRENCE,"HOURLY"}, + {ICAL_DAILY_RECURRENCE,"DAILY"}, + {ICAL_WEEKLY_RECURRENCE,"WEEKLY"}, + {ICAL_MONTHLY_RECURRENCE,"MONTHLY"}, + {ICAL_YEARLY_RECURRENCE,"YEARLY"}, + {ICAL_NO_RECURRENCE,0} +}; + +const char* icalrecur_freq_to_string(icalrecurrencetype_frequency kind) +{ + int i; + + for (i=0; freq_map[i].kind != ICAL_NO_RECURRENCE ; i++) { + if ( freq_map[i].kind == kind ) { + return freq_map[i].str; + } + } + return 0; +} + +icalrecurrencetype_frequency icalrecur_string_to_freq(const char* str) +{ + int i; + + for (i=0; freq_map[i].kind != ICAL_NO_RECURRENCE ; i++) { + if ( strcmp(str,freq_map[i].str) == 0){ + return freq_map[i].kind; + } + } + return ICAL_NO_RECURRENCE; +} + +/* Fill an array with the 'count' number of occurrences generated by + the rrule. Note that the times are returned in UTC, but the times + are calculated in local time. YOu will have to convert the results + back into local time before using them. */ + +int icalrecur_expand_recurrence(char* rule, time_t start, + int count, time_t* array) +{ + struct icalrecurrencetype recur; + icalrecur_iterator* ritr; + time_t tt; + struct icaltimetype icstart, next; + int i = 0; + + memset(array, 0, count*sizeof(time_t)); + + icstart = icaltime_from_timet(start,0); + + recur = icalrecurrencetype_from_string(rule); + + for(ritr = icalrecur_iterator_new(recur,icstart), + next = icalrecur_iterator_next(ritr); + !icaltime_is_null_time(next) && i < count; + next = icalrecur_iterator_next(ritr)){ + + tt = icaltime_as_timet(next); + + if (tt >= start ){ + array[i++] = tt; + } + + } + + icalrecur_iterator_free(ritr); + + return 1; +} diff --git a/libical/src/libical/icalrecur.h b/libical/src/libical/icalrecur.h new file mode 100644 index 0000000..5fcdc15 --- a/dev/null +++ b/libical/src/libical/icalrecur.h @@ -0,0 +1,189 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalrecur.h + CREATOR: eric 20 March 2000 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + +How to use: + +1) Get a rule and a start time from a component + icalproperty rrule; + struct icalrecurrencetype recur; + struct icaltimetype dtstart; + + rrule = icalcomponent_get_first_property(comp,ICAL_RRULE_PROPERTY); + recur = icalproperty_get_rrule(rrule); + start = icalproperty_get_dtstart(dtstart); + +Or, just make them up: + recur = icalrecurrencetype_from_string("FREQ=YEARLY;BYDAY=SU,WE"); + dtstart = icaltime_from_string("19970101T123000") + +2) Create an iterator + icalrecur_iterator* ritr; + ritr = icalrecur_iterator_new(recur,start); + +3) Iterator over the occurrences + struct icaltimetype next; + while (next = icalrecur_iterator_next(ritr) + && !icaltime_is_null_time(next){ + Do something with next + } + +Note that that the time returned by icalrecur_iterator_next is in +whatever timezone that dtstart is in. + +======================================================================*/ + +#ifndef ICALRECUR_H +#define ICALRECUR_H + +#include <time.h> +#include "icaltime.h" + +/*********************************************************************** + * Recurrance enumerations +**********************************************************************/ + +typedef enum icalrecurrencetype_frequency +{ + /* These enums are used to index an array, so don't change the + order or the integers */ + + ICAL_SECONDLY_RECURRENCE=0, + ICAL_MINUTELY_RECURRENCE=1, + ICAL_HOURLY_RECURRENCE=2, + ICAL_DAILY_RECURRENCE=3, + ICAL_WEEKLY_RECURRENCE=4, + ICAL_MONTHLY_RECURRENCE=5, + ICAL_YEARLY_RECURRENCE=6, + ICAL_NO_RECURRENCE=7 + +} icalrecurrencetype_frequency; + +typedef enum icalrecurrencetype_weekday +{ + ICAL_NO_WEEKDAY, + ICAL_SUNDAY_WEEKDAY, + ICAL_MONDAY_WEEKDAY, + ICAL_TUESDAY_WEEKDAY, + ICAL_WEDNESDAY_WEEKDAY, + ICAL_THURSDAY_WEEKDAY, + ICAL_FRIDAY_WEEKDAY, + ICAL_SATURDAY_WEEKDAY +} icalrecurrencetype_weekday; + +enum { + ICAL_RECURRENCE_ARRAY_MAX = 0x7f7f, + ICAL_RECURRENCE_ARRAY_MAX_BYTE = 0x7f +}; + + + +/********************** Recurrence type routines **************/ + +/* See RFC 2445 Section 4.3.10, RECUR Value, for an explaination of + the values and fields in struct icalrecurrencetype */ + +#define ICAL_BY_SECOND_SIZE 61 +#define ICAL_BY_MINUTE_SIZE 61 +#define ICAL_BY_HOUR_SIZE 25 +#define ICAL_BY_DAY_SIZE 364 /* 7 days * 52 weeks */ +#define ICAL_BY_MONTHDAY_SIZE 32 +#define ICAL_BY_YEARDAY_SIZE 367 +#define ICAL_BY_WEEKNO_SIZE 54 +#define ICAL_BY_MONTH_SIZE 13 +#define ICAL_BY_SETPOS_SIZE 367 + +/* Main struct for holding digested recurrence rules */ +struct icalrecurrencetype +{ + icalrecurrencetype_frequency freq; + + + /* until and count are mutually exclusive. */ + struct icaltimetype until; + int count; + + short interval; + + icalrecurrencetype_weekday week_start; + + /* The BY* parameters can each take a list of values. Here I + * assume that the list of values will not be larger than the + * range of the value -- that is, the client will not name a + * value more than once. + + * Each of the lists is terminated with the value + * ICAL_RECURRENCE_ARRAY_MAX unless the the list is full. + */ + + short by_second[ICAL_BY_SECOND_SIZE]; + short by_minute[ICAL_BY_MINUTE_SIZE]; + short by_hour[ICAL_BY_HOUR_SIZE]; + short by_day[ICAL_BY_DAY_SIZE]; /* Encoded value, see below */ + short by_month_day[ICAL_BY_MONTHDAY_SIZE]; + short by_year_day[ ICAL_BY_YEARDAY_SIZE]; + short by_week_no[ICAL_BY_WEEKNO_SIZE]; + short by_month[ICAL_BY_MONTH_SIZE]; + short by_set_pos[ICAL_BY_SETPOS_SIZE]; +}; + + +void icalrecurrencetype_clear(struct icalrecurrencetype *r); + +/* The 'day' element of the by_day array is encoded to allow +representation of both the day of the week ( Monday, Tueday), but also +the Nth day of the week ( First tuesday of the month, last thursday of +the year) These routines decode the day values */ + +/* 1 == Monday, etc. */ +enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day); + +/* 0 == any of day of week. 1 == first, 2 = second, -2 == second to last, etc */ +short icalrecurrencetype_day_position(short day); + + +/*********************************************************************** + * Recurrance rule parser +**********************************************************************/ + +/* Convert between strings ans recurrencetype structures. */ +struct icalrecurrencetype icalrecurrencetype_from_string(const char* str); +char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur); + + +/********** recurrence iteration routines ********************/ + +typedef void icalrecur_iterator; + +/* Create a new recurrence rule iterator */ +icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule, + struct icaltimetype dtstart); + +/* Get the next occurrence from an iterator */ +struct icaltimetype icalrecur_iterator_next(icalrecur_iterator*); + +/* Free the iterator */ +void icalrecur_iterator_free(icalrecur_iterator*); + +/* Fills array up with at most 'count' time_t values, each + representing an occurrence time in seconds past the POSIX epoch */ +int icalrecur_expand_recurrence(char* rule, time_t start, + int count, time_t* array); + + +#endif diff --git a/libical/src/libical/icalrestriction.c b/libical/src/libical/icalrestriction.c new file mode 100644 index 0000000..0f863c4 --- a/dev/null +++ b/libical/src/libical/icalrestriction.c @@ -0,0 +1,1781 @@ +/* -*- Mode: C -*- */ +/* ====================================================================== + File: icalrestriction.c + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + ======================================================================*/ +/*#line 7 "icalrestriction.c.in"*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalrestriction.h" +#include "icalenums.h" +#include "icalerror.h" + +#include <assert.h> +#include <stdio.h> /* For snprintf */ + +int snprintf(char *str, size_t n, char const *fmt, ...); + +#define TMP_BUF_SIZE 1024 + + +/* Define the structs for the restrictions. these data are filled out +in machine generated code below */ + +struct icalrestriction_property_record; + +typedef char* (*restriction_func)(struct icalrestriction_property_record* rec,icalcomponent* comp,icalproperty* prop); + + +typedef struct icalrestriction_property_record { + icalproperty_method method; + icalcomponent_kind component; + icalproperty_kind property; + icalrestriction_kind restriction; + restriction_func function; +} icalrestriction_property_record; + + +typedef struct icalrestriction_component_record { + icalproperty_method method; + icalcomponent_kind component; + icalcomponent_kind subcomponent; + icalrestriction_kind restriction; + restriction_func function; +} icalrestriction_component_record; + +icalrestriction_property_record* +icalrestriction_get_property_restriction(icalproperty_method method, + icalcomponent_kind component, + icalproperty_kind property); +icalrestriction_component_record* +icalrestriction_get_component_restriction(icalproperty_method method, + icalcomponent_kind component, + icalcomponent_kind subcomponent); + +icalrestriction_component_record icalrestriction_component_records[]; +icalrestriction_property_record icalrestriction_property_records[]; + +icalrestriction_property_record null_prop_record = {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_PROPERTY,ICAL_RESTRICTION_UNKNOWN,0}; +icalrestriction_component_record null_comp_record = {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_COMPONENT,ICAL_RESTRICTION_UNKNOWN,0}; + + +/* The each row gives the result of comparing a restriction against a + count. The columns in each row represent 0,1,2+. '-1' indicates + 'invalid, 'don't care' or 'needs more analysis' So, for + ICAL_RESTRICTION_ONE, if there is 1 of a property with that + restriction, it passes, but if there are 0 or 2+, it fails. */ + +char compare_map[ICAL_RESTRICTION_UNKNOWN+1][3] = { + { 1, 1, 1},/*ICAL_RESTRICTION_NONE*/ + { 1, 0, 0},/*ICAL_RESTRICTION_ZERO*/ + { 0, 1, 0},/*ICAL_RESTRICTION_ONE*/ + { 1, 1, 1},/*ICAL_RESTRICTION_ZEROPLUS*/ + { 0, 1, 1},/*ICAL_RESTRICTION_ONEPLUS*/ + { 1, 1, 0},/*ICAL_RESTRICTION_ZEROORONE*/ + { 1, 1, 0},/*ICAL_RESTRICTION_ONEEXCLUSIVE*/ + { 1, 1, 0},/*ICAL_RESTRICTION_ONEMUTUAL*/ + { 1, 1, 1} /*ICAL_RESTRICTION_UNKNOWN*/ +}; + +char restr_string_map[ICAL_RESTRICTION_UNKNOWN+1][60] = { + "unknown number",/*ICAL_RESTRICTION_NONE*/ + "0",/*ICAL_RESTRICTION_ZERO*/ + "1",/*ICAL_RESTRICTION_ONE*/ + "zero or more",/*ICAL_RESTRICTION_ZEROPLUS*/ + "one or more" ,/*ICAL_RESTRICTION_ONEPLUS*/ + "zero or one",/*ICAL_RESTRICTION_ZEROORONE*/ + "zero or one, exclusive with another property",/*ICAL_RESTRICTION_ONEEXCLUSIVE*/ + "zero or one, mutual with another property",/*ICAL_RESTRICTION_ONEMUTUAL*/ + "unknown number" /*ICAL_RESTRICTION_UNKNOWN*/ +}; + + +int +icalrestriction_compare(icalrestriction_kind restr, int count){ + + if ( restr < ICAL_RESTRICTION_NONE || restr > ICAL_RESTRICTION_UNKNOWN + || count < 0){ + return -1; + } + + if (count > 2) { + count = 2; + } + + return compare_map[restr][count]; + +} + +/* Special case routines */ + +char* icalrestriction_may_be_draft_final_canceled( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + + icalproperty_status stat = icalproperty_get_status(prop); + + if( !( stat == ICAL_STATUS_DRAFT || + stat == ICAL_STATUS_FINAL || + stat == ICAL_STATUS_CANCELLED )){ + + return "Failed iTIP restrictions for STATUS property. Value must be one of DRAFT, FINAL, or CANCELED"; + + } + + return 0; +} + +char* icalrestriction_may_be_comp_need_process( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + icalproperty_status stat = icalproperty_get_status(prop); + + if( !( stat == ICAL_STATUS_COMPLETED || + stat == ICAL_STATUS_NEEDSACTION || + stat == ICAL_STATUS_INPROCESS )){ + + return "Failed iTIP restrictions for STATUS property. Value must be one of COMPLETED, NEEDS-ACTION or IN-PROCESS"; + + } + + return 0; +} +char* icalrestriction_may_be_tent_conf(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + icalproperty_status stat = icalproperty_get_status(prop); + + if( !( stat == ICAL_STATUS_TENTATIVE || + stat == ICAL_STATUS_CONFIRMED )){ + + return "Failed iTIP restrictions for STATUS property. Value must be one of TENTATIVE or CONFIRMED"; + + } + + return 0; +} +char* icalrestriction_may_be_tent_conf_cancel( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + icalproperty_status stat = icalproperty_get_status(prop); + + if( !( stat == ICAL_STATUS_TENTATIVE || + stat == ICAL_STATUS_CONFIRMED || + stat == ICAL_STATUS_CANCELLED )){ + + return "Failed iTIP restrictions for STATUS property. Value must be one of TENTATIVE, CONFIRMED or CANCELED"; + + } + + return 0; +} + +char* icalrestriction_must_be_cancel_if_present( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + /* This routine will not be called if prop == 0 */ + icalproperty_status stat = icalproperty_get_status(prop); + + if( stat != ICAL_STATUS_CANCELLED) + { + return "Failed iTIP restrictions for STATUS property. Value must be CANCELLED"; + + } + + + return 0; +} + +char* icalrestriction_must_be_canceled_no_attendee( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + + /* Hack. see rfc2446, 3.2.5 CANCEL for porperty STATUS. I don't + understand the note */ + + return 0; +} +char* icalrestriction_must_be_recurring(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + /* Hack */ + return 0; +} +char* icalrestriction_must_have_duration(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + + if( !icalcomponent_get_first_property(comp,ICAL_DURATION_PROPERTY)){ + + return "Failed iTIP restrictions for STATUS property. This component must have a DURATION property"; + + } + + return 0; +} +char* icalrestriction_must_have_repeat(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + if( !icalcomponent_get_first_property(comp,ICAL_REPEAT_PROPERTY)){ + + return "Failed iTIP restrictions for STATUS property. This component must have a REPEAT property"; + + } + + return 0; +} +char* icalrestriction_must_if_tz_ref(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + + /* Hack */ + return 0; +} +char* icalrestriction_no_dtend(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + + if( !icalcomponent_get_first_property(comp,ICAL_DTEND_PROPERTY)){ + + return "Failed iTIP restrictions for STATUS property. The component must not have both DURATION and DTEND"; + + } + + return 0; +} +char* icalrestriction_no_duration(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + + /* _no_dtend takes care of this one */ + return 0; +} + + +int icalrestriction_check_component(icalproperty_method method, + icalcomponent* comp) +{ + icalproperty_kind kind; + icalcomponent_kind comp_kind; + icalrestriction_kind restr; + icalrestriction_property_record *prop_record = 0L; + icalrestriction_component_record *comp_record = 0L; + char* funcr = 0; + icalproperty *prop; + + int count; + int compare; + int valid = 1; + + comp_kind = icalcomponent_isa(comp); + + /* Check all of the properties in this component */ + + for(kind = ICAL_ANY_PROPERTY+1; kind != ICAL_NO_PROPERTY; kind++){ + count = icalcomponent_count_properties(comp, kind); + + prop_record = icalrestriction_get_property_restriction(method, + comp_kind, + kind); + + restr = prop_record->restriction; + + if(restr == ICAL_RESTRICTION_ONEEXCLUSIVE || + restr == ICAL_RESTRICTION_ONEMUTUAL) { + + /* First treat is as a 0/1 restriction */ + restr = ICAL_RESTRICTION_ZEROORONE; + compare = icalrestriction_compare(restr,count); + + } else { + + compare = icalrestriction_compare(restr,count); + } + + assert(compare != -1); + + if (compare == 0){ + char temp[TMP_BUF_SIZE]; + + snprintf(temp, TMP_BUF_SIZE,"Failed iTIP restrictions for %s property. Expected %s instances of the property and got %d", + icalenum_property_kind_to_string(kind), + restr_string_map[restr], count); + + icalcomponent_add_property + (comp, + icalproperty_vanew_xlicerror( + temp, + icalparameter_new_xlicerrortype(ICAL_XLICERRORTYPE_INVALIDITIP), + 0)); + } + + + prop = icalcomponent_get_first_property(comp, kind); + + if (prop != 0 && prop_record->function !=0 ){ + funcr = prop_record->function(prop_record,comp,prop); + } + + if(funcr !=0){ + icalcomponent_add_property + (comp, + icalproperty_vanew_xlicerror( + funcr, + icalparameter_new_xlicerrortype( + ICAL_XLICERRORTYPE_INVALIDITIP), + 0)); + + compare = 0; + } + + valid = valid && compare; + } + + + + return valid; + + +} + +int icalrestriction_check(icalcomponent* outer_comp) +{ + icalcomponent_kind comp_kind; + icalproperty_method method; + icalcomponent* inner_comp; + icalproperty *method_prop; + int valid; + + icalerror_check_arg_rz( (outer_comp!=0), "outer comp"); + + + /* Get the Method value from the outer component */ + + comp_kind = icalcomponent_isa(outer_comp); + + if (comp_kind != ICAL_VCALENDAR_COMPONENT){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return 0; + } + + method_prop = icalcomponent_get_first_property(outer_comp, + ICAL_METHOD_PROPERTY); + + if (method_prop == 0){ + method = ICAL_METHOD_NONE; + } else { + method = icalproperty_get_method(method_prop); + } + + + /* Check the VCALENDAR wrapper */ + valid = icalrestriction_check_component(ICAL_METHOD_NONE,outer_comp); + + + /* Now check the inner components */ + + for(inner_comp= icalcomponent_get_first_component(outer_comp, + ICAL_ANY_COMPONENT); + inner_comp != 0; + inner_comp= icalcomponent_get_next_component(outer_comp, + ICAL_ANY_COMPONENT)){ + + valid = valid && icalrestriction_check_component(method,inner_comp); + + } + + + return valid; + +} + +icalrestriction_property_record* +icalrestriction_get_property_restriction(icalproperty_method method, + icalcomponent_kind component, + icalproperty_kind property) +{ + int i; + + for(i = 0; + icalrestriction_property_records[i].restriction != ICAL_RESTRICTION_NONE; + i++){ + + if (method == icalrestriction_property_records[i].method && + component == icalrestriction_property_records[i].component && + property == icalrestriction_property_records[i].property ){ + return &icalrestriction_property_records[i]; + } + } + + return &null_prop_record; +} + + +icalrestriction_component_record* +icalrestriction_get_component_restriction(icalproperty_method method, + icalcomponent_kind component, + icalcomponent_kind subcomponent) +{ + + int i; + + for(i = 0; + icalrestriction_component_records[i].restriction != ICAL_RESTRICTION_NONE; + i++){ + + if (method == icalrestriction_component_records[i].method && + component == icalrestriction_component_records[i].component && + subcomponent == icalrestriction_component_records[i].subcomponent ){ + return &icalrestriction_component_records[i]; + } + } + + return &null_comp_record; +} + +/* Everything below this line is machine generated. Do not edit. */ +icalrestriction_property_record icalrestriction_property_records[] = { + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_may_be_tent_conf_cancel}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_duration}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_dtend}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_may_be_tent_conf}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_duration}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_dtend}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_duration}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_duration}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_may_be_tent_conf}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,icalrestriction_must_be_recurring}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE ,icalrestriction_no_duration}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_duration}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_canceled_no_attendee}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_duration}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_duration}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_may_be_tent_conf_cancel}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_may_be_comp_need_process}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_may_be_comp_need_process}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,icalrestriction_must_be_recurring}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_canceled_no_attendee}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_may_be_comp_need_process}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_may_be_draft_final_canceled}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS ,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_cancel_if_present}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_VCALENDAR_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_duration}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,icalrestriction_no_duration}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VEVENT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTODO_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEEXCLUSIVE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_be_recurring}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VJOURNAL_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VFREEBUSY_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_VTIMEZONE_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XSTANDARD_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDAYLIGHT_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEMUTUAL,icalrestriction_must_have_repeat}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ONEMUTUAL,icalrestriction_must_have_duration}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XAUDIOALARM_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEMUTUAL,icalrestriction_must_have_repeat}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ONEMUTUAL,icalrestriction_must_have_duration}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XDISPLAYALARM_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ONEPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEMUTUAL,icalrestriction_must_have_repeat}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ONEMUTUAL,icalrestriction_must_have_duration}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XEMAILALARM_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_ACTION_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_ATTACH_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_ATTENDEE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_CALSCALE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_CATEGORIES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_CLASS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_COMMENT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_COMPLETED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_CONTACT_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_CREATED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_DESCRIPTION_PROPERTY,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_DTEND_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_DTSTAMP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_DTSTART_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_DUE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_DURATION_PROPERTY,ICAL_RESTRICTION_ONEMUTUAL,icalrestriction_must_have_repeat}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_REPEAT_PROPERTY,ICAL_RESTRICTION_ONEMUTUAL,icalrestriction_must_have_duration}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_EXDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_EXRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_FREEBUSY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_GEO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_LASTMODIFIED_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_LOCATION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_METHOD_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_ORGANIZER_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_PERCENTCOMPLETE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_PRIORITY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_PRODID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_RDATE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_RECURRENCEID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_RELATEDTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_REQUESTSTATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_RESOURCES_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_RRULE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_SEQUENCE_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_STATUS_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_SUMMARY_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_TRANSP_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_TRIGGER_PROPERTY,ICAL_RESTRICTION_ONE,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_TZID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_TZNAME_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_TZOFFSETFROM_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_TZOFFSETTO_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_TZURL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_UID_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_URL_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_VERSION_PROPERTY,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_XPROCEDUREALARM_COMPONENT,ICAL_X_PROPERTY,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_PROPERTY,ICAL_RESTRICTION_NONE} +}; +icalrestriction_component_record icalrestriction_component_records[] = { + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,icalrestriction_must_if_tz_ref}, + {ICAL_METHOD_PUBLISH,ICAL_VEVENT_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,icalrestriction_must_if_tz_ref}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VEVENT_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROORONE,icalrestriction_must_if_tz_ref}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VEVENT_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,icalrestriction_must_if_tz_ref}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VEVENT_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,icalrestriction_must_if_tz_ref}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VEVENT_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZERO,icalrestriction_must_if_tz_ref}, + {ICAL_METHOD_REFRESH,ICAL_VEVENT_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,icalrestriction_must_if_tz_ref}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_COUNTER,ICAL_VEVENT_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZERO,icalrestriction_must_if_tz_ref}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VEVENT_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZERO,icalrestriction_must_if_tz_ref}, + {ICAL_METHOD_PUBLISH,ICAL_VFREEBUSY_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VFREEBUSY_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VFREEBUSY_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VTODO_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REQUEST,ICAL_VTODO_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REPLY,ICAL_VTODO_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_VJOURNAL_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VTODO_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VTODO_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_REFRESH,ICAL_VTODO_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_COUNTER,ICAL_VTODO_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_DECLINECOUNTER,ICAL_VTODO_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_PUBLISH,ICAL_VJOURNAL_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROORONE,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_ADD,ICAL_VJOURNAL_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_VTIMEZONE_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_X_COMPONENT,ICAL_RESTRICTION_ZEROPLUS,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_VALARM_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_VEVENT_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_VFREEBUSY_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_CANCEL,ICAL_VJOURNAL_COMPONENT,ICAL_VTODO_COMPONENT,ICAL_RESTRICTION_ZERO,0}, + {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_COMPONENT,ICAL_RESTRICTION_NONE} +}; diff --git a/libical/src/libical/icalrestriction.c.in b/libical/src/libical/icalrestriction.c.in new file mode 100644 index 0000000..4544425 --- a/dev/null +++ b/libical/src/libical/icalrestriction.c.in @@ -0,0 +1,447 @@ +/* -*- Mode: C -*- */ +/* ====================================================================== + File: icalrestriction.c + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + ======================================================================*/ +/*#line 7 "icalrestriction.c.in"*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalrestriction.h" +#include "icalenums.h" +#include "icalerror.h" + +#include <assert.h> +#include <stdio.h> /* For snprintf */ + +#define TMP_BUF_SIZE 1024 + + +/* Define the structs for the restrictions. these data are filled out +in machine generated code below */ + +struct icalrestriction_property_record; + +typedef char* (*restriction_func)(struct icalrestriction_property_record* rec,icalcomponent* comp,icalproperty* prop); + + +typedef struct icalrestriction_property_record { + icalproperty_method method; + icalcomponent_kind component; + icalproperty_kind property; + icalrestriction_kind restriction; + restriction_func function; +} icalrestriction_property_record; + + +typedef struct icalrestriction_component_record { + icalproperty_method method; + icalcomponent_kind component; + icalcomponent_kind subcomponent; + icalrestriction_kind restriction; + restriction_func function; +} icalrestriction_component_record; + +icalrestriction_property_record* +icalrestriction_get_property_restriction(icalproperty_method method, + icalcomponent_kind component, + icalproperty_kind property); +icalrestriction_component_record* +icalrestriction_get_component_restriction(icalproperty_method method, + icalcomponent_kind component, + icalcomponent_kind subcomponent); + +icalrestriction_component_record icalrestriction_component_records[]; +icalrestriction_property_record icalrestriction_property_records[]; + +icalrestriction_property_record null_prop_record = {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_PROPERTY,ICAL_RESTRICTION_UNKNOWN,0}; +icalrestriction_component_record null_comp_record = {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_COMPONENT,ICAL_RESTRICTION_UNKNOWN,0}; + + +/* The each row gives the result of comparing a restriction against a + count. The columns in each row represent 0,1,2+. '-1' indicates + 'invalid, 'don't care' or 'needs more analysis' So, for + ICAL_RESTRICTION_ONE, if there is 1 of a property with that + restriction, it passes, but if there are 0 or 2+, it fails. */ + +char compare_map[ICAL_RESTRICTION_UNKNOWN+1][3] = { + { 1, 1, 1},/*ICAL_RESTRICTION_NONE*/ + { 1, 0, 0},/*ICAL_RESTRICTION_ZERO*/ + { 0, 1, 0},/*ICAL_RESTRICTION_ONE*/ + { 1, 1, 1},/*ICAL_RESTRICTION_ZEROPLUS*/ + { 0, 1, 1},/*ICAL_RESTRICTION_ONEPLUS*/ + { 1, 1, 0},/*ICAL_RESTRICTION_ZEROORONE*/ + { 1, 1, 0},/*ICAL_RESTRICTION_ONEEXCLUSIVE*/ + { 1, 1, 0},/*ICAL_RESTRICTION_ONEMUTUAL*/ + { 1, 1, 1} /*ICAL_RESTRICTION_UNKNOWN*/ +}; + +char restr_string_map[ICAL_RESTRICTION_UNKNOWN+1][60] = { + "unknown number",/*ICAL_RESTRICTION_NONE*/ + "0",/*ICAL_RESTRICTION_ZERO*/ + "1",/*ICAL_RESTRICTION_ONE*/ + "zero or more",/*ICAL_RESTRICTION_ZEROPLUS*/ + "one or more" ,/*ICAL_RESTRICTION_ONEPLUS*/ + "zero or one",/*ICAL_RESTRICTION_ZEROORONE*/ + "zero or one, exclusive with another property",/*ICAL_RESTRICTION_ONEEXCLUSIVE*/ + "zero or one, mutual with another property",/*ICAL_RESTRICTION_ONEMUTUAL*/ + "unknown number" /*ICAL_RESTRICTION_UNKNOWN*/ +}; + + +int +icalrestriction_compare(icalrestriction_kind restr, int count){ + + if ( restr < ICAL_RESTRICTION_NONE || restr > ICAL_RESTRICTION_UNKNOWN + || count < 0){ + return -1; + } + + if (count > 2) { + count = 2; + } + + return compare_map[restr][count]; + +} + +/* Special case routines */ + +char* icalrestriction_may_be_draft_final_canceled( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + + icalproperty_status stat = icalproperty_get_status(prop); + + if( !( stat == ICAL_STATUS_DRAFT || + stat == ICAL_STATUS_FINAL || + stat == ICAL_STATUS_CANCELLED )){ + + return "Failed iTIP restrictions for STATUS property. Value must be one of DRAFT, FINAL, or CANCELED"; + + } + + return 0; +} + +char* icalrestriction_may_be_comp_need_process( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + icalproperty_status stat = icalproperty_get_status(prop); + + if( !( stat == ICAL_STATUS_COMPLETED || + stat == ICAL_STATUS_NEEDSACTION || + stat == ICAL_STATUS_INPROCESS )){ + + return "Failed iTIP restrictions for STATUS property. Value must be one of COMPLETED, NEEDS-ACTION or IN-PROCESS"; + + } + + return 0; +} +char* icalrestriction_may_be_tent_conf(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + icalproperty_status stat = icalproperty_get_status(prop); + + if( !( stat == ICAL_STATUS_TENTATIVE || + stat == ICAL_STATUS_CONFIRMED )){ + + return "Failed iTIP restrictions for STATUS property. Value must be one of TENTATIVE or CONFIRMED"; + + } + + return 0; +} +char* icalrestriction_may_be_tent_conf_cancel( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + icalproperty_status stat = icalproperty_get_status(prop); + + if( !( stat == ICAL_STATUS_TENTATIVE || + stat == ICAL_STATUS_CONFIRMED || + stat == ICAL_STATUS_CANCELLED )){ + + return "Failed iTIP restrictions for STATUS property. Value must be one of TENTATIVE, CONFIRMED or CANCELED"; + + } + + return 0; +} + +char* icalrestriction_must_be_cancel_if_present( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + /* This routine will not be called if prop == 0 */ + icalproperty_status stat = icalproperty_get_status(prop); + + if( stat != ICAL_STATUS_CANCELLED) + { + return "Failed iTIP restrictions for STATUS property. Value must be CANCELLED"; + + } + + + return 0; +} + +char* icalrestriction_must_be_canceled_no_attendee( + icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop) +{ + + /* Hack. see rfc2446, 3.2.5 CANCEL for porperty STATUS. I don't + understand the note */ + + return 0; +} +char* icalrestriction_must_be_recurring(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + /* Hack */ + return 0; +} +char* icalrestriction_must_have_duration(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + + if( !icalcomponent_get_first_property(comp,ICAL_DURATION_PROPERTY)){ + + return "Failed iTIP restrictions for STATUS property. This component must have a DURATION property"; + + } + + return 0; +} +char* icalrestriction_must_have_repeat(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + if( !icalcomponent_get_first_property(comp,ICAL_REPEAT_PROPERTY)){ + + return "Failed iTIP restrictions for STATUS property. This component must have a REPEAT property"; + + } + + return 0; +} +char* icalrestriction_must_if_tz_ref(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + + /* Hack */ + return 0; +} +char* icalrestriction_no_dtend(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + + if( !icalcomponent_get_first_property(comp,ICAL_DTEND_PROPERTY)){ + + return "Failed iTIP restrictions for STATUS property. The component must not have both DURATION and DTEND"; + + } + + return 0; +} +char* icalrestriction_no_duration(icalrestriction_property_record *rec, + icalcomponent* comp, + icalproperty* prop){ + + /* _no_dtend takes care of this one */ + return 0; +} + + +int icalrestriction_check_component(icalproperty_method method, + icalcomponent* comp) +{ + icalproperty_kind kind; + icalcomponent_kind comp_kind; + icalrestriction_kind restr; + icalrestriction_property_record *prop_record; + icalrestriction_component_record *comp_record; + char* funcr = 0; + icalproperty *prop; + + int count; + int compare; + int valid = 1; + + comp_kind = icalcomponent_isa(comp); + + /* Check all of the properties in this component */ + + for(kind = ICAL_ANY_PROPERTY+1; kind != ICAL_NO_PROPERTY; kind++){ + count = icalcomponent_count_properties(comp, kind); + + prop_record = icalrestriction_get_property_restriction(method, + comp_kind, + kind); + + restr = prop_record->restriction; + + if(restr == ICAL_RESTRICTION_ONEEXCLUSIVE || + restr == ICAL_RESTRICTION_ONEMUTUAL) { + + /* First treat is as a 0/1 restriction */ + restr = ICAL_RESTRICTION_ZEROORONE; + compare = icalrestriction_compare(restr,count); + + } else { + + compare = icalrestriction_compare(restr,count); + } + + assert(compare != -1); + + if (compare == 0){ + char temp[TMP_BUF_SIZE]; + + snprintf(temp, TMP_BUF_SIZE,"Failed iTIP restrictions for %s property. Expected %s instances of the property and got %d", + icalenum_property_kind_to_string(kind), + restr_string_map[restr], count); + + icalcomponent_add_property + (comp, + icalproperty_vanew_xlicerror( + temp, + icalparameter_new_xlicerrortype(ICAL_XLICERRORTYPE_INVALIDITIP), + 0)); + } + + + prop = icalcomponent_get_first_property(comp, kind); + + if (prop != 0 && prop_record->function !=0 ){ + funcr = prop_record->function(prop_record,comp,prop); + } + + if(funcr !=0){ + icalcomponent_add_property + (comp, + icalproperty_vanew_xlicerror( + funcr, + icalparameter_new_xlicerrortype( + ICAL_XLICERRORTYPE_INVALIDITIP), + 0)); + + compare = 0; + } + + valid = valid && compare; + } + + + + return valid; + + +} + +int icalrestriction_check(icalcomponent* outer_comp) +{ + icalcomponent_kind comp_kind; + icalproperty_method method; + icalcomponent* inner_comp; + icalproperty *method_prop; + int valid; + + icalerror_check_arg_rz( (outer_comp!=0), "outer comp"); + + + /* Get the Method value from the outer component */ + + comp_kind = icalcomponent_isa(outer_comp); + + if (comp_kind != ICAL_VCALENDAR_COMPONENT){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return 0; + } + + method_prop = icalcomponent_get_first_property(outer_comp, + ICAL_METHOD_PROPERTY); + + if (method_prop == 0){ + method = ICAL_METHOD_NONE; + } else { + method = icalproperty_get_method(method_prop); + } + + + /* Check the VCALENDAR wrapper */ + valid = icalrestriction_check_component(ICAL_METHOD_NONE,outer_comp); + + + /* Now check the inner components */ + + for(inner_comp= icalcomponent_get_first_component(outer_comp, + ICAL_ANY_COMPONENT); + inner_comp != 0; + inner_comp= icalcomponent_get_next_component(outer_comp, + ICAL_ANY_COMPONENT)){ + + valid = valid && icalrestriction_check_component(method,inner_comp); + + } + + + return valid; + +} + +icalrestriction_property_record* +icalrestriction_get_property_restriction(icalproperty_method method, + icalcomponent_kind component, + icalproperty_kind property) +{ + int i; + + for(i = 0; + icalrestriction_property_records[i].restriction != ICAL_RESTRICTION_NONE; + i++){ + + if (method == icalrestriction_property_records[i].method && + component == icalrestriction_property_records[i].component && + property == icalrestriction_property_records[i].property ){ + return &icalrestriction_property_records[i]; + } + } + + return &null_prop_record; +} + + +icalrestriction_component_record* +icalrestriction_get_component_restriction(icalproperty_method method, + icalcomponent_kind component, + icalcomponent_kind subcomponent) +{ + + int i; + + for(i = 0; + icalrestriction_component_records[i].restriction != ICAL_RESTRICTION_NONE; + i++){ + + if (method == icalrestriction_component_records[i].method && + component == icalrestriction_component_records[i].component && + subcomponent == icalrestriction_component_records[i].subcomponent ){ + return &icalrestriction_component_records[i]; + } + } + + return &null_comp_record; +} + diff --git a/libical/src/libical/icalrestriction.h b/libical/src/libical/icalrestriction.h new file mode 100644 index 0000000..409334c --- a/dev/null +++ b/libical/src/libical/icalrestriction.h @@ -0,0 +1,63 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalrestriction.h + CREATOR: eric 24 April 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalrestriction.h + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + +======================================================================*/ + +#include "icalproperty.h" +#include "icalcomponent.h" + +#ifndef ICALRESTRICTION_H +#define ICALRESTRICTION_H + +/* These must stay in this order for icalrestriction_compare to work */ +typedef enum icalrestriction_kind { + ICAL_RESTRICTION_NONE=0, /* 0 */ + ICAL_RESTRICTION_ZERO, /* 1 */ + ICAL_RESTRICTION_ONE, /* 2 */ + ICAL_RESTRICTION_ZEROPLUS, /* 3 */ + ICAL_RESTRICTION_ONEPLUS, /* 4 */ + ICAL_RESTRICTION_ZEROORONE, /* 5 */ + ICAL_RESTRICTION_ONEEXCLUSIVE, /* 6 */ + ICAL_RESTRICTION_ONEMUTUAL, /* 7 */ + ICAL_RESTRICTION_UNKNOWN /* 8 */ +} icalrestriction_kind; + +int +icalrestriction_compare(icalrestriction_kind restr, int count); + + +int +icalrestriction_is_parameter_allowed(icalproperty_kind property, + icalparameter_kind parameter); + +int icalrestriction_check(icalcomponent* comp); + + +#endif /* !ICALRESTRICTION_H */ + + + diff --git a/libical/src/libical/icaltime.c b/libical/src/libical/icaltime.c new file mode 100644 index 0000000..a04ca04 --- a/dev/null +++ b/libical/src/libical/icaltime.c @@ -0,0 +1,577 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icaltime.c + CREATOR: eric 02 June 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icaltime.h" +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +int snprintf(char *str, size_t n, char const *fmt, ...); + +#ifdef ICAL_NO_LIBICAL +#define icalerror_set_errno(x) +#define icalerror_check_arg_rv(x,y) +#define icalerror_check_arg_re(x,y,z) +#else +#include "icalerror.h" +#include "icalmemory.h" +#endif + + + + +struct icaltimetype +icaltime_from_timet(time_t tm, int is_date) +{ + struct icaltimetype tt = icaltime_null_time(); + struct tm t; + + t = *(gmtime(&tm)); + + if(is_date == 0){ + tt.second = t.tm_sec; + tt.minute = t.tm_min; + tt.hour = t.tm_hour; + } else { + tt.second = tt.minute =tt.hour = 0 ; + } + + tt.day = t.tm_mday; + tt.month = t.tm_mon + 1; + tt.year = t.tm_year+ 1900; + + tt.is_utc = 1; + tt.is_date = is_date; + + return tt; +} + +/* Structure used by set_tz to hold an old value of TZ, and the new + value, which is in memory we will have to free in unset_tz */ +struct set_tz_save {char* orig_tzid; char* new_env_str;}; + +/* Temporarily change the TZ environmental variable. */ +struct set_tz_save set_tz(const char* tzid) +{ + + char *orig_tzid = 0; + char *new_env_str; + struct set_tz_save savetz; + size_t tmp_sz; + + savetz.orig_tzid = 0; + savetz.new_env_str = 0; + + if(getenv("TZ") != 0){ + orig_tzid = (char*)icalmemory_strdup(getenv("TZ")); + + if(orig_tzid == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return savetz; + } + } + + tmp_sz =strlen(tzid)+4; + new_env_str = (char*)malloc(tmp_sz); + + if(new_env_str == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return savetz; + } + + /* Copy the TZid into a string with the form that putenv expects. */ + strcpy(new_env_str,"TZ="); + strcpy(new_env_str+3,tzid); + + putenv(new_env_str); + + /* Old value of TZ and the string we will have to free later */ + savetz.orig_tzid = orig_tzid; + savetz.new_env_str = new_env_str; + return savetz; +} + +void unset_tz(struct set_tz_save savetz) +{ + /* restore the original TZ environment */ + + char* orig_tzid = savetz.orig_tzid; + + if(orig_tzid!=0){ + size_t tmp_sz =strlen(orig_tzid)+4; + char* orig_env_str = (char*)icalmemory_tmp_buffer(tmp_sz); + + if(orig_env_str == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return; + } + + strcpy(orig_env_str,"TZ="); + strcpy(orig_env_str+3,orig_tzid); +#ifndef _WIN32 + setenv("TZ", savetz.orig_tzid,1 ); +#else + putenv("TZ=MEZ");//, savetz.orig_tzid ); +#endif + free(orig_tzid); + } else { +#ifdef __FreeBSD__ + unsetenv("TZ"); +#else + putenv("TZ"); /* Delete from environment */ +#endif + } + + if(savetz.new_env_str != 0){ + free(savetz.new_env_str); + } +} + + +time_t icaltime_as_timet(struct icaltimetype tt) +{ + struct tm stm; + time_t t; + + memset(&stm,0,sizeof( struct tm)); + + if(icaltime_is_null_time(tt)) { + return 0; + } + + stm.tm_sec = tt.second; + stm.tm_min = tt.minute; + stm.tm_hour = tt.hour; + stm.tm_mday = tt.day; + stm.tm_mon = tt.month-1; + stm.tm_year = tt.year-1900; + stm.tm_isdst = -1; + + if(tt.is_utc == 1 || tt.is_date == 1){ + struct set_tz_save old_tz = set_tz("UTC"); + t = mktime(&stm); + unset_tz(old_tz); + } else { + t = mktime(&stm); + } + + return t; + +} + +char* icaltime_as_ical_string(struct icaltimetype tt) +{ + size_t size = 17; + char* buf = icalmemory_new_buffer(size); + + if(tt.is_date){ + snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day); + } else { + char* fmt; + if(tt.is_utc){ + fmt = "%04d%02d%02dT%02d%02d%02dZ"; + } else { + fmt = "%04d%02d%02dT%02d%02d%02d"; + } + snprintf(buf, size,fmt,tt.year,tt.month,tt.day, + tt.hour,tt.minute,tt.second); + } + + icalmemory_add_tmp_buffer(buf); + + return buf; + +} + + +/* convert tt, of timezone tzid, into a utc time */ +struct icaltimetype icaltime_as_utc(struct icaltimetype tt,const char* tzid) +{ + int tzid_offset; + + if(tt.is_utc == 1 || tt.is_date == 1){ + return tt; + } + + tzid_offset = icaltime_utc_offset(tt,tzid); + + tt.second -= tzid_offset; + + tt.is_utc = 1; + + return icaltime_normalize(tt); +} + +/* convert tt, a time in UTC, into a time in timezone tzid */ +struct icaltimetype icaltime_as_zone(struct icaltimetype tt,const char* tzid) +{ + int tzid_offset; + + tzid_offset = icaltime_utc_offset(tt,tzid); + + tt.second += tzid_offset; + + tt.is_utc = 0; + + return icaltime_normalize(tt); + +} + + +/* Return the offset of the named zone as seconds. tt is a time + indicating the date for which you want the offset */ +int icaltime_utc_offset(struct icaltimetype ictt, const char* tzid) +{ + + time_t tt = icaltime_as_timet(ictt); + time_t offset_tt; + struct tm gtm; + struct set_tz_save old_tz; + + if(tzid != 0){ + old_tz = set_tz(tzid); + } + + /* Mis-interpret a UTC broken out time as local time */ + gtm = *(gmtime(&tt)); + gtm.tm_isdst = localtime(&tt)->tm_isdst; + offset_tt = mktime(>m); + + if(tzid != 0){ + unset_tz(old_tz); + } + + return tt-offset_tt; +} + + + +/* Normalize by converting from localtime to utc and back to local + time. This uses localtime because localtime and mktime are inverses + of each other */ + +struct icaltimetype icaltime_normalize(struct icaltimetype tt) +{ + struct tm stm; + time_t tut; + + memset(&stm,0,sizeof( struct tm)); + + stm.tm_sec = tt.second; + stm.tm_min = tt.minute; + stm.tm_hour = tt.hour; + stm.tm_mday = tt.day; + stm.tm_mon = tt.month-1; + stm.tm_year = tt.year-1900; + stm.tm_isdst = -1; /* prevents mktime from changing hour based on + daylight savings */ + + tut = mktime(&stm); + + stm = *(localtime(&tut)); + + tt.second = stm.tm_sec; + tt.minute = stm.tm_min; + tt.hour = stm.tm_hour; + tt.day = stm.tm_mday; + tt.month = stm.tm_mon +1; + tt.year = stm.tm_year+1900; + + return tt; +} + + +#ifndef ICAL_NO_LIBICAL +#include "icalvalue.h" + +struct icaltimetype icaltime_from_string(const char* str) +{ + struct icaltimetype tt = icaltime_null_time(); + int size; + + icalerror_check_arg_re(str!=0,"str",icaltime_null_time()); + + size = strlen(str); + + if(size == 15) { /* floating time */ + tt.is_utc = 0; + tt.is_date = 0; + } else if (size == 16) { /* UTC time, ends in 'Z'*/ + tt.is_utc = 1; + tt.is_date = 0; + + if(str[15] != 'Z'){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return icaltime_null_time(); + } + + } else if (size == 8) { /* A DATE */ + tt.is_utc = 1; + tt.is_date = 1; + } else { /* error */ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return icaltime_null_time(); + } + + if(tt.is_date == 1){ + sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day); + } else { + char tsep; + sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day, + &tsep,&tt.hour,&tt.minute,&tt.second); + + if(tsep != 'T'){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return icaltime_null_time(); + } + + } + + return tt; +} +#endif + +char ctime_str[20]; +char* icaltime_as_ctime(struct icaltimetype t) +{ + time_t tt; + + tt = icaltime_as_timet(t); + sprintf(ctime_str,"%s",ctime(&tt)); + + ctime_str[strlen(ctime_str)-1] = 0; + + return ctime_str; +} + + +short days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; + +short icaltime_days_in_month(short month,short year) +{ + + int is_leap =0; + int days = days_in_month[month]; + + assert(month > 0); + assert(month <= 12); + + if( (year % 4 == 0 && year % 100 != 0) || + year % 400 == 0){ + is_leap =1; + } + + if( month == 2){ + days += is_leap; + } + + return days; +} + +/* 1-> Sunday, 7->Saturday */ +short icaltime_day_of_week(struct icaltimetype t){ + + time_t tt = icaltime_as_timet(t); + struct tm *tm; + + if(t.is_utc == 1 || t.is_date == 1){ + tm = gmtime(&tt); + } else { + tm = localtime(&tt); + } + + return tm->tm_wday+1; +} + +/* Day of the year that the first day of the week (Sunday) is on */ +short icaltime_start_doy_of_week(struct icaltimetype t){ + time_t tt = icaltime_as_timet(t); + time_t start_tt; + struct tm *stm; + int syear; + + stm = gmtime(&tt); + syear = stm->tm_year; + + start_tt = tt - stm->tm_wday*(60*60*24); + + stm = gmtime(&start_tt); + + if(syear == stm->tm_year){ + return stm->tm_yday+1; + } else { + /* return negative to indicate that start of week is in + previous year. */ + int is_leap = 0; + int year = stm->tm_year; + + if( (year % 4 == 0 && year % 100 != 0) || + year % 400 == 0){ + is_leap =1; + } + + return (stm->tm_yday+1)-(365+is_leap); + } + +} + +short icaltime_week_number(struct icaltimetype ictt) +{ + char str[5]; + time_t t = icaltime_as_timet(ictt); + int week_no; + + strftime(str,5,"%V", gmtime(&t)); + + week_no = atoi(str); + + return week_no; + +} + + +short icaltime_day_of_year(struct icaltimetype t){ + time_t tt; + struct tm *stm; + struct set_tz_save old_tz; + + tt = icaltime_as_timet(t); + + old_tz = set_tz("UTC"); + stm = localtime(&tt); + unset_tz(old_tz); + + return stm->tm_yday+1; + +} + +/* Jan 1 is day #1, not 0 */ +struct icaltimetype icaltime_from_day_of_year(short doy, short year) +{ + struct tm stm; + time_t tt; + struct set_tz_save old_tz; + + /* Get the time of january 1 of this year*/ + memset(&stm,0,sizeof(struct tm)); + stm.tm_year = year-1900; + stm.tm_mday = 1; + + old_tz = set_tz("UTC"); + tt = mktime(&stm); + unset_tz(old_tz); + + + /* Now add in the days */ + + doy--; + tt += doy *60*60*24; + + return icaltime_from_timet(tt, 1); +} + +struct icaltimetype icaltime_null_time() +{ + struct icaltimetype t; + memset(&t,0,sizeof(struct icaltimetype)); + + return t; +} + + +int icaltime_is_valid_time(struct icaltimetype t){ + if(t.is_utc > 1 || t.is_utc < 0 || + t.year < 0 || t.year > 3000 || + t.is_date > 1 || t.is_date < 0){ + return 0; + } else { + return 1; + } + +} + +int icaltime_is_null_time(struct icaltimetype t) +{ + if (t.second +t.minute+t.hour+t.day+t.month+t.year == 0){ + return 1; + } + + return 0; + +} + +int icaltime_compare(struct icaltimetype a,struct icaltimetype b) +{ + time_t t1 = icaltime_as_timet(a); + time_t t2 = icaltime_as_timet(b); + + if (t1 > t2) { + return 1; + } else if (t1 < t2) { + return -1; + } else { + return 0; + } + +} + +int +icaltime_compare_date_only (struct icaltimetype a, struct icaltimetype b) +{ + time_t t1; + time_t t2; + + if (a.year == b.year && a.month == b.month && a.day == b.day) + return 0; + + t1 = icaltime_as_timet (a); + t2 = icaltime_as_timet (b); + + if (t1 > t2) + return 1; + else if (t1 < t2) + return -1; + else { + /* not reached */ + assert (0); + return 0; + } +} + + +/* These are defined in icalduration.c: +struct icaltimetype icaltime_add(struct icaltimetype t, + struct icaldurationtype d) +struct icaldurationtype icaltime_subtract(struct icaltimetype t1, + struct icaltimetype t2) +*/ + diff --git a/libical/src/libical/icaltime.h b/libical/src/libical/icaltime.h new file mode 100644 index 0000000..0f0379b --- a/dev/null +++ b/libical/src/libical/icaltime.h @@ -0,0 +1,145 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icaltime.h + CREATOR: eric 02 June 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALTIME_H +#define ICALTIME_H + +#include <time.h> + +/* icaltime_span is returned by icalcomponent_get_span() */ +struct icaltime_span { + time_t start; /* in UTC */ + time_t end; /* in UTC */ + int is_busy; /* 1->busy time, 0-> free time */ +}; + + +struct icaltimetype +{ + int year; + int month; + int day; + int hour; + int minute; + int second; + + int is_utc; /* 1-> time is in UTC timezone */ + + int is_date; /* 1 -> interpret this as date. */ + + const char* zone; /*Ptr to Olsen placename. Libical does not own mem*/ +}; + +/* Convert seconds past UNIX epoch to a timetype*/ +struct icaltimetype icaltime_from_timet(time_t v, int is_date); + +/* Return the time as seconds past the UNIX epoch */ +time_t icaltime_as_timet(struct icaltimetype); + +/* Return a string represention of the time, in RFC2445 format. The + string is owned by libical */ +char* icaltime_as_ical_string(struct icaltimetype tt); + +/* Like icaltime_from_timet(), except that the input may be in seconds + past the epoch in floating time. This routine is deprecated */ +struct icaltimetype icaltime_from_int(int v, int is_date, int is_utc); + +/* Like icaltime_as_timet, but in a floating epoch. This routine is deprecated */ +int icaltime_as_int(struct icaltimetype); + +/* create a time from an ISO format string */ +struct icaltimetype icaltime_from_string(const char* str); + +/* Routines for handling timezones */ +/* Return the offset of the named zone as seconds. tt is a time + indicating the date for which you want the offset */ +int icaltime_utc_offset(struct icaltimetype tt, const char* tzid); + +/* convert tt, of timezone tzid, into a utc time. Does nothing if the + time is already UTC. */ +struct icaltimetype icaltime_as_utc(struct icaltimetype tt, + const char* tzid); + +/* convert tt, a time in UTC, into a time in timezone tzid */ +struct icaltimetype icaltime_as_zone(struct icaltimetype tt, + const char* tzid); + +/* Return a null time, which indicates no time has been set. This time represent the beginning of the epoch */ +struct icaltimetype icaltime_null_time(void); + +/* Return true of the time is null. */ +int icaltime_is_null_time(struct icaltimetype t); + +/* Returns false if the time is clearly invalid, but is not null. This + is usually the result of creating a new time type buy not clearing + it, or setting one of the flags to an illegal value. */ +int icaltime_is_valid_time(struct icaltimetype t); + +/* Reset all of the time components to be in their normal ranges. For + instance, given a time with minutes=70, the minutes will be reduces + to 10, and the hour incremented. This allows the caller to do + arithmetic on times without worrying about overflow or + underflow. */ +struct icaltimetype icaltime_normalize(struct icaltimetype t); + +/* Return the day of the year of the given time */ +short icaltime_day_of_year(struct icaltimetype t); + +/* Create a new time, given a day of year and a year. */ +struct icaltimetype icaltime_from_day_of_year(short doy, short year); + +/* Return the day of the week of the given time. Sunday is 1 */ +short icaltime_day_of_week(struct icaltimetype t); + +/* Return the day of the year for the Sunday of the week that the + given time is within. */ +short icaltime_start_doy_of_week(struct icaltimetype t); + +/* Return a string with the time represented in the same format as ctime(). THe string is owned by libical */ +char* icaltime_as_ctime(struct icaltimetype); + +/* Return the week number for the week the given time is within */ +short icaltime_week_number(struct icaltimetype t); + +/* Create a new time from a weeknumber and a year. */ +struct icaltimetype icaltime_from_week_number(short week_number, short year); + +/* Return -1, 0, or 1 to indicate that a<b, a==b or a>b */ +int icaltime_compare(struct icaltimetype a,struct icaltimetype b); + +/* like icaltime_compare, but only use the date parts. */ +int icaltime_compare_date_only(struct icaltimetype a, struct icaltimetype b); + +/* Return the number of days in the given month */ +short icaltime_days_in_month(short month,short year); + + +#endif /* !ICALTIME_H */ + + + diff --git a/libical/src/libical/icaltypes.c b/libical/src/libical/icaltypes.c new file mode 100644 index 0000000..8c67deb --- a/dev/null +++ b/libical/src/libical/icaltypes.c @@ -0,0 +1,285 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icaltypes.c + CREATOR: eric 16 May 1999 + + $Id$ + $Locker$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icaltypes.c + + ======================================================================*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icaltypes.h" +#include "icalerror.h" +#include "icalmemory.h" +#include <stdlib.h> /* for malloc and abs() */ +#include <errno.h> /* for errno */ +#include <string.h> /* for icalmemory_strdup */ +#include <assert.h> + +int snprintf(char *str, size_t n, char const *fmt, ...); + +#define TEMP_MAX 1024 + +void* +icalattachtype_get_data (struct icalattachtype* type); + +struct icalattachtype* +icalattachtype_new() +{ + struct icalattachtype* v; + + if ( ( v = (struct icalattachtype*) + malloc(sizeof(struct icalattachtype))) == 0) { + errno = ENOMEM; + return 0; + } + + v->refcount = 1; + + v->binary = 0; + v->owns_binary = 0; + v->base64 = 0; + //fprintf(stderr,"setting base 64 to 0 \n"); + + v->owns_base64 = 0; + + v->url = 0; + + return v; +} + + +void +icalattachtype_free(struct icalattachtype* v) +{ + icalerror_check_arg( (v!=0),"v"); + + v->refcount--; + + if (v->refcount <= 0){ + + if (v->base64 != 0 && v->owns_base64 != 0){ + int val = v->base64 ; + if ( val < 255 ) { + fprintf(stderr,"Possible error in attachment processing (%d)\nPocssible solution: Remove attachment from file.\n",val ); + } + free(v->base64); + } + + if (v->binary != 0 && v->owns_binary != 0){ + free(v->binary); + } + + if (v->url != 0){ + free(v->url); + } + + free(v); + } +} + +void icalattachtype_add_reference(struct icalattachtype* v) +{ + icalerror_check_arg( (v!=0),"v"); + v->refcount++; +} + +void icalattachtype_set_url(struct icalattachtype* v, char* url) +{ + icalerror_check_arg( (v!=0),"v"); + + if (v->url != 0){ + free (v->url); + } + + v->url = icalmemory_strdup(url); + + /* HACK This routine should do something if icalmemory_strdup returns NULL */ + +} + +char* icalattachtype_get_url(struct icalattachtype* v) +{ + icalerror_check_arg( (v!=0),"v"); + return v->url; +} + +void icalattachtype_set_base64(struct icalattachtype* v, char* base64, + int owns) +{ + //fprintf(stderr,"1setbase64 %d \n", base64 ); + icalerror_check_arg( (v!=0),"v"); + //fprintf(stderr,"setbase64 %d \n", base64 ); + v->base64 = base64; + v->owns_base64 = !(owns != 0 ); + +} + +char* icalattachtype_get_base64(struct icalattachtype* v) +{ + icalerror_check_arg( (v!=0),"v"); + return v->base64; +} + +void icalattachtype_set_binary(struct icalattachtype* v, char* binary, + int owns) +{ + icalerror_check_arg( (v!=0),"v"); + + v->binary = binary; + v->owns_binary = !(owns != 0 ); + +} + +void* icalattachtype_get_binary(struct icalattachtype* v) +{ + icalerror_check_arg( (v!=0),"v"); + return v->binary; +} + +int icaltriggertype_is_null_trigger(struct icaltriggertype tr) +{ + if(icaltime_is_null_time(tr.time) && + icaldurationtype_is_null_duration(tr.duration)){ + return 1; + } + + return 0; +} + +struct icaltriggertype icaltriggertype_from_string(const char* str) +{ + + + struct icaltriggertype tr, null_tr; + icalerrorstate es; + icalerrorenum e; + + tr.time= icaltime_null_time(); + tr.duration = icaldurationtype_from_int(0); + + null_tr = tr; + + if(str == 0) goto error; + + /* Surpress errors so a failure in icaltime_from_string() does not cause an abort */ + es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR); + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL); + e = icalerrno; + icalerror_set_errno(ICAL_NO_ERROR); + + tr.time = icaltime_from_string(str); + + if (icaltime_is_null_time(tr.time)){ + + tr.duration = icaldurationtype_from_string(str); + + if(icaldurationtype_as_int(tr.duration) == 0) goto error; + } + + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es); + icalerror_set_errno(e); + return tr; + + error: + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es); + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return null_tr; + +} + + +struct icalreqstattype icalreqstattype_from_string(const char* str) +{ + const char *p1,*p2; + struct icalreqstattype stat; + int major, minor; + + icalerror_check_arg((str != 0),"str"); + + stat.code = ICAL_UNKNOWN_STATUS; + stat.debug = 0; + stat.desc = 0; + + /* Get the status numbers */ + + sscanf(str, "%d.%d",&major, &minor); + + if (major <= 0 || minor < 0){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return stat; + } + + stat.code = icalenum_num_to_reqstat(major, minor); + + if (stat.code == ICAL_UNKNOWN_STATUS){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return stat; + } + + + p1 = strchr(str,';'); + + if (p1 == 0){ +/* icalerror_set_errno(ICAL_BADARG_ERROR);*/ + return stat; + } + + /* Just ignore the second clause; it will be taken from inside the library + */ + + + + p2 = strchr(p1+1,';'); + if (p2 != 0 && *p2 != 0){ + stat.debug = p2+1; + } + + return stat; + +} + +const char* icalreqstattype_as_string(struct icalreqstattype stat) +{ + char *temp; + + temp = (char*)icalmemory_tmp_buffer(TEMP_MAX); + + icalerror_check_arg_rz((stat.code != ICAL_UNKNOWN_STATUS),"Status"); + + if (stat.desc == 0){ + stat.desc = icalenum_reqstat_desc(stat.code); + } + + if(stat.debug != 0){ + snprintf(temp,TEMP_MAX,"%d.%d;%s;%s", icalenum_reqstat_major(stat.code), + icalenum_reqstat_minor(stat.code), + stat.desc, stat.debug); + + } else { + snprintf(temp,TEMP_MAX,"%d.%d;%s", icalenum_reqstat_major(stat.code), + icalenum_reqstat_minor(stat.code), + stat.desc); + } + + return temp; +} diff --git a/libical/src/libical/icaltypes.h b/libical/src/libical/icaltypes.h new file mode 100644 index 0000000..d61b9f3 --- a/dev/null +++ b/libical/src/libical/icaltypes.h @@ -0,0 +1,138 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icaltypes.h + CREATOR: eric 20 March 1999 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icaltypes.h + +======================================================================*/ + +#ifndef ICALTYPES_H +#define ICALTYPES_H + +#include <time.h> +#include "icalenums.h" +#include "icaltime.h" +#include "icalduration.h" +#include "icalperiod.h" + + +/* This type type should probably be an opaque type... */ +struct icalattachtype +{ + void* binary; + int owns_binary; + + char* base64; + int owns_base64; + + char* url; + + int refcount; + +}; + +/* converts base64 to binary, fetches url and stores as binary, or + just returns data */ + +struct icalattachtype* icalattachtype_new(void); +void icalattachtype_add_reference(struct icalattachtype* v); +void icalattachtype_free(struct icalattachtype* v); + +void icalattachtype_set_url(struct icalattachtype* v, char* url); +char* icalattachtype_get_url(struct icalattachtype* v); + +void icalattachtype_set_base64(struct icalattachtype* v, char* base64, + int owns); +char* icalattachtype_get_base64(struct icalattachtype* v); + +void icalattachtype_set_binary(struct icalattachtype* v, char* binary, + int owns); +void* icalattachtype_get_binary(struct icalattachtype* v); + +struct icalgeotype +{ + float lat; + float lon; +}; + + +struct icaldatetimeperiodtype +{ + struct icaltimetype time; + struct icalperiodtype period; +}; + + +struct icaltriggertype +{ + struct icaltimetype time; + struct icaldurationtype duration; +}; + +struct icaltriggertype icaltriggertype_from_string(const char* str); + +int icaltriggertype_is_null_trigger(struct icaltriggertype tr); + +/* struct icalreqstattype. This struct contains two string pointers, +but don't try to free either of them. The "desc" string is a pointer +to a static table inside the library. Don't try to free it. The +"debug" string is a pointer into the string that the called passed +into to icalreqstattype_from_string. Don't try to free it either, and +don't use it after the original string has been freed. + +BTW, you would get that original string from +*icalproperty_get_requeststatus() or icalvalue_get_text(), when +operating on a the value of a request_status property. */ + +struct icalreqstattype { + + icalrequeststatus code; + const char* desc; + const char* debug; +}; + +struct icalreqstattype icalreqstattype_from_string(const char* str); +const char* icalreqstattype_as_string(struct icalreqstattype); + + + +struct icaltimezonephase { + const char* tzname; + int is_stdandard; /* 1 = standard tme, 0 = daylight savings time */ + struct icaltimetype dtstart; + int offsetto; + int tzoffsetfrom; + const char* comment; + struct icaldatetimeperiodtype rdate; + const char* rrule; +}; + + +struct icaltimezonetype { + const char* tzid; + struct icaltimetype last_mod; + const char* tzurl; + + /* Array of phases. The end of the array is a phase with tzname == 0 */ + struct icaltimezonephase *phases; +}; + +void icaltimezonetype_free(struct icaltimezonetype tzt); + + +#endif /* !ICALTYPES_H */ diff --git a/libical/src/libical/icalvalue.c b/libical/src/libical/icalvalue.c new file mode 100644 index 0000000..eb5476e --- a/dev/null +++ b/libical/src/libical/icalvalue.c @@ -0,0 +1,1215 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.c + CREATOR: eric 02 May 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalvalue.c + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + +======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalerror.h" +#include "icalmemory.h" +#include "icalparser.h" +#include "icalenums.h" +#include "icalvalueimpl.h" + +#include <stdlib.h> /* for malloc */ +#include <stdio.h> /* for sprintf */ +#include <string.h> /* For memset, others */ +#include <stddef.h> /* For offsetof() macro */ +#include <errno.h> +#include <time.h> /* for mktime */ +#include <stdlib.h> /* for atoi and atof */ +#include <limits.h> /* for SHRT_MAX */ + +int snprintf(char *str, size_t n, char const *fmt, ...); + +#if _MAC_OS_ +#include "icalmemory_strdup.h" +#endif + +#define TMP_BUF_SIZE 1024 + +void print_datetime_to_string(char* str, struct icaltimetype *data); +void print_date_to_string(char* str, struct icaltimetype *data); +void print_time_to_string(char* str, struct icaltimetype *data); +void print_recur_to_string(char* str, struct icaltimetype *data); + + +struct icalvalue_impl* icalvalue_new_impl(icalvalue_kind kind){ + + struct icalvalue_impl* v; + + if ( ( v = (struct icalvalue_impl*) + malloc(sizeof(struct icalvalue_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + strcpy(v->id,"val"); + + v->kind = kind; + v->size = 0; + v->parent = 0; + v->x_value = 0; + memset(&(v->data),0,sizeof(v->data)); + + return v; + +} + + + +icalvalue* +icalvalue_new (icalvalue_kind kind) +{ + return (icalvalue*)icalvalue_new_impl(kind); +} + +icalvalue* icalvalue_new_clone(icalvalue* value){ + + struct icalvalue_impl* new; + struct icalvalue_impl* old = (struct icalvalue_impl*)value; + + new = icalvalue_new_impl(old->kind); + + if (new == 0){ + return 0; + } + + + strcpy(new->id, old->id); + new->kind = old->kind; + new->size = old->size; + + switch (new->kind){ + + /* The contents of the attach value may or may not be owned by the + * library. */ + case ICAL_ATTACH_VALUE: + case ICAL_BINARY_VALUE: + { + /* HACK ugh. I don't feel like impleenting this */ + } + + case ICAL_STRING_VALUE: + case ICAL_TEXT_VALUE: + case ICAL_CALADDRESS_VALUE: + case ICAL_URI_VALUE: + { + if (old->data.v_string != 0) { + new->data.v_string=icalmemory_strdup(old->data.v_string); + + if ( new->data.v_string == 0 ) { + return 0; + } + + } + break; + } + case ICAL_RECUR_VALUE: + { + if(old->data.v_recur != 0){ + new->data.v_recur = malloc(sizeof(struct icalrecurrencetype)); + + if(new->data.v_recur == 0){ + return 0; + } + + memcpy( new->data.v_recur, old->data.v_recur, + sizeof(struct icalrecurrencetype)); + } + break; + } + + default: + { + /* all of the other types are stored as values, not + pointers, so we can just copy the whole structure. */ + + new->data = old->data; + } + } + + return new; +} + +char* icalmemory_strdup_and_dequote(const char* str) +{ + const char* p; + char* out = (char*)malloc(sizeof(char) * strlen(str) +1); + char* pout; + + if (out == 0){ + return 0; + } + + pout = out; + + for (p = str; *p!=0; p++){ + + if( *p == '\\') + { + p++; + switch(*p){ + case 0: + { + *pout = '\0'; + break; + + } + case 'n': + { + *pout = '\n'; + break; + } + case 'N': + { + *pout = '\n'; + break; + } + case '\\': + case ',': + case ';': + { + *pout = *p; + break; + } + default: + { + *pout = ' '; + } + } + } else { + *pout = *p; + } + + pout++; + + } + + *pout = '\0'; + + return out; +} + +icalvalue* icalvalue_new_enum(icalvalue_kind kind, int x_type, const char* str) +{ + int e = icalproperty_string_to_enum(str); + struct icalvalue_impl *value; + + if(e != 0 && icalproperty_enum_belongs_to_property( + icalproperty_value_kind_to_kind(kind),e)) { + + value = icalvalue_new_impl(kind); + value->data.v_enum = e; + } else { + /* Make it an X value */ + value = icalvalue_new_impl(kind); + value->data.v_enum = x_type; + icalvalue_set_x(value,str); + } + + return value; +} + + +icalvalue* icalvalue_new_from_string_with_error(icalvalue_kind kind,const char* str,icalproperty** error) +{ + + struct icalvalue_impl *value = 0; + struct icalattachtype *attach = 0; + + icalerror_check_arg_rz(str!=0,"str"); + + if (error != 0){ + *error = 0; + } + + switch (kind){ + + case ICAL_ATTACH_VALUE: + attach = icalattachtype_new(); + value = icalvalue_new_attach( attach ); + icalattachtype_free( attach ); + icalattachtype_set_url( value->data.v_attach, str ); + break; + case ICAL_BINARY_VALUE: + case ICAL_BOOLEAN_VALUE: + { + /* HACK */ + value = 0; + + if (error != 0){ + char temp[TMP_BUF_SIZE]; + sprintf(temp,"%s Values are not implemented", + icalparameter_kind_to_string(kind)); + *error = icalproperty_vanew_xlicerror( + temp, + icalparameter_new_xlicerrortype( + ICAL_XLICERRORTYPE_VALUEPARSEERROR), + 0); + } + break; + } + + + case ICAL_TRANSP_VALUE: + value = icalvalue_new_enum(kind, ICAL_TRANSP_X,str); + break; + case ICAL_METHOD_VALUE: + value = icalvalue_new_enum(kind, ICAL_METHOD_X,str); + break; + case ICAL_STATUS_VALUE: + value = icalvalue_new_enum(kind, ICAL_STATUS_X,str); + break; + case ICAL_ACTION_VALUE: + value = icalvalue_new_enum(kind, ICAL_ACTION_X,str); + break; + case ICAL_CLASS_VALUE: + value = icalvalue_new_enum(kind, ICAL_CLASS_X,str); + break; + + + case ICAL_INTEGER_VALUE: + { + value = icalvalue_new_integer(atoi(str)); + break; + } + + case ICAL_FLOAT_VALUE: + { + value = icalvalue_new_float((float )atof(str)); + break; + } + + case ICAL_UTCOFFSET_VALUE: + { + value = icalparser_parse_value(kind,str,(icalcomponent*)0); + break; + } + + case ICAL_TEXT_VALUE: + { + char* dequoted_str = icalmemory_strdup_and_dequote(str); + value = icalvalue_new_text(dequoted_str); + free(dequoted_str); + break; + } + + + case ICAL_STRING_VALUE: + { + value = icalvalue_new_string(str); + break; + } + + case ICAL_CALADDRESS_VALUE: + { + value = icalvalue_new_caladdress(str); + break; + } + + case ICAL_URI_VALUE: + { + value = icalvalue_new_uri(str); + break; + } + + + case ICAL_GEO_VALUE: + { + value = 0; + /* HACK */ + + if (error != 0){ + char temp[TMP_BUF_SIZE]; + sprintf(temp,"GEO Values are not implemented"); + *error = icalproperty_vanew_xlicerror( + temp, + icalparameter_new_xlicerrortype( + ICAL_XLICERRORTYPE_VALUEPARSEERROR), + 0); + } + + /*icalerror_warn("Parsing GEO properties is unimplmeneted");*/ + + break; + } + + case ICAL_RECUR_VALUE: + { + struct icalrecurrencetype rt; + rt = icalrecurrencetype_from_string(str); + if(rt.freq != ICAL_NO_RECURRENCE){ + value = icalvalue_new_recur(rt); + } + break; + } + + case ICAL_DATE_VALUE: + case ICAL_DATETIME_VALUE: + { + struct icaltimetype tt; + + tt = icaltime_from_string(str); + if(!icaltime_is_null_time(tt)){ + value = icalvalue_new_impl(kind); + value->data.v_time = tt; + + icalvalue_reset_kind(value); + } + break; + } + + case ICAL_DATETIMEPERIOD_VALUE: + { + struct icaltimetype tt; + struct icalperiodtype p; + tt = icaltime_from_string(str); + p = icalperiodtype_from_string(str); + + if(!icaltime_is_null_time(tt)){ + value = icalvalue_new_datetime(tt); + } else if (!icalperiodtype_is_null_period(p)){ + value = icalvalue_new_period(p); + } + + break; + } + + case ICAL_DURATION_VALUE: + { + struct icaldurationtype dur = icaldurationtype_from_string(str); + + if(icaldurationtype_is_null_duration(dur)){ + value = 0; + } else { + value = icalvalue_new_duration(dur); + } + + break; + } + + case ICAL_PERIOD_VALUE: + { + struct icalperiodtype p; + p = icalperiodtype_from_string(str); + + if(!icalperiodtype_is_null_period(p)){ + value = icalvalue_new_period(p); + } + break; + } + + case ICAL_TRIGGER_VALUE: + { + struct icaltriggertype tr = icaltriggertype_from_string(str); + if (!icaltriggertype_is_null_trigger(tr)){ + value = icalvalue_new_trigger(tr); + } + break; + } + + case ICAL_REQUESTSTATUS_VALUE: + { + struct icalreqstattype rst = icalreqstattype_from_string(str); + if(rst.code != ICAL_UNKNOWN_STATUS){ + value = icalvalue_new_requeststatus(rst); + } + break; + + } + default: + { + + if (error != 0 ){ + char temp[TMP_BUF_SIZE]; + + snprintf(temp,TMP_BUF_SIZE,"Unknown type for \'%s\'",str); + + *error = icalproperty_vanew_xlicerror( + temp, + icalparameter_new_xlicerrortype( + ICAL_XLICERRORTYPE_VALUEPARSEERROR), + 0); + } + + icalerror_warn("icalvalue_new_from_string got an unknown value type"); + value=0; + } + } + + + if (error != 0 && *error == 0 && value == 0){ + char temp[TMP_BUF_SIZE]; + + snprintf(temp,TMP_BUF_SIZE,"Failed to parse value: \'%s\'",str); + + *error = icalproperty_vanew_xlicerror( + temp, + icalparameter_new_xlicerrortype( + ICAL_XLICERRORTYPE_VALUEPARSEERROR), + 0); + } + + + return value; + +} + +icalvalue* icalvalue_new_from_string(icalvalue_kind kind,const char* str) +{ + return icalvalue_new_from_string_with_error(kind,str,(icalproperty*)0); +} + + + +void +icalvalue_free (icalvalue* value) +{ + struct icalvalue_impl* v = (struct icalvalue_impl*)value; + + icalerror_check_arg_rv((value != 0),"value"); + +#ifdef ICAL_FREE_ON_LIST_IS_ERROR + icalerror_assert( (v->parent ==0),"This value is still attached to a property"); + +#else + if(v->parent !=0){ + return; + } +#endif + + if(v->x_value != 0){ + free(v->x_value); + } + + switch (v->kind){ + case ICAL_ATTACH_VALUE: + icalattachtype_free( v->data.v_attach ); + break; + case ICAL_BINARY_VALUE: { + /* HACK ugh. This will be tough to implement */ + } + case ICAL_TEXT_VALUE: + case ICAL_CALADDRESS_VALUE: + case ICAL_URI_VALUE: + { + if (v->data.v_string != 0) { + free((void*)v->data.v_string); + v->data.v_string = 0; + } + break; + } + case ICAL_RECUR_VALUE: + { + if(v->data.v_recur != 0){ + free((void*)v->data.v_recur); + v->data.v_recur = 0; + } + break; + } + + default: + { + /* Nothing to do */ + } + } + + v->kind = ICAL_NO_VALUE; + v->size = 0; + v->parent = 0; + memset(&(v->data),0,sizeof(v->data)); + v->id[0] = 'X'; + free(v); +} + +int +icalvalue_is_valid (icalvalue* value) +{ + /*struct icalvalue_impl* v = (struct icalvalue_impl*)value;*/ + + if(value == 0){ + return 0; + } + + return 1; +} + +char* icalvalue_binary_as_ical_string(icalvalue* value) { + + const char* data; + char* str; + icalerror_check_arg_rz( (value!=0),"value"); + + data = icalvalue_get_binary(value); + + str = (char*)icalmemory_tmp_buffer(60); + sprintf(str,"icalvalue_binary_as_ical_string is not implemented yet"); + + return str; +} + +#ifndef _WIN32 +#define MAX_INT_DIGITS 12 /* Enough for 2^32 + sign*/ +char* icalvalue_int_as_ical_string(icalvalue* value) { + + int data; + char* str = (char*)icalmemory_tmp_buffer(MAX_INT_DIGITS); + + icalerror_check_arg_rz( (value!=0),"value"); + + data = icalvalue_get_integer(value); + + snprintf(str,MAX_INT_DIGITS,"%d",data); + + return str; +} +#else +// snprintf not working on wintendo + +#define MAX_INT_DIGITS 32 /* Enough for 2^32 + sign*/ +char* icalvalue_int_as_ical_string(icalvalue* value) { + + int data; + char* str = (char*)icalmemory_tmp_buffer(MAX_INT_DIGITS); + + icalerror_check_arg_rz( (value!=0),"value"); + + data = icalvalue_get_integer(value); + + sprintf(str,"%d",data); + + return str; +} + +#endif +char* icalvalue_utcoffset_as_ical_string(icalvalue* value) +{ + int data,h,m,s; + char sign; + char* str = (char*)icalmemory_tmp_buffer(9); + + icalerror_check_arg_rz( (value!=0),"value"); + + data = icalvalue_get_utcoffset(value); + + if (abs(data) == data){ + sign = '+'; + } else { + sign = '-'; + } + + h = data/3600; + m = (data - (h*3600))/ 60; + s = (data - (h*3600) - (m*60)); + + sprintf(str,"%c%02d%02d%02d",sign,abs(h),abs(m),abs(s)); + + return str; +} + +char* icalvalue_string_as_ical_string(icalvalue* value) { + + const char* data; + char* str = 0; + icalerror_check_arg_rz( (value!=0),"value"); + + data = ((struct icalvalue_impl*)value)->data.v_string; + + str = (char*)icalmemory_tmp_buffer(strlen(data)+1); + + strcpy(str,data); + + return str; +} + + +char* icalvalue_recur_as_ical_string(icalvalue* value) +{ + struct icalvalue_impl *impl = (struct icalvalue_impl*)value; + struct icalrecurrencetype *recur = impl->data.v_recur; + + return icalrecurrencetype_as_string(recur); +} + +char* icalvalue_text_as_ical_string(icalvalue* value) { + + char *str; + char *str_p; + char *rtrn; + const char *p; + size_t buf_sz; + int line_length; + + line_length = 0; + + buf_sz = strlen(((struct icalvalue_impl*)value)->data.v_string)+1; + + str_p = str = (char*)icalmemory_new_buffer(buf_sz); + + if (str_p == 0){ + return 0; + } + + for(p=((struct icalvalue_impl*)value)->data.v_string; *p!=0; p++){ + + switch(*p){ + case '\n': { + icalmemory_append_string(&str,&str_p,&buf_sz,"\\n"); + line_length+=3; + break; + } + + case '\t': { + icalmemory_append_string(&str,&str_p,&buf_sz,"\\t"); + line_length+=3; + break; + } + case '\r': { + icalmemory_append_string(&str,&str_p,&buf_sz,"\\r"); + line_length+=3; + break; + } + case '\b': { + icalmemory_append_string(&str,&str_p,&buf_sz,"\\b"); + line_length+=3; + break; + } + case '\f': { + icalmemory_append_string(&str,&str_p,&buf_sz,"\\f"); + line_length+=3; + break; + } + + case ';': + case ',':{ + icalmemory_append_char(&str,&str_p,&buf_sz,'\\'); + icalmemory_append_char(&str,&str_p,&buf_sz,*p); + line_length+=3; + break; + } + + default: { + icalmemory_append_char(&str,&str_p,&buf_sz,*p); + line_length++; + } + } + + if (line_length > 65 && *p == ' '){ + icalmemory_append_string(&str,&str_p,&buf_sz,"\n "); + line_length=0; + } + + + if (line_length > 75){ + icalmemory_append_string(&str,&str_p,&buf_sz,"\n "); + line_length=0; + } + + } + + /* Assume the last character is not a '\0' and add one. We could + check *str_p != 0, but that would be an uninitialized memory + read. */ + + + icalmemory_append_char(&str,&str_p,&buf_sz,'\0'); + + rtrn = icalmemory_tmp_copy(str); + + icalmemory_free_buffer(str); + + return rtrn; +} + + +char* icalvalue_attach_as_ical_string(icalvalue* value) { + + struct icalattachtype *a; + char * str; + + icalerror_check_arg_rz( (value!=0),"value"); + + a = icalvalue_get_attach(value); + + if (a->binary != 0) { + return icalvalue_binary_as_ical_string(value); + } else if (a->base64 != 0) { + str = (char*)icalmemory_tmp_buffer(strlen(a->base64)+1); + strcpy(str,a->base64); + return str; + } else if (a->url != 0){ + icalvalue *v = icalvalue_new_text( a->url ); + char *icalstring = icalvalue_string_as_ical_string(v); + icalvalue_free( v ); + return icalstring; + } else { + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } +} + + +char* icalvalue_duration_as_ical_string(icalvalue* value) { + + struct icaldurationtype data; + + icalerror_check_arg_rz( (value!=0),"value"); + data = icalvalue_get_duration(value); + + return icaldurationtype_as_ical_string(data); +} + +void print_time_to_string(char* str, struct icaltimetype *data) +{ + char temp[20]; + + if (data->is_utc == 1){ + sprintf(temp,"%02d%02d%02dZ",data->hour,data->minute,data->second); + } else { + sprintf(temp,"%02d%02d%02d",data->hour,data->minute,data->second); + } + + strcat(str,temp); +} + + +void print_date_to_string(char* str, struct icaltimetype *data) +{ + char temp[20]; + + sprintf(temp,"%04d%02d%02d",data->year,data->month,data->day); + + strcat(str,temp); +} + +char* icalvalue_date_as_ical_string(icalvalue* value) { + + struct icaltimetype data; + char* str; + icalerror_check_arg_rz( (value!=0),"value"); + data = icalvalue_get_date(value); + + str = (char*)icalmemory_tmp_buffer(9); + + str[0] = 0; + print_date_to_string(str,&data); + + return str; +} + +void print_datetime_to_string(char* str, struct icaltimetype *data) +{ + print_date_to_string(str,data); + strcat(str,"T"); + print_time_to_string(str,data); + +} + +const char* icalvalue_datetime_as_ical_string(icalvalue* value) { + + struct icaltimetype data; + char* str; + icalvalue_kind kind = icalvalue_isa(value); + + icalerror_check_arg_rz( (value!=0),"value"); + + + if( !(kind == ICAL_DATE_VALUE || kind == ICAL_DATETIME_VALUE )) + { + icalerror_set_errno(ICAL_BADARG_ERROR); + return 0; + } + + data = icalvalue_get_datetime(value); + + str = (char*)icalmemory_tmp_buffer(20); + + str[0] = 0; + + print_datetime_to_string(str,&data); + + return str; + +} + +char* icalvalue_float_as_ical_string(icalvalue* value) { + + float data; + char* str; + icalerror_check_arg_rz( (value!=0),"value"); + data = icalvalue_get_float(value); + + str = (char*)icalmemory_tmp_buffer(15); + + sprintf(str,"%f",data); + + return str; +} + +char* icalvalue_geo_as_ical_string(icalvalue* value) { + + struct icalgeotype data; + char* str; + icalerror_check_arg_rz( (value!=0),"value"); + + data = icalvalue_get_geo(value); + + str = (char*)icalmemory_tmp_buffer(25); + + sprintf(str,"%f;%f",data.lat,data.lon); + + return str; +} + +const char* icalvalue_datetimeperiod_as_ical_string(icalvalue* value) { + struct icaldatetimeperiodtype dtp = icalvalue_get_datetimeperiod(value); + + icalerror_check_arg_rz( (value!=0),"value"); + + if(!icaltime_is_null_time(dtp.time)){ + return icaltime_as_ical_string(dtp.time); + } else { + return icalperiodtype_as_ical_string(dtp.period); + } +} + +const char* icalvalue_period_as_ical_string(icalvalue* value) { + struct icalperiodtype data; + icalerror_check_arg_rz( (value!=0),"value"); + data = icalvalue_get_period(value); + + return icalperiodtype_as_ical_string(data); + +} + +char* icalvalue_trigger_as_ical_string(icalvalue* value) { + + struct icaltriggertype data; + + icalerror_check_arg_rz( (value!=0),"value"); + data = icalvalue_get_trigger(value); + + if(!icaltime_is_null_time(data.time)){ + return icaltime_as_ical_string(data.time); + } else { + return icaldurationtype_as_ical_string(data.duration); + } + +} + +const char* +icalvalue_as_ical_string (icalvalue* value) +{ + struct icalvalue_impl* v = (struct icalvalue_impl*)value; + + v=v; + + if(value == 0){ + return 0; + } + + switch (v->kind){ + + case ICAL_ATTACH_VALUE: + return icalvalue_attach_as_ical_string(value); + + case ICAL_BINARY_VALUE: + return icalvalue_binary_as_ical_string(value); + + case ICAL_BOOLEAN_VALUE: + case ICAL_INTEGER_VALUE: + return icalvalue_int_as_ical_string(value); + + case ICAL_UTCOFFSET_VALUE: + return icalvalue_utcoffset_as_ical_string(value); + + case ICAL_TEXT_VALUE: + return icalvalue_text_as_ical_string(value); + + case ICAL_STRING_VALUE: + case ICAL_URI_VALUE: + case ICAL_CALADDRESS_VALUE: + return icalvalue_string_as_ical_string(value); + + case ICAL_DATE_VALUE: + return icalvalue_date_as_ical_string(value); + case ICAL_DATETIME_VALUE: + return icalvalue_datetime_as_ical_string(value); + case ICAL_DURATION_VALUE: + return icalvalue_duration_as_ical_string(value); + + case ICAL_PERIOD_VALUE: + return icalvalue_period_as_ical_string(value); + case ICAL_DATETIMEPERIOD_VALUE: + return icalvalue_datetimeperiod_as_ical_string(value); + + case ICAL_FLOAT_VALUE: + return icalvalue_float_as_ical_string(value); + + case ICAL_GEO_VALUE: + return icalvalue_geo_as_ical_string(value); + + case ICAL_RECUR_VALUE: + return icalvalue_recur_as_ical_string(value); + + case ICAL_TRIGGER_VALUE: + return icalvalue_trigger_as_ical_string(value); + + case ICAL_REQUESTSTATUS_VALUE: + return icalreqstattype_as_string(v->data.v_requeststatus); + + case ICAL_ACTION_VALUE: + case ICAL_METHOD_VALUE: + case ICAL_STATUS_VALUE: + case ICAL_TRANSP_VALUE: + case ICAL_CLASS_VALUE: + if(v->x_value !=0){ + return icalmemory_tmp_copy(v->x_value); + } + + return icalproperty_enum_to_string(v->data.v_enum); + + case ICAL_X_VALUE: + return icalmemory_tmp_copy(v->x_value); + + case ICAL_NO_VALUE: + default: + { + return 0; + } + } +} + + +icalvalue_kind +icalvalue_isa (icalvalue* value) +{ + struct icalvalue_impl* v = (struct icalvalue_impl*)value; + + if(value == 0){ + return ICAL_NO_VALUE; + } + + return v->kind; +} + + +int +icalvalue_isa_value (void* value) +{ + struct icalvalue_impl *impl = (struct icalvalue_impl *)value; + + icalerror_check_arg_rz( (value!=0), "value"); + + if (strcmp(impl->id,"val") == 0) { + return 1; + } else { + return 0; + } +} + + +int icalvalue_is_time(icalvalue* a) { + icalvalue_kind kind = icalvalue_isa(a); + + if(kind == ICAL_DATETIME_VALUE || + kind == ICAL_DATE_VALUE ){ + return 1; + } + + return 0; + +} + +icalparameter_xliccomparetype +icalvalue_compare(icalvalue* a, icalvalue *b) +{ + struct icalvalue_impl *impla = (struct icalvalue_impl *)a; + struct icalvalue_impl *implb = (struct icalvalue_impl *)b; + + icalerror_check_arg_rz( (a!=0), "a"); + icalerror_check_arg_rz( (b!=0), "b"); + + /* Not the same type; they can only be unequal */ + if( ! (icalvalue_is_time(a) && icalvalue_is_time(b)) && + icalvalue_isa(a) != icalvalue_isa(b)){ + return ICAL_XLICCOMPARETYPE_NOTEQUAL; + } + + switch (icalvalue_isa(a)){ + + case ICAL_ATTACH_VALUE: + case ICAL_BINARY_VALUE: + + case ICAL_BOOLEAN_VALUE: + { + if (icalvalue_get_boolean(a) == icalvalue_get_boolean(b)){ + return ICAL_XLICCOMPARETYPE_EQUAL; + } else { + return ICAL_XLICCOMPARETYPE_NOTEQUAL; + } + } + + case ICAL_FLOAT_VALUE: + { + if (impla->data.v_float > implb->data.v_float){ + return ICAL_XLICCOMPARETYPE_GREATER; + } else if (impla->data.v_float < implb->data.v_float){ + return ICAL_XLICCOMPARETYPE_LESS; + } else { + return ICAL_XLICCOMPARETYPE_EQUAL; + } + } + + case ICAL_INTEGER_VALUE: + case ICAL_UTCOFFSET_VALUE: + { + if (impla->data.v_int > implb->data.v_int){ + return ICAL_XLICCOMPARETYPE_GREATER; + } else if (impla->data.v_int < implb->data.v_int){ + return ICAL_XLICCOMPARETYPE_LESS; + } else { + return ICAL_XLICCOMPARETYPE_EQUAL; + } + } + + case ICAL_DURATION_VALUE: + { + int a = icaldurationtype_as_int(impla->data.v_duration); + int b = icaldurationtype_as_int(implb->data.v_duration); + + if (a > b){ + return ICAL_XLICCOMPARETYPE_GREATER; + } else if (a < b){ + return ICAL_XLICCOMPARETYPE_LESS; + } else { + return ICAL_XLICCOMPARETYPE_EQUAL; + } + } + + + case ICAL_TEXT_VALUE: + case ICAL_URI_VALUE: + case ICAL_CALADDRESS_VALUE: + case ICAL_TRIGGER_VALUE: + case ICAL_DATE_VALUE: + case ICAL_DATETIME_VALUE: + case ICAL_DATETIMEPERIOD_VALUE: + { + int r; + + r = strcmp(icalvalue_as_ical_string(a), + icalvalue_as_ical_string(b)); + + if (r > 0) { + return ICAL_XLICCOMPARETYPE_GREATER; + } else if (r < 0){ + return ICAL_XLICCOMPARETYPE_LESS; + } else { + return ICAL_XLICCOMPARETYPE_EQUAL; + } + + + } + + case ICAL_METHOD_VALUE: + { + if (icalvalue_get_method(a) == icalvalue_get_method(b)){ + return ICAL_XLICCOMPARETYPE_EQUAL; + } else { + return ICAL_XLICCOMPARETYPE_NOTEQUAL; + } + + } + + case ICAL_STATUS_VALUE: + { + if (icalvalue_get_status(a) == icalvalue_get_status(b)){ + return ICAL_XLICCOMPARETYPE_EQUAL; + } else { + return ICAL_XLICCOMPARETYPE_NOTEQUAL; + } + + } + + case ICAL_PERIOD_VALUE: + case ICAL_GEO_VALUE: + case ICAL_RECUR_VALUE: + case ICAL_NO_VALUE: + default: + { + icalerror_warn("Comparison not implemented for value type"); + return ICAL_XLICCOMPARETYPE_REGEX+1; /* HACK */ + } + } + +} + +/* Examine the value and possiby chage the kind to agree with the value */ +void icalvalue_reset_kind(icalvalue* value) +{ + struct icalvalue_impl* impl = (struct icalvalue_impl*)value; + + if( (impl->kind==ICAL_DATETIME_VALUE || impl->kind==ICAL_DATE_VALUE )&& + !icaltime_is_null_time(impl->data.v_time) ) { + + if( impl->data.v_time.is_date == 1){ + impl->kind = ICAL_DATE_VALUE; + } else { + impl->kind = ICAL_DATETIME_VALUE; + } + } + +} + +void icalvalue_set_parent(icalvalue* value, + icalproperty* property) +{ + struct icalvalue_impl* v = (struct icalvalue_impl*)value; + + v->parent = property; + +} + +icalproperty* icalvalue_get_parent(icalvalue* value) +{ + struct icalvalue_impl* v = (struct icalvalue_impl*)value; + + + return v->parent; +} + + + +/* The remaining interfaces are 'new', 'set' and 'get' for each of the value + types */ + + +/* Everything below this line is machine generated. Do not edit. */ diff --git a/libical/src/libical/icalvalue.h b/libical/src/libical/icalvalue.h new file mode 100644 index 0000000..6983c23 --- a/dev/null +++ b/libical/src/libical/icalvalue.h @@ -0,0 +1,85 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.h + CREATOR: eric 20 March 1999 + + + $Id$ + $Locker$ + + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalvalue.h + + ======================================================================*/ + +#ifndef ICALVALUE_H +#define ICALVALUE_H + +#include <time.h> +#include "icalenums.h" +#include "icaltypes.h" +#include "icalrecur.h" +#include "icalduration.h" +#include "icalperiod.h" +#include "icalderivedproperty.h" /* For icalproperty_method, etc. */ +#include "icalderivedparameter.h" +#include "icalderivedvalue.h" + +/* Defined in icalderivedvalue.h */ +/*typedef void icalvalue;*/ + +icalvalue* icalvalue_new(icalvalue_kind kind); + +icalvalue* icalvalue_new_clone(icalvalue* value); + +icalvalue* icalvalue_new_from_string(icalvalue_kind kind, const char* str); + +void icalvalue_free(icalvalue* value); + +int icalvalue_is_valid(icalvalue* value); + +const char* icalvalue_as_ical_string(icalvalue* value); + +icalvalue_kind icalvalue_isa(icalvalue* value); + +int icalvalue_isa_value(void*); + +icalparameter_xliccomparetype icalvalue_compare(icalvalue* a, icalvalue *b); + + +/* Special, non autogenerated value accessors */ + +icalvalue* icalvalue_new_recur (struct icalrecurrencetype v); +void icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v); +struct icalrecurrencetype icalvalue_get_recur(icalvalue* value); + +icalvalue* icalvalue_new_trigger (struct icaltriggertype v); +void icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v); +struct icaltriggertype icalvalue_get_trigger(icalvalue* value); + +icalvalue* icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v); +void icalvalue_set_datetimeperiod(icalvalue* value, + struct icaldatetimeperiodtype v); +struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(icalvalue* value); + +/* Convert enumerations */ + +icalvalue_kind icalvalue_string_to_kind(const char* str); +const char* icalvalue_kind_to_string(icalvalue_kind kind); + + +#endif /*ICALVALUE_H*/ diff --git a/libical/src/libical/icalvalueimpl.h b/libical/src/libical/icalvalueimpl.h new file mode 100644 index 0000000..116535d --- a/dev/null +++ b/libical/src/libical/icalvalueimpl.h @@ -0,0 +1,93 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.c + CREATOR: eric 02 May 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalvalue.c + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + +======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef ICALVALUEIMPL_H +#define ICALVALUEIMPL_H + +#include "icalenums.h" + + +struct icalvalue_impl { + icalvalue_kind kind; /*this is the kind that is visible from the outside*/ + + char id[5]; + int size; + icalproperty* parent; + const char* x_value; + + union data { + struct icalattachtype *v_attach; + /* void *v_binary; */ /* use v_attach */ + const char *v_string; + /*char *v_text;*/ + /*char *v_caladdress;*/ + /*char *v_uri;*/ + float v_float; + int v_int; + /*int v_boolean;*/ + /*int v_integer;*/ + struct icaldurationtype v_duration; + /*int v_utcoffset;*/ + + struct icalperiodtype v_period; + /*struct icalperiodtype v_datetimeperiod;*/ + struct icalgeotype v_geo; + /*time_t v_time;*/ + struct icaltimetype v_time; + /*struct icaltimetype v_date;*/ + /*struct icaltimetype v_datetime;*/ + /*struct icaltimetype v_datetimedate;*/ + + struct icalreqstattype v_requeststatus; + + /* struct icalrecurrencetype was once included + directly ( not referenced ) in this union, but it + contributes 2000 bytes to every value, so now it is + a reference*/ + + struct icalrecurrencetype *v_recur; + struct icaltriggertype v_trigger; + + int v_enum; + /* v_enum takes care of several enumerated types including: + icalproperty_method v_method; + icalproperty_status v_status; + icalproperty_action v_action; + icalproperty_class v_class; + icalproperty_transp v_transp; + */ + + } data; +}; + +#endif diff --git a/libical/src/libical/icalversion.h b/libical/src/libical/icalversion.h new file mode 100644 index 0000000..beae8e0 --- a/dev/null +++ b/libical/src/libical/icalversion.h @@ -0,0 +1,7 @@ +#ifndef ICAL_VERSION_H +#define ICAL_VERSION_H + +#define ICAL_PACKAGE "libical" +#define ICAL_VERSION "0.23" + +#endif diff --git a/libical/src/libical/icalversion.h.in b/libical/src/libical/icalversion.h.in new file mode 100644 index 0000000..5d21369 --- a/dev/null +++ b/libical/src/libical/icalversion.h.in @@ -0,0 +1,7 @@ +#ifndef ICAL_VERSION_H +#define ICAL_VERSION_H + +#define ICAL_PACKAGE "@PACKAGE@" +#define ICAL_VERSION "@VERSION@" + +#endif diff --git a/libical/src/libical/icalyacc.c b/libical/src/libical/icalyacc.c new file mode 100644 index 0000000..d0b9a10 --- a/dev/null +++ b/libical/src/libical/icalyacc.c @@ -0,0 +1,1447 @@ + +/* A Bison parser, made from ../../../../libical/src/libical/icalyacc.y + by GNU Bison version 1.28 */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define yyparse ical_yyparse +#define yylex ical_yylex +#define yyerror ical_yyerror +#define yylval ical_yylval +#define yychar ical_yychar +#define yydebug ical_yydebug +#define yynerrs ical_yynerrs +#define DIGITS 257 +#define INTNUMBER 258 +#define FLOATNUMBER 259 +#define STRING 260 +#define EOL 261 +#define EQUALS 262 +#define CHARACTER 263 +#define COLON 264 +#define COMMA 265 +#define SEMICOLON 266 +#define MINUS 267 +#define TIMESEPERATOR 268 +#define TRUE 269 +#define FALSE 270 +#define FREQ 271 +#define BYDAY 272 +#define BYHOUR 273 +#define BYMINUTE 274 +#define BYMONTH 275 +#define BYMONTHDAY 276 +#define BYSECOND 277 +#define BYSETPOS 278 +#define BYWEEKNO 279 +#define BYYEARDAY 280 +#define DAILY 281 +#define MINUTELY 282 +#define MONTHLY 283 +#define SECONDLY 284 +#define WEEKLY 285 +#define HOURLY 286 +#define YEARLY 287 +#define INTERVAL 288 +#define COUNT 289 +#define UNTIL 290 +#define WKST 291 +#define MO 292 +#define SA 293 +#define SU 294 +#define TU 295 +#define WE 296 +#define TH 297 +#define FR 298 +#define BIT8 299 +#define ACCEPTED 300 +#define ADD 301 +#define AUDIO 302 +#define BASE64 303 +#define BINARY 304 +#define BOOLEAN 305 +#define BUSY 306 +#define BUSYTENTATIVE 307 +#define BUSYUNAVAILABLE 308 +#define CALADDRESS 309 +#define CANCEL 310 +#define CANCELLED 311 +#define CHAIR 312 +#define CHILD 313 +#define COMPLETED 314 +#define CONFIDENTIAL 315 +#define CONFIRMED 316 +#define COUNTER 317 +#define DATE 318 +#define DATETIME 319 +#define DECLINECOUNTER 320 +#define DECLINED 321 +#define DELEGATED 322 +#define DISPLAY 323 +#define DRAFT 324 +#define DURATION 325 +#define EMAIL 326 +#define END 327 +#define FINAL 328 +#define FLOAT 329 +#define FREE 330 +#define GREGORIAN 331 +#define GROUP 332 +#define INDIVIDUAL 333 +#define INPROCESS 334 +#define INTEGER 335 +#define NEEDSACTION 336 +#define NONPARTICIPANT 337 +#define OPAQUE 338 +#define OPTPARTICIPANT 339 +#define PARENT 340 +#define PERIOD 341 +#define PRIVATE 342 +#define PROCEDURE 343 +#define PUBLIC 344 +#define PUBLISH 345 +#define RECUR 346 +#define REFRESH 347 +#define REPLY 348 +#define REQPARTICIPANT 349 +#define REQUEST 350 +#define RESOURCE 351 +#define ROOM 352 +#define SIBLING 353 +#define START 354 +#define TENTATIVE 355 +#define TEXT 356 +#define THISANDFUTURE 357 +#define THISANDPRIOR 358 +#define TIME 359 +#define TRANSPAENT 360 +#define UNKNOWN 361 +#define UTCOFFSET 362 +#define XNAME 363 +#define ALTREP 364 +#define CN 365 +#define CUTYPE 366 +#define DAYLIGHT 367 +#define DIR 368 +#define ENCODING 369 +#define EVENT 370 +#define FBTYPE 371 +#define FMTTYPE 372 +#define LANGUAGE 373 +#define MEMBER 374 +#define PARTSTAT 375 +#define RANGE 376 +#define RELATED 377 +#define RELTYPE 378 +#define ROLE 379 +#define RSVP 380 +#define SENTBY 381 +#define STANDARD 382 +#define URI 383 +#define TIME_CHAR 384 +#define UTC_CHAR 385 + +#line 1 "../../../../libical/src/libical/icalyacc.y" + +/* -*- Mode: C -*- + ====================================================================== + FILE: icalitip.y + CREATOR: eric 10 June 1999 + + DESCRIPTION: + + $Id$ + $Locker$ + + (C) COPYRIGHT 1999 Eric Busboom + http://www.softwarestudio.org + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + The original author is Eric Busboom + The original code is icalitip.y + + + + =======================================================================*/ + +#include <stdlib.h> +#include <string.h> /* for strdup() */ +#include "icalparser.h" +#include "pvl.h" + +icalvalue *icalparser_yy_value; /* Current Value */ + +void ical_yyerror(char* s); +void icalparser_clear_flex_input(); +int ical_yy_lex(void); + +/* Globals for UTCOFFSET values */ +int utc; +int utc_b; +int utcsign; + +/* Globals for DURATION values */ +struct icaldurationtype duration; + +/* Globals for TRIGGER values */ +struct icaltriggertype trigger; + +void copy_list(short* array, size_t size); +void add_prop(icalproperty_kind); +void icalparser_fill_date(struct tm* t, char* dstr); +void icalparser_fill_time(struct tm* t, char* tstr); +void set_value_type(icalvalue_kind kind); +void set_parser_value_state(); +struct icaltimetype fill_datetime(char* d, char* t); +void ical_yy_error(char *s); /* Don't know why I need this.... */ +int yylex(void); /* Or this. */ + + + +/* Set the state of the lexer so it will interpret values ( iCAL + VALUEs, that is, ) correctly. */ + + +#line 71 "../../../../libical/src/libical/icalyacc.y" +typedef union { + float v_float; + int v_int; + char* v_string; +} YYSTYPE; +#ifndef YYDEBUG +#define YYDEBUG 1 +#endif + +#include <stdio.h> + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 51 +#define YYFLAG -32768 +#define YYNTBASE 141 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 385 ? yytranslate[x] : 158) + +static const short yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 137, 2, 138, 2, 140, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 136, 2, 2, + 2, 133, 2, 2, 2, 2, 134, 2, 2, 139, + 2, 2, 135, 2, 2, 2, 132, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 131 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 4, 6, 8, 10, 12, 14, 15, 17, + 18, 20, 25, 27, 30, 33, 36, 39, 42, 45, + 49, 52, 56, 59, 62, 63, 65, 67, 71, 75, + 79, 89, 96, 97, 99, 101, 105 +}; + +static const short yyrhs[] = { 142, + 0, 145, 0, 154, 0, 155, 0, 157, 0, 1, + 0, 3, 0, 0, 131, 0, 0, 131, 0, 3, + 130, 3, 143, 0, 152, 0, 152, 148, 0, 3, + 132, 0, 130, 149, 0, 130, 150, 0, 130, 151, + 0, 3, 133, 0, 3, 133, 150, 0, 3, 134, + 0, 3, 134, 151, 0, 3, 135, 0, 3, 136, + 0, 0, 137, 0, 138, 0, 153, 139, 146, 0, + 153, 139, 148, 0, 153, 139, 147, 0, 3, 130, + 3, 143, 140, 3, 130, 3, 144, 0, 3, 130, + 3, 143, 140, 154, 0, 0, 137, 0, 138, 0, + 156, 4, 4, 0, 156, 4, 4, 4, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 177, 179, 180, 181, 182, 183, 190, 205, 207, 210, + 212, 214, 230, 231, 233, 238, 241, 244, 248, 252, + 257, 261, 266, 271, 276, 280, 284, 289, 294, 299, + 308, 329, 358, 364, 365, 367, 373 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","DIGITS", +"INTNUMBER","FLOATNUMBER","STRING","EOL","EQUALS","CHARACTER","COLON","COMMA", +"SEMICOLON","MINUS","TIMESEPERATOR","TRUE","FALSE","FREQ","BYDAY","BYHOUR","BYMINUTE", +"BYMONTH","BYMONTHDAY","BYSECOND","BYSETPOS","BYWEEKNO","BYYEARDAY","DAILY", +"MINUTELY","MONTHLY","SECONDLY","WEEKLY","HOURLY","YEARLY","INTERVAL","COUNT", +"UNTIL","WKST","MO","SA","SU","TU","WE","TH","FR","BIT8","ACCEPTED","ADD","AUDIO", +"BASE64","BINARY","BOOLEAN","BUSY","BUSYTENTATIVE","BUSYUNAVAILABLE","CALADDRESS", +"CANCEL","CANCELLED","CHAIR","CHILD","COMPLETED","CONFIDENTIAL","CONFIRMED", +"COUNTER","DATE","DATETIME","DECLINECOUNTER","DECLINED","DELEGATED","DISPLAY", +"DRAFT","DURATION","EMAIL","END","FINAL","FLOAT","FREE","GREGORIAN","GROUP", +"INDIVIDUAL","INPROCESS","INTEGER","NEEDSACTION","NONPARTICIPANT","OPAQUE","OPTPARTICIPANT", +"PARENT","PERIOD","PRIVATE","PROCEDURE","PUBLIC","PUBLISH","RECUR","REFRESH", +"REPLY","REQPARTICIPANT","REQUEST","RESOURCE","ROOM","SIBLING","START","TENTATIVE", +"TEXT","THISANDFUTURE","THISANDPRIOR","TIME","TRANSPAENT","UNKNOWN","UTCOFFSET", +"XNAME","ALTREP","CN","CUTYPE","DAYLIGHT","DIR","ENCODING","EVENT","FBTYPE", +"FMTTYPE","LANGUAGE","MEMBER","PARTSTAT","RANGE","RELATED","RELTYPE","ROLE", +"RSVP","SENTBY","STANDARD","URI","TIME_CHAR","UTC_CHAR","'W'","'H'","'M'","'S'", +"'D'","'+'","'-'","'P'","'/'","value","date_value","utc_char","utc_char_b","datetime_value", +"dur_date","dur_week","dur_time","dur_hour","dur_minute","dur_second","dur_day", +"dur_prefix","duration_value","period_value","plusminus","utcoffset_value", NULL +}; +#endif + +static const short yyr1[] = { 0, + 141, 141, 141, 141, 141, 141, 142, 143, 143, 144, + 144, 145, 146, 146, 147, 148, 148, 148, 149, 149, + 150, 150, 151, 152, 153, 153, 153, 154, 154, 154, + 155, 155, -1, 156, 156, 157, 157 +}; + +static const short yyr2[] = { 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, + 1, 4, 1, 2, 2, 2, 2, 2, 2, 3, + 2, 3, 2, 2, 0, 1, 1, 3, 3, 3, + 9, 6, 0, 1, 1, 3, 4 +}; + +static const short yydefact[] = { 0, + 6, 7, 26, 27, 1, 2, 0, 3, 4, 0, + 5, 0, 0, 0, 8, 0, 0, 28, 30, 29, + 13, 36, 9, 12, 15, 24, 0, 16, 17, 18, + 14, 37, 25, 19, 21, 23, 0, 26, 27, 32, + 0, 20, 0, 22, 0, 10, 11, 31, 0, 0, + 0 +}; + +static const short yydefgoto[] = { 49, + 5, 24, 48, 6, 18, 19, 20, 28, 29, 30, + 21, 7, 8, 9, 10, 11 +}; + +static const short yypact[] = { -1, +-32768, -126, 7, 8,-32768,-32768, -133,-32768,-32768, 9, +-32768, 11, -2, 12, -116, -129, 14,-32768,-32768,-32768, + -112, 15,-32768, -120,-32768,-32768, -125,-32768,-32768,-32768, +-32768,-32768, 2, 18, 19,-32768, -107,-32768,-32768,-32768, + -110,-32768, -109,-32768, 22, -104,-32768,-32768, 28, 29, +-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768,-32768,-32768,-32768,-32768, 10,-32768, -4, -3, +-32768,-32768, 0,-32768,-32768,-32768 +}; + + +#define YYLAST 140 + + +static const short yytable[] = { 1, + 16, 2, 25, 12, 37, 13, 26, 34, 35, 36, + -34, -35, 14, 15, 23, 22, 27, 17, 32, 33, + 41, 43, 45, 35, 46, 36, 47, 50, 51, 42, + 31, 44, 40, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 3, 4, -25, 38, 39 +}; + +static const short yycheck[] = { 1, + 3, 3, 132, 130, 3, 139, 136, 133, 134, 135, + 4, 4, 4, 3, 131, 4, 3, 130, 4, 140, + 3, 3, 130, 134, 3, 135, 131, 0, 0, 34, + 21, 35, 33, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 130, -1, -1, + -1, -1, -1, -1, -1, 137, 138, 139, 137, 138 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/bison.simple" +/* This file comes from bison-1.28. */ + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +#ifndef YYPARSE_RETURN_TYPE +#define YYPARSE_RETURN_TYPE int +#endif + + +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ +#ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA +#include <alloca.h> +#else /* not sparc */ +/* We think this test detects Watcom and Microsoft C. */ +/* This used to test MSDOS, but that is a bad idea + since that symbol is in the user namespace. */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; + instead, just don't use alloca. */ +#include <malloc.h> +#endif +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +/* I don't know what this was needed for, but it pollutes the namespace. + So I turned it off. rms, 2 May 1997. */ +/* #include <malloc.h> */ + #pragma alloca +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, + and on HPUX 10. Eventually we can turn this on. */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#endif /* __hpux */ +#endif +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ + +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc +#endif + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Define __yy_memcpy. Note that the size argument + should be passed with type unsigned int, because that is what the non-GCC + definitions require. With GCC, __builtin_memcpy takes an arg + of type size_t, but it can handle unsigned int. */ + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + unsigned int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, unsigned int count) +{ + register char *t = to; + register char *f = from; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 222 "/usr/share/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +#ifdef YYPARSE_PARAM +YYPARSE_RETURN_TYPE +yyparse (void *); +#else +YYPARSE_RETURN_TYPE +yyparse (void); +#endif +#endif + +YYPARSE_RETURN_TYPE +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; +#ifndef YYSTACK_USE_ALLOCA + int yyfree_stacks = 0; +#endif + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); +#ifndef YYSTACK_USE_ALLOCA + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } +#endif + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; +#ifndef YYSTACK_USE_ALLOCA + yyfree_stacks = 1; +#endif + yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, + size * (unsigned int) sizeof (*yyssp)); + yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, + size * (unsigned int) sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, + size * (unsigned int) sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 6: +#line 183 "../../../../libical/src/libical/icalyacc.y" +{ + icalparser_yy_value = 0; + icalparser_clear_flex_input(); + yyclearin; + ; + break;} +case 7: +#line 191 "../../../../libical/src/libical/icalyacc.y" +{ + struct icaltimetype stm; + + stm = fill_datetime(yyvsp[0].v_string,0); + + stm.hour = -1; + stm.minute = -1; + stm.second = -1; + stm.is_utc = 0; + stm.is_date = 1; + + icalparser_yy_value = icalvalue_new_date(stm); + ; + break;} +case 8: +#line 206 "../../../../libical/src/libical/icalyacc.y" +{utc = 0;; + break;} +case 9: +#line 207 "../../../../libical/src/libical/icalyacc.y" +{utc = 1;; + break;} +case 10: +#line 211 "../../../../libical/src/libical/icalyacc.y" +{utc_b = 0;; + break;} +case 11: +#line 212 "../../../../libical/src/libical/icalyacc.y" +{utc_b = 1;; + break;} +case 12: +#line 216 "../../../../libical/src/libical/icalyacc.y" +{ + struct icaltimetype stm; + stm = fill_datetime(yyvsp[-3].v_string, yyvsp[-1].v_string); + stm.is_utc = utc; + stm.is_date = 0; + + icalparser_yy_value = + icalvalue_new_datetime(stm); + ; + break;} +case 15: +#line 234 "../../../../libical/src/libical/icalyacc.y" +{ + duration.weeks = atoi(yyvsp[-1].v_string); + ; + break;} +case 16: +#line 239 "../../../../libical/src/libical/icalyacc.y" +{ + ; + break;} +case 17: +#line 242 "../../../../libical/src/libical/icalyacc.y" +{ + ; + break;} +case 18: +#line 245 "../../../../libical/src/libical/icalyacc.y" +{ + ; + break;} +case 19: +#line 249 "../../../../libical/src/libical/icalyacc.y" +{ + duration.hours = atoi(yyvsp[-1].v_string); + ; + break;} +case 20: +#line 253 "../../../../libical/src/libical/icalyacc.y" +{ + duration.hours = atoi(yyvsp[-2].v_string); + ; + break;} +case 21: +#line 258 "../../../../libical/src/libical/icalyacc.y" +{ + duration.minutes = atoi(yyvsp[-1].v_string); + ; + break;} +case 22: +#line 262 "../../../../libical/src/libical/icalyacc.y" +{ + duration.minutes = atoi(yyvsp[-2].v_string); + ; + break;} +case 23: +#line 267 "../../../../libical/src/libical/icalyacc.y" +{ + duration.seconds = atoi(yyvsp[-1].v_string); + ; + break;} +case 24: +#line 272 "../../../../libical/src/libical/icalyacc.y" +{ + duration.days = atoi(yyvsp[-1].v_string); + ; + break;} +case 25: +#line 277 "../../../../libical/src/libical/icalyacc.y" +{ + duration.is_neg = 0; + ; + break;} +case 26: +#line 281 "../../../../libical/src/libical/icalyacc.y" +{ + duration.is_neg = 0; + ; + break;} +case 27: +#line 285 "../../../../libical/src/libical/icalyacc.y" +{ + duration.is_neg = 1; + ; + break;} +case 28: +#line 290 "../../../../libical/src/libical/icalyacc.y" +{ + icalparser_yy_value = icalvalue_new_duration(duration); + memset(&duration,0, sizeof(duration)); + ; + break;} +case 29: +#line 295 "../../../../libical/src/libical/icalyacc.y" +{ + icalparser_yy_value = icalvalue_new_duration(duration); + memset(&duration,0, sizeof(duration)); + ; + break;} +case 30: +#line 300 "../../../../libical/src/libical/icalyacc.y" +{ + icalparser_yy_value = icalvalue_new_duration(duration); + memset(&duration,0, sizeof(duration)); + ; + break;} +case 31: +#line 309 "../../../../libical/src/libical/icalyacc.y" +{ + struct icalperiodtype p; + + p.start = fill_datetime(yyvsp[-8].v_string,yyvsp[-6].v_string); + p.start.is_utc = utc; + p.start.is_date = 0; + + + p.end = fill_datetime(yyvsp[-3].v_string,yyvsp[-1].v_string); + p.end.is_utc = utc_b; + p.end.is_date = 0; + + p.duration.days = -1; + p.duration.weeks = -1; + p.duration.hours = -1; + p.duration.minutes = -1; + p.duration.seconds = -1; + + icalparser_yy_value = icalvalue_new_period(p); + ; + break;} +case 32: +#line 330 "../../../../libical/src/libical/icalyacc.y" +{ + struct icalperiodtype p; + + p.start = fill_datetime(yyvsp[-5].v_string,yyvsp[-3].v_string); + p.start.is_utc = utc; + p.start.is_date = 0; + + p.end.year = -1; + p.end.month = -1; + p.end.day = -1; + p.end.hour = -1; + p.end.minute = -1; + p.end.second = -1; + + /* The duration_value rule setes the global 'duration' + variable, but it also creates a new value in + icalparser_yy_value. So, free that, then copy + 'duration' into the icalperiodtype struct. */ + + p.duration = icalvalue_get_duration(icalparser_yy_value); + icalvalue_free(icalparser_yy_value); + icalparser_yy_value = 0; + + icalparser_yy_value = icalvalue_new_period(p); + + ; + break;} +case 34: +#line 364 "../../../../libical/src/libical/icalyacc.y" +{ utcsign = 1; ; + break;} +case 35: +#line 365 "../../../../libical/src/libical/icalyacc.y" +{ utcsign = -1; ; + break;} +case 36: +#line 369 "../../../../libical/src/libical/icalyacc.y" +{ + icalparser_yy_value = icalvalue_new_utcoffset( utcsign * (yyvsp[-1].v_int*3600) + (yyvsp[0].v_int*60) ); + ; + break;} +case 37: +#line 374 "../../../../libical/src/libical/icalyacc.y" +{ + icalparser_yy_value = icalvalue_new_utcoffset(utcsign * (yyvsp[-2].v_int*3600) + (yyvsp[-1].v_int*60) +(yyvsp[0].v_int)); + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 554 "/usr/share/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + yyacceptlab: + /* YYACCEPT comes here. */ +#ifndef YYSTACK_USE_ALLOCA + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } +#endif + return 0; + + yyabortlab: + /* YYABORT comes here. */ +#ifndef YYSTACK_USE_ALLOCA + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } +#endif + return 1; +} +#line 378 "../../../../libical/src/libical/icalyacc.y" + + +struct icaltimetype fill_datetime(char* datestr, char* timestr) +{ + struct icaltimetype stm; + + memset(&stm,0,sizeof(stm)); + + if (datestr != 0){ + sscanf(datestr,"%4d%2d%2d",&(stm.year), &(stm.month), + &(stm.day)); + } + + if (timestr != 0){ + sscanf(timestr,"%2d%2d%2d", &(stm.hour), &(stm.minute), + &(stm.second)); + } + + return stm; + +} + +void ical_yyerror(char* s) +{ + /*fprintf(stderr,"Parse error \'%s\'\n", s);*/ +} + diff --git a/libical/src/libical/icalyacc.h b/libical/src/libical/icalyacc.h new file mode 100644 index 0000000..f6d66bc --- a/dev/null +++ b/libical/src/libical/icalyacc.h @@ -0,0 +1,137 @@ +typedef union { + float v_float; + int v_int; + char* v_string; +} YYSTYPE; +#define DIGITS 257 +#define INTNUMBER 258 +#define FLOATNUMBER 259 +#define STRING 260 +#define EOL 261 +#define EQUALS 262 +#define CHARACTER 263 +#define COLON 264 +#define COMMA 265 +#define SEMICOLON 266 +#define MINUS 267 +#define TIMESEPERATOR 268 +#define TRUE 269 +#define FALSE 270 +#define FREQ 271 +#define BYDAY 272 +#define BYHOUR 273 +#define BYMINUTE 274 +#define BYMONTH 275 +#define BYMONTHDAY 276 +#define BYSECOND 277 +#define BYSETPOS 278 +#define BYWEEKNO 279 +#define BYYEARDAY 280 +#define DAILY 281 +#define MINUTELY 282 +#define MONTHLY 283 +#define SECONDLY 284 +#define WEEKLY 285 +#define HOURLY 286 +#define YEARLY 287 +#define INTERVAL 288 +#define COUNT 289 +#define UNTIL 290 +#define WKST 291 +#define MO 292 +#define SA 293 +#define SU 294 +#define TU 295 +#define WE 296 +#define TH 297 +#define FR 298 +#define BIT8 299 +#define ACCEPTED 300 +#define ADD 301 +#define AUDIO 302 +#define BASE64 303 +#define BINARY 304 +#define BOOLEAN 305 +#define BUSY 306 +#define BUSYTENTATIVE 307 +#define BUSYUNAVAILABLE 308 +#define CALADDRESS 309 +#define CANCEL 310 +#define CANCELLED 311 +#define CHAIR 312 +#define CHILD 313 +#define COMPLETED 314 +#define CONFIDENTIAL 315 +#define CONFIRMED 316 +#define COUNTER 317 +#define DATE 318 +#define DATETIME 319 +#define DECLINECOUNTER 320 +#define DECLINED 321 +#define DELEGATED 322 +#define DISPLAY 323 +#define DRAFT 324 +#define DURATION 325 +#define EMAIL 326 +#define END 327 +#define FINAL 328 +#define FLOAT 329 +#define FREE 330 +#define GREGORIAN 331 +#define GROUP 332 +#define INDIVIDUAL 333 +#define INPROCESS 334 +#define INTEGER 335 +#define NEEDSACTION 336 +#define NONPARTICIPANT 337 +#define OPAQUE 338 +#define OPTPARTICIPANT 339 +#define PARENT 340 +#define PERIOD 341 +#define PRIVATE 342 +#define PROCEDURE 343 +#define PUBLIC 344 +#define PUBLISH 345 +#define RECUR 346 +#define REFRESH 347 +#define REPLY 348 +#define REQPARTICIPANT 349 +#define REQUEST 350 +#define RESOURCE 351 +#define ROOM 352 +#define SIBLING 353 +#define START 354 +#define TENTATIVE 355 +#define TEXT 356 +#define THISANDFUTURE 357 +#define THISANDPRIOR 358 +#define TIME 359 +#define TRANSPAENT 360 +#define UNKNOWN 361 +#define UTCOFFSET 362 +#define XNAME 363 +#define ALTREP 364 +#define CN 365 +#define CUTYPE 366 +#define DAYLIGHT 367 +#define DIR 368 +#define ENCODING 369 +#define EVENT 370 +#define FBTYPE 371 +#define FMTTYPE 372 +#define LANGUAGE 373 +#define MEMBER 374 +#define PARTSTAT 375 +#define RANGE 376 +#define RELATED 377 +#define RELTYPE 378 +#define ROLE 379 +#define RSVP 380 +#define SENTBY 381 +#define STANDARD 382 +#define URI 383 +#define TIME_CHAR 384 +#define UTC_CHAR 385 + + +extern YYSTYPE ical_yylval; diff --git a/libical/src/libical/icalyacc.y b/libical/src/libical/icalyacc.y new file mode 100644 index 0000000..4f53d84 --- a/dev/null +++ b/libical/src/libical/icalyacc.y @@ -0,0 +1,404 @@ +%{ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalitip.y + CREATOR: eric 10 June 1999 + + DESCRIPTION: + + $Id$ + $Locker$ + + (C) COPYRIGHT 1999 Eric Busboom + http://www.softwarestudio.org + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + The original author is Eric Busboom + The original code is icalitip.y + + + + =======================================================================*/ + +#include <stdlib.h> +#include <string.h> /* for strdup() */ +#include "icalparser.h" +#include "pvl.h" + +icalvalue *icalparser_yy_value; /* Current Value */ + +void ical_yyerror(char* s); +void icalparser_clear_flex_input(); +int ical_yy_lex(void); + +/* Globals for UTCOFFSET values */ +int utc; +int utc_b; +int utcsign; + +/* Globals for DURATION values */ +struct icaldurationtype duration; + +/* Globals for TRIGGER values */ +struct icaltriggertype trigger; + +void copy_list(short* array, size_t size); +void add_prop(icalproperty_kind); +void icalparser_fill_date(struct tm* t, char* dstr); +void icalparser_fill_time(struct tm* t, char* tstr); +void set_value_type(icalvalue_kind kind); +void set_parser_value_state(); +struct icaltimetype fill_datetime(char* d, char* t); +void ical_yy_error(char *s); /* Don't know why I need this.... */ +int yylex(void); /* Or this. */ + + + +/* Set the state of the lexer so it will interpret values ( iCAL + VALUEs, that is, ) correctly. */ + +%} + +%union { + float v_float; + int v_int; + char* v_string; +} + + + /* Renaming hack */ + +/* +#define yymaxdepth ical_yy_maxdepth +#define yyparse ical_yy_parse +#define yyerror ical_yy_error +#define yylval ical_yy_lval +#define yychar ical_yy_char +#define yydebug ical_yy_debug +#define yypact ical_yy_pact +#define yyr1 ical_yy_r1 +#define yyr2 ical_yy_r2 +#define yydef ical_yy_def +#define yychk ical_yy_chk +#define yypgo ical_yy_pgo +#define yyact ical_yy_act +#define yyexca ical_yy_exca +#define yyerrflag ical_yy_errflag +#define yynerrs ical_yy_nerrs +#define yyps ical_yy_ps +#define yypv ical_yy_pv +#define yys ical_yy_s +#define yy_yys ical_yy_yys +#define yystate ical_yy_state +#define yytmp ical_yy_tmp +#define yyv ical_yy_v +#define yy_yyv ical_yy_yyv +#define yyval ical_yy_val +#define yylloc ical_yy_lloc +#define yyreds ical_yy_reds +#define yytoks ical_yy_toks +#define yylhs ical_yy_yylhs +#define yylen ical_yy_yylen +#define yydefred ical_yy_yydefred +#define yydgoto ical_yy_yydgoto +#define yydefred ical_yy_yydefred +#define yydgoto ical_yy_yydgoto +#define yysindex ical_yy_yysindex +#define yyrindex ical_yy_yyrindex +#define yygindex ical_yy_yygindex +#define yytable ical_yy_yytable +#define yycheck ical_yy_yycheck +#define yyname ical_yy_yyname +#define yyrule ical_yy_yyrule +#define yy_scan_bytes ical_yy_scan_bytes +#define yy_scan_string ical_yy_scan_string +#define yy_scan_buffer ical_yy_scan_buffer +*/ + +/* These are redefined with the -P option to flex */ +/* +#define yy_create_buffer ical_yy_create_buffer +#define yy_delete_buffer ical_yy_delete_buffer +#define yy_flex_debug ical_yy_flex_debug +#define yy_init_buffer ical_yy_init_buffer +#define yy_flush_buffer ical_yy_flush_buffer +#define yy_load_buffer_state ical_yy_load_buffer_state +#define yy_switch_to_buffer ical_yy_switch_to_buffer +#define yyin ical_yyin +#define yyleng ical_yyleng +#define yylex ical_yylex +#define yylineno ical_yylineno +#define yyout ical_yyout +#define yyrestart ical_yyrestart +#define yytext ical_yytext +#define yywrap ical_yywrap +*/ + + +%token <v_string> DIGITS +%token <v_int> INTNUMBER +%token <v_float> FLOATNUMBER +%token <v_string> STRING +%token EOL EQUALS CHARACTER COLON COMMA SEMICOLON MINUS TIMESEPERATOR + +%token TRUE FALSE + +%token FREQ BYDAY BYHOUR BYMINUTE BYMONTH BYMONTHDAY BYSECOND BYSETPOS BYWEEKNO +%token BYYEARDAY DAILY MINUTELY MONTHLY SECONDLY WEEKLY HOURLY YEARLY +%token INTERVAL COUNT UNTIL WKST MO SA SU TU WE TH FR + +%token BIT8 ACCEPTED ADD AUDIO BASE64 BINARY BOOLEAN BUSY BUSYTENTATIVE +%token BUSYUNAVAILABLE CALADDRESS CANCEL CANCELLED CHAIR CHILD COMPLETED +%token CONFIDENTIAL CONFIRMED COUNTER DATE DATETIME DECLINECOUNTER DECLINED +%token DELEGATED DISPLAY DRAFT DURATION EMAIL END FINAL FLOAT FREE GREGORIAN +%token GROUP INDIVIDUAL INPROCESS INTEGER NEEDSACTION NONPARTICIPANT +%token OPAQUE OPTPARTICIPANT PARENT PERIOD PRIVATE PROCEDURE PUBLIC PUBLISH +%token RECUR REFRESH REPLY REQPARTICIPANT REQUEST RESOURCE ROOM SIBLING +%token START TENTATIVE TEXT THISANDFUTURE THISANDPRIOR TIME TRANSPAENT +%token UNKNOWN UTCOFFSET XNAME + +%token ALTREP CN CUTYPE DAYLIGHT DIR ENCODING EVENT FBTYPE FMTTYPE LANGUAGE +%token MEMBER PARTSTAT RANGE RELATED RELTYPE ROLE RSVP SENTBY STANDARD URI + +%token TIME_CHAR UTC_CHAR + + +%% + +value: + date_value + | datetime_value + | duration_value + | period_value + | utcoffset_value + | error { + icalparser_yy_value = 0; + icalparser_clear_flex_input(); + yyclearin; + } + + +date_value: DIGITS + { + struct icaltimetype stm; + + stm = fill_datetime($1,0); + + stm.hour = -1; + stm.minute = -1; + stm.second = -1; + stm.is_utc = 0; + stm.is_date = 1; + + icalparser_yy_value = icalvalue_new_date(stm); + } + +utc_char: + /*empty*/ {utc = 0;} + | UTC_CHAR {utc = 1;} + +/* This is used in the period_value, where there may be two utc characters per rule. */ +utc_char_b: + /*empty*/ {utc_b = 0;} + | UTC_CHAR {utc_b = 1;} + +datetime_value: + DIGITS TIME_CHAR DIGITS utc_char + { + struct icaltimetype stm; + stm = fill_datetime($1, $3); + stm.is_utc = utc; + stm.is_date = 0; + + icalparser_yy_value = + icalvalue_new_datetime(stm); + } + + +/* Duration */ + + +dur_date: dur_day + | dur_day dur_time + +dur_week: DIGITS 'W' + { + duration.weeks = atoi($1); + } + +dur_time: TIME_CHAR dur_hour + { + } + | TIME_CHAR dur_minute + { + } + | TIME_CHAR dur_second + { + } + +dur_hour: DIGITS 'H' + { + duration.hours = atoi($1); + } + | DIGITS 'H' dur_minute + { + duration.hours = atoi($1); + } + +dur_minute: DIGITS 'M' + { + duration.minutes = atoi($1); + } + | DIGITS 'M' dur_second + { + duration.minutes = atoi($1); + } + +dur_second: DIGITS 'S' + { + duration.seconds = atoi($1); + } + +dur_day: DIGITS 'D' + { + duration.days = atoi($1); + } + +dur_prefix: /* empty */ + { + duration.is_neg = 0; + } + | '+' + { + duration.is_neg = 0; + } + | '-' + { + duration.is_neg = 1; + } + +duration_value: dur_prefix 'P' dur_date + { + icalparser_yy_value = icalvalue_new_duration(duration); + memset(&duration,0, sizeof(duration)); + } + | dur_prefix 'P' dur_time + { + icalparser_yy_value = icalvalue_new_duration(duration); + memset(&duration,0, sizeof(duration)); + } + | dur_prefix 'P' dur_week + { + icalparser_yy_value = icalvalue_new_duration(duration); + memset(&duration,0, sizeof(duration)); + } + + +/* Period */ + +period_value: DIGITS TIME_CHAR DIGITS utc_char '/' DIGITS TIME_CHAR DIGITS utc_char_b + { + struct icalperiodtype p; + + p.start = fill_datetime($1,$3); + p.start.is_utc = utc; + p.start.is_date = 0; + + + p.end = fill_datetime($6,$8); + p.end.is_utc = utc_b; + p.end.is_date = 0; + + p.duration.days = -1; + p.duration.weeks = -1; + p.duration.hours = -1; + p.duration.minutes = -1; + p.duration.seconds = -1; + + icalparser_yy_value = icalvalue_new_period(p); + } + | DIGITS TIME_CHAR DIGITS utc_char '/' duration_value + { + struct icalperiodtype p; + + p.start = fill_datetime($1,$3); + p.start.is_utc = utc; + p.start.is_date = 0; + + p.end.year = -1; + p.end.month = -1; + p.end.day = -1; + p.end.hour = -1; + p.end.minute = -1; + p.end.second = -1; + + /* The duration_value rule setes the global 'duration' + variable, but it also creates a new value in + icalparser_yy_value. So, free that, then copy + 'duration' into the icalperiodtype struct. */ + + p.duration = icalvalue_get_duration(icalparser_yy_value); + icalvalue_free(icalparser_yy_value); + icalparser_yy_value = 0; + + icalparser_yy_value = icalvalue_new_period(p); + + } + + +trigger: + + + +/* UTC Offset */ + +plusminus: '+' { utcsign = 1; } + | '-' { utcsign = -1; } + +utcoffset_value: + plusminus INTNUMBER INTNUMBER + { + icalparser_yy_value = icalvalue_new_utcoffset( utcsign * ($2*3600) + ($3*60) ); + } + + | plusminus INTNUMBER INTNUMBER INTNUMBER + { + icalparser_yy_value = icalvalue_new_utcoffset(utcsign * ($2*3600) + ($3*60) +($4)); + } + +%% + +struct icaltimetype fill_datetime(char* datestr, char* timestr) +{ + struct icaltimetype stm; + + memset(&stm,0,sizeof(stm)); + + if (datestr != 0){ + sscanf(datestr,"%4d%2d%2d",&(stm.year), &(stm.month), + &(stm.day)); + } + + if (timestr != 0){ + sscanf(timestr,"%2d%2d%2d", &(stm.hour), &(stm.minute), + &(stm.second)); + } + + return stm; + +} + +void ical_yyerror(char* s) +{ + /*fprintf(stderr,"Parse error \'%s\'\n", s);*/ +} + diff --git a/libical/src/libical/libical.pro b/libical/src/libical/libical.pro new file mode 100644 index 0000000..9cc3983 --- a/dev/null +++ b/libical/src/libical/libical.pro @@ -0,0 +1,68 @@ +include(../../../variables.pri) + +TEMPLATE = lib + +TARGET = ical +DESTDIR = ../../lib + +win32: DEFINES += _WIN32 + +CONFIG += staticlib + +HEADERS = \ + icalattendee.h \ + icalcomponent.h \ + icalderivedparameter.h \ + icalderivedproperty.h \ + icalderivedvalue.h \ + icalduration.h \ + icalenums.h \ + icalerror.h \ + icallangbind.h \ + icalmemory.h \ + icalmime.h \ + icalparameter.h \ + icalparameterimpl.h \ + icalparser.h \ + icalperiod.h \ + icalproperty.h \ + icalrecur.h \ + icalrestriction.h \ + icaltime.h \ + icaltypes.h \ + icalvalue.h \ + icalvalueimpl.h \ + icalversion.h \ + icalyacc.h \ + pvl.h \ + sspm.h + +SOURCES = icalattendee.c \ + icalcomponent.c \ + icalderivedparameter.c \ + icalderivedproperty.c \ + icalderivedvalue.c \ + icalduration.c \ + icalenums.c \ + icalerror.c \ + icallangbind.c \ + icallexer.c \ + icalmemory.c \ + icalmime.c \ + icalparameter.c \ + icalparser.c \ + icalperiod.c \ + icalproperty.c \ + icalrecur.c \ + icalrestriction.c \ + icaltime.c \ + icaltypes.c \ + icalvalue.c \ + icalyacc.c \ + pvl.c \ + sspm.c \ + vsnprintf.c + +INTERFACES = + +INCLUDEPATH += . diff --git a/libical/src/libical/libicalE.pro b/libical/src/libical/libicalE.pro new file mode 100644 index 0000000..2b9b720 --- a/dev/null +++ b/libical/src/libical/libicalE.pro @@ -0,0 +1,66 @@ +TEMPLATE = lib +CONFIG = warn_on staticlib + +INCLUDEPATH += . +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR=../../lib/$(PLATFORM) +TARGET = ical +INTERFACES = \ + +HEADERS = \ + ical.h \ + icalattendee.h \ + icalcomponent.h \ + icalderivedparameter.h \ + icalderivedproperty.h \ + icalderivedvalue.h \ + icalduration.h \ + icalenums.h \ + icalerror.h \ + icallangbind.h \ + icalmemory.h \ + icalmime.h \ + icalparameter.h \ + icalparameterimpl.h \ + icalparser.h \ + icalperiod.h \ + icalproperty.h \ + icalrecur.h \ + icalrestriction.h \ + icaltime.h \ + icaltypes.h \ + icalvalue.h \ + icalvalueimpl.h \ + icalversion.h \ + icalyacc.h \ + pvl.h \ + sspm.h \ + +SOURCES = \ + icalattendee.c \ + icalcomponent.c \ + icalderivedparameter.c \ + icalderivedproperty.c \ + icalderivedvalue.c \ + icalduration.c \ + icalenums.c \ + icalerror.c \ + icallangbind.c \ + icallexer.c \ + icalmemory.c \ + icalmime.c \ + icalparameter.c \ + icalparser.c \ + icalperiod.c \ + icalproperty.c \ + icalrecur.c \ + icalrestriction.c \ + icaltime.c \ + icaltypes.c \ + icalvalue.c \ + icalyacc.c \ + pvl.c \ + sspm.c \ + vsnprintf.c \ + diff --git a/libical/src/libical/pvl.c b/libical/src/libical/pvl.c new file mode 100644 index 0000000..2a733e8 --- a/dev/null +++ b/libical/src/libical/pvl.c @@ -0,0 +1,761 @@ +/*====================================================================== + FILE: pvl.c + CREATOR: eric November, 1995 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org +======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pvl.h" +#include <errno.h> +#include <assert.h> +#include <stdlib.h> + + + +/* + struct pvl_list_t + + The list structure. This is the hanlde for the entire list + + This type is also private. Use pvl_list instead + + */ + +typedef struct pvl_list_t +{ + int MAGIC; /* Magic Identifier */ + struct pvl_elem_t *head; /* Head of list */ + struct pvl_elem_t *tail; /* Tail of list */ + int count; /* Number of items in the list */ + struct pvl_elem_t *p; /* Pointer used for iterators */ +} pvl_list_t; + + + + +/* This global is incremented for each call to pvl_new_element(); it gives each + * list a unique identifer */ + +int pvl_elem_count = 0; +int pvl_list_count = 0; + + +/*---------------------------------------------------------------------- + Function: pvl_list pvl_newlist() + + Purpose: + + Creates a new list, clears the pointers and assigns a magic number + + Returns: + + Pointer to the new list + 0 if there is no available memory. + *----------------------------------------------------------------------*/ + +pvl_list +pvl_newlist() +{ + struct pvl_list_t *L; + + if ( ( L = (struct pvl_list_t*)malloc(sizeof(struct pvl_list_t))) == 0) + { + errno = ENOMEM; + return 0; + } + + L->MAGIC = pvl_list_count; + pvl_list_count++; + L->head = 0; + L->tail = 0; + L->count = 0; + L->p = 0; + + return L; +} + +void +pvl_free(pvl_list l) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + + pvl_clear(l); + + free(L); +} + +/*---------------------------------------------------------------------- + Function: pvl_new_element(void *d, struct pvl_elem_t *next,struct pvl_elem_t *prior) + + Purpose: + Creates a new list element, assigns a magic number, and assigns + the next and previous pointers. + + Passing in the next and previous points may seem odd, but it allos the user + to set them while keeping the internal data hidden. In nearly all cases, + the user is the pvl library itself. + + Parameters: + + d The data item to be stored in the list + next Pointer value to assign to the member "next" + prior Pointer value to assign to the member "prior" + + Returns: + + A pointer to the new element. + 0 if there is no memory available. + + *----------------------------------------------------------------------*/ + +pvl_elem +pvl_new_element(void *d, pvl_elem next,pvl_elem prior) +{ + struct pvl_elem_t *E; + + if ( ( E = (struct pvl_elem_t*)malloc(sizeof(struct pvl_elem_t))) == 0) + { + errno = ENOMEM; + return 0; + } + + E->MAGIC = pvl_elem_count++; + E->d = d; + E->next = next; + E->prior = prior; + + return (pvl_elem)E; +} + +/*---------------------------------------------------------------------- + Function: pvl_unshift(pvl_list l,void *d) + + Purpose: + + Add a new element to the from of the list + + Parameters: + + l The list to add the item to + d Pointer to the item to add + + Returns: + *----------------------------------------------------------------------*/ + +void +pvl_unshift(pvl_list l,void *d) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + struct pvl_elem_t *E = pvl_new_element(d,L->head,0); + + if (E->next != 0) + { + /* Link the head node to it */ + E->next->prior = E; + } + + /* move the head */ + L->head = E; + + /* maybe move the tail */ + + if (L->tail == 0) + { + L->tail = E; + } + + L->count++; +} + +/*---------------------------------------------------------------------- + Function: pvl_shift(pvl_list l) + + Purpose: + + Remove an element from the front of the list + + Parameters: + + l The list to operate on + + Returns: + *----------------------------------------------------------------------*/ + +void* +pvl_shift(pvl_list l) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + + if (L->head == 0) + { + return 0; + } + + return pvl_remove(l,(void*)L->head); + +} + +/*---------------------------------------------------------------------- + Function: void pvl_push(pvl_list l,void *d) + + Purpose: + + Add a new item to the tail of the list + + Paramters: + + l The list to operate on + d Pointer to the item to add + + Returns: + *----------------------------------------------------------------------*/ + +void +pvl_push(pvl_list l,void *d) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + struct pvl_elem_t *E = pvl_new_element(d,0,L->tail); + + /* These are done in pvl_new_element + E->next = 0; + E->prior = L->tail; + */ + + if (L->tail != 0) + { + L->tail->next = E; + } + + if (L->head == 0) + { + L->head = E; + } + + L->tail = E; + + L->count++; + +} + +/*---------------------------------------------------------------------- + Function: void* pvl_pop(pvl_list l) + + Purpose: + + Remove an element from the tail of the list + + Paramters: + + l The list to operate on + + Returns: + *----------------------------------------------------------------------*/ + +void* +pvl_pop(pvl_list l) +{ + + struct pvl_list_t *L = (struct pvl_list_t *)l; + + if ( L->tail == 0) + { + return 0; + } + + return pvl_remove(l,(void*) L->tail);; + +} + + +/*---------------------------------------------------------------------- + Function: void pvl_insert_ordered(pvl_list l,pvl_comparef f,void *d) + + Purpose: + + Add a new item to a list that is ordered by a comparison function. + This routine assumes that the list is properly ordered. + + l The list to operate on + f Pointer to a comparison function + d Pointer to data to pass to the comparison function + + Returns: + + void + + *----------------------------------------------------------------------*/ + +void +pvl_insert_ordered(pvl_list l,pvl_comparef f,void *d) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + + struct pvl_elem_t *P; + + L->count++; + + /* Empty list, add to head */ + + if(L->head == 0) + { + pvl_unshift(l,d); + return; + } + + /* smaller than head, add to head */ + + if ( ((*f)(d,L->head->d)) <= 0) + { + pvl_unshift(l,d); + return; + } + + /* larger than tail, add to tail */ + if ( (*f)(d,L->tail->d) >= 0) + { + pvl_push(l,d); + return; + } + + + /* Search for the first element that is smaller, and add before it */ + + for (P=L->head; P != 0; P = P->next) + { + if ( (*f)(P->d,d) >= 0) + { + pvl_insert_before(l,P,d); + return; + } + } + + /* badness, choke */ + + assert(0); + +} + +/*---------------------------------------------------------------------- + Function: void pvl_insert_after(pvl_list l,pvl_elem p,void *d) + + Purpose: + + Add a new item after the referenced element. + + Parameters: + + l The list to operate on + p The list element to add the item after + d Pointer to the item to add. + + Returns: + + void + + *----------------------------------------------------------------------*/ + +void +pvl_insert_after(pvl_list l,pvl_elem p,void *d) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + struct pvl_elem_t *P = (struct pvl_elem_t *)p; + struct pvl_elem_t *E = 0; + + L->count++; + + if (P == 0) + { + pvl_unshift(l,d); + return; + } + + if ( P == L->tail) + { + E = pvl_new_element(d,0,P); + L->tail = E; + E->prior->next = E; + } + else + { + E = pvl_new_element(d,P->next,P); + E->next->prior = E; + E->prior->next = E; + } +} + +/*---------------------------------------------------------------------- + Function: void pvl_insert_before(pvl_list l,pvl_elem p,void *d) + + Purpose: + + Add an item after a referenced item + + Parameters: + + l The list to operate on + p The list element to add the item before + d Pointer to the data to be added. + + Returns: + *----------------------------------------------------------------------*/ + +void +pvl_insert_before(pvl_list l,pvl_elem p,void *d) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + struct pvl_elem_t *P = (struct pvl_elem_t *)p; + struct pvl_elem_t *E = 0; + + L->count++; + + if (P == 0) + { + pvl_unshift(l,d); + return; + } + + if ( P == L->head) + { + E = pvl_new_element(d,P,0); + E->next->prior = E; + L->head = E; + } + else + { + E = pvl_new_element(d,P,P->prior); + E->prior->next = E; + E->next->prior = E; + } +} + +/*---------------------------------------------------------------------- + Function: void pvl_remove(pvl_list l,pvl_elem e) + + Purpose: + + Remove the referenced item from the list + + This routine will free the element, but not the data item that the + element contains. + + Parameters: + + l The list to operate on + e The element to remove. + + Returns: + *----------------------------------------------------------------------*/ + +void* +pvl_remove(pvl_list l,pvl_elem e) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + struct pvl_elem_t *E = (struct pvl_elem_t *)e; + void* data; + + if (E == L->head) + { + if (E->next != 0) + { + E->next->prior = 0; + L->head = E->next; + } else { + /* E Also points to tail -> only one element in list */ + L->tail = 0; + L->head = 0; + } + } + else if (E == L->tail) + { + if (E->prior != 0) + { + E->prior->next = 0; + L->tail = E->prior; + } else { + /* E points to the head, so it was the last element */ + /* This case should be taken care of in the previous clause */ + L->head = 0; + L->tail = 0; + } + } + else + { + E->prior->next = E->next; + E->next->prior = E->prior; + } + + + L->count--; + + data = E->d; + + E->prior = 0; + E->next = 0; + E->d = 0; + + free(E); + + return data; + +} + +/*---------------------------------------------------------------------- + Function: pvl_elem pvl_find(pvl_list l,pvl_findf f,void* v) + + Purpose: + + Return a pointer to data that satisfies a function + + This routine will interate through the entire list and call the + find function for each item. It will break and return a pointer to the + data that causes the find function to return 1. + + Parameters: + + l The list to operate on + f Pointer to the find function + v Pointer to constant data to pass into the function + + Returns: + + Pointer to the element that the find function found. + + *----------------------------------------------------------------------*/ + +pvl_elem +pvl_find(pvl_list l,pvl_findf f,void* v) +{ + pvl_elem e; + + for (e=pvl_head(l); e!= 0; e = pvl_next(e)) + { + if ( (*f)(((struct pvl_elem_t *)e)->d,v) == 1) + { + /* Save this elem for a call to find_next */ + ((struct pvl_list_t *)l)->p = e; + return e; + } + } + + return 0; + +} +/*---------------------------------------------------------------------- + Function: void* pvl_find_next(pvl_list l,pvl_findf f,void* v) + + Purpose: + + Like pvl_find(), but continues the search where the last find() or + find_next() left off + + Parameters: + + l The list to operate on + f Pointer to the find function + v Pointer to constant data to pass into the function + + Returns: + + Pointer to the element that the find function found. + + *----------------------------------------------------------------------*/ + +pvl_elem +pvl_find_next(pvl_list l,pvl_findf f,void* v) +{ + + pvl_elem e; + + for (e=pvl_head(l); e!= 0; e = pvl_next(e)) + { + if ( (*f)(((struct pvl_elem_t *)e)->d,v) == 1) + { + /* Save this elem for a call to find_next */ + ((struct pvl_list_t *)l)->p = e; + return e; + } + } + + return 0; + +} + +/*---------------------------------------------------------------------- + Function: void pvl_clear(pvl_list l) + + Purpose: + + Remove the all the elements in the list. The does not free the data items + the elements hold. + + + Returns: + *----------------------------------------------------------------------*/ + +void +pvl_clear(pvl_list l) +{ + pvl_elem e = pvl_head(l); + pvl_elem next; + + if (e == 0) { + return; + } + + while(e != 0) + { + next = pvl_next(e); + pvl_remove(l,e); + e = next; + } +} + +/*---------------------------------------------------------------------- + Function: int pvl_count(pvl_list l) + + Purpose: + + Returns the number of items in the list. + + Returns: + *----------------------------------------------------------------------*/ + +int +pvl_count(pvl_list l) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + + return L->count; +} + + +/*---------------------------------------------------------------------- + Function: pvl_elem pvl_next(pvl_elem e) + + Purpose: + Returns a pointer to the given element + + Returns: + *----------------------------------------------------------------------*/ + +pvl_elem +pvl_next(pvl_elem e) +{ + struct pvl_elem_t *E = (struct pvl_elem_t *)e; + + if (E == 0){ + return 0; + } + + return (pvl_elem)E->next; +} + +/*---------------------------------------------------------------------- + Function: pvl_elem pvl_prior(pvl_elem e) + + Purpose: + + Returns a pointer to the element previous to the element given. + + Returns: + *----------------------------------------------------------------------*/ + +pvl_elem +pvl_prior(pvl_elem e) +{ + struct pvl_elem_t *E = (struct pvl_elem_t *)e; + + return (pvl_elem)E->prior; +} + +/*---------------------------------------------------------------------- + Function: pvl_elem pvl_head(pvl_list l ) + + Purpose: + + Returns a pointer to the first item in the list. + + Returns: + *----------------------------------------------------------------------*/ +pvl_elem +pvl_head(pvl_list l ) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + + return (pvl_elem)L->head; +} + +/*---------------------------------------------------------------------- + Function: pvl_elem pvl_tail(pvl_list l) + + Purpose: + + Returns a pointer to the last item in the list. + + Returns: + *----------------------------------------------------------------------*/ +pvl_elem +pvl_tail(pvl_list l) +{ + struct pvl_list_t *L = (struct pvl_list_t *)l; + return (pvl_elem)L->tail; +} + +/*---------------------------------------------------------------------- + Function: + + + Purpose: + + + Returns: + *----------------------------------------------------------------------*/ + +#ifndef PVL_USE_MACROS +void* +pvl_data(pvl_elem e) +{ + struct pvl_elem_t *E = (struct pvl_elem_t *)e; + + if ( e == 0){ + return 0; + } + + return E->d; +} +#endif + +/*---------------------------------------------------------------------- + Function: void pvl_apply(pvl_list l,pvl_applyf f, void *v) + + Purpose: + + Call a function for every item in the list. + + Paramters: + + l The list to operate on + f Pointer to the function to call + v Data to pass to the function on every iteration + + Returns: + + void + *----------------------------------------------------------------------*/ + +void +pvl_apply(pvl_list l,pvl_applyf f, void *v) +{ + pvl_elem e; + + for (e=pvl_head(l); e!= 0; e = pvl_next(e)) + { + (*f)(((struct pvl_elem_t *)e)->d,v); + } + +} diff --git a/libical/src/libical/pvl.h b/libical/src/libical/pvl.h new file mode 100644 index 0000000..14a15a1 --- a/dev/null +++ b/libical/src/libical/pvl.h @@ -0,0 +1,94 @@ +/*====================================================================== + FILE: pvl.h + CREATOR: eric November, 1995 + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org +======================================================================*/ + + +#ifndef __PVL_H__ +#define __PVL_H__ + +typedef void* pvl_list; +typedef void* pvl_elem; + +/* + struct pvl_elem_t + + This type is private. Always use pvl_elem instead. The struct would + not even appear in this header except to make code in the USE_MACROS + blocks work + + */ +typedef struct pvl_elem_t +{ + int MAGIC; /* Magic Identifier */ + void *d; /* Pointer to data user is storing */ + struct pvl_elem_t *next; /* Next element */ + struct pvl_elem_t *prior; /* prior element */ +} pvl_elem_t; + + + +/* This global is incremented for each call to pvl_new_element(); it gives each + * list a unique identifer */ + +extern int pvl_elem_count; +extern int pvl_list_count; + +/* Create new lists or elements */ +pvl_elem pvl_new_element(void* d, pvl_elem next,pvl_elem prior); +pvl_list pvl_newlist(void); +void pvl_free(pvl_list); + +/* Add, remove, or get the head of the list */ +void pvl_unshift(pvl_list l,void *d); +void* pvl_shift(pvl_list l); +pvl_elem pvl_head(pvl_list); + +/* Add, remove or get the tail of the list */ +void pvl_push(pvl_list l,void *d); +void* pvl_pop(pvl_list l); +pvl_elem pvl_tail(pvl_list); + +/* Insert elements in random places */ +typedef int (*pvl_comparef)(void* a, void* b); /* a, b are of the data type*/ +void pvl_insert_ordered(pvl_list l,pvl_comparef f,void *d); +void pvl_insert_after(pvl_list l,pvl_elem e,void *d); +void pvl_insert_before(pvl_list l,pvl_elem e,void *d); + +/* Remove an element, or clear the entire list */ +void* pvl_remove(pvl_list,pvl_elem); /* Remove element, return data */ +void pvl_clear(pvl_list); /* Remove all elements, de-allocate all data */ + +int pvl_count(pvl_list); + +/* Navagate the list */ +pvl_elem pvl_next(pvl_elem e); +pvl_elem pvl_prior(pvl_elem e); + +/* get the data in the list */ +#ifndef PVL_USE_MACROS +void* pvl_data(pvl_elem); +#else +#define pvl_data(x) x==0 ? 0 : ((struct pvl_elem_t *)x)->d; +#endif + + +/* Find an element for which a function returns true */ +typedef int (*pvl_findf)(void* a, void* b); /*a is list elem, b is other data*/ +pvl_elem pvl_find(pvl_list l,pvl_findf f,void* v); +pvl_elem pvl_find_next(pvl_list l,pvl_findf f,void* v); + +/* Pass each element in the list to a function */ +typedef void (*pvl_applyf)(void* a, void* b); /*a is list elem, b is other data*/ +void pvl_apply(pvl_list l,pvl_applyf f, void *v); + + +#endif /* __PVL_H__ */ + + + + + diff --git a/libical/src/libical/sspm.c b/libical/src/libical/sspm.c new file mode 100644 index 0000000..2df581b --- a/dev/null +++ b/libical/src/libical/sspm.c @@ -0,0 +1,1621 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: sspm.c Parse Mime + CREATOR: eric 25 June 2000 + + $Id$ + $Locker$ + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Initial Developer of the Original Code is Eric Busboom + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + ======================================================================*/ + +#include <stdio.h> +#include <string.h> +#include "sspm.h" +#include <assert.h> +#include <ctype.h> /* for tolower */ +#include <stdlib.h> /* for malloc, free */ +#include <string.h> /* for strcasecmp */ + +// Eugen C. <eug@thekompany.com> +#ifdef _WIN32 +#define strcasecmp _stricmp +#endif +// Eugen C. <eug@thekompany.com> + +int snprintf(char *str, size_t n, char const *fmt, ...); + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define TMP_BUF_SIZE 1024 + + +enum mime_state { + UNKNOWN_STATE, + IN_HEADER, + END_OF_HEADER, + IN_BODY, + OPENING_PART, + END_OF_PART, + TERMINAL_END_OF_PART, + END_OF_INPUT +}; + +struct mime_impl{ + struct sspm_part *parts; + size_t max_parts; + int part_no; + int level; + struct sspm_action_map *actions; + char* (*get_string)(char *s, size_t size, void* data); + void* get_string_data; + char temp[TMP_BUF_SIZE]; + enum mime_state state; +}; + +void sspm_free_header(struct sspm_header *header); +void* sspm_make_multipart_part(struct mime_impl *impl,struct sspm_header *header); +void sspm_read_header(struct mime_impl *impl,struct sspm_header *header); + +char* sspm_strdup(char* str){ + + char* s; + + s = strdup(str); + + return s; +} + + +struct major_content_type_map +{ + enum sspm_major_type type; + char* str; + +} major_content_type_map[] = +{ + {SSPM_MULTIPART_MAJOR_TYPE,"multipart" }, + {SSPM_TEXT_MAJOR_TYPE,"text" }, + {SSPM_TEXT_MAJOR_TYPE,"text" }, + {SSPM_IMAGE_MAJOR_TYPE,"image" }, + {SSPM_AUDIO_MAJOR_TYPE,"audio" }, + {SSPM_VIDEO_MAJOR_TYPE,"video" }, + {SSPM_APPLICATION_MAJOR_TYPE,"application" }, + {SSPM_MULTIPART_MAJOR_TYPE,"multipart" }, + {SSPM_MESSAGE_MAJOR_TYPE,"message" }, + {SSPM_UNKNOWN_MAJOR_TYPE,"" }, +}; + +struct minor_content_type_map +{ + enum sspm_minor_type type; + char* str; + +} minor_content_type_map[] = +{ + {SSPM_ANY_MINOR_TYPE,"*" }, + {SSPM_PLAIN_MINOR_TYPE,"plain" }, + {SSPM_RFC822_MINOR_TYPE,"rfc822" }, + {SSPM_DIGEST_MINOR_TYPE,"digest" }, + {SSPM_CALENDAR_MINOR_TYPE,"calendar" }, + {SSPM_MIXED_MINOR_TYPE,"mixed" }, + {SSPM_RELATED_MINOR_TYPE,"related" }, + {SSPM_ALTERNATIVE_MINOR_TYPE,"alternative" }, + {SSPM_PARALLEL_MINOR_TYPE, "parallel" }, + {SSPM_UNKNOWN_MINOR_TYPE,"" } +}; + + + +struct encoding_map { + enum sspm_encoding encoding; + char* str; +} sspm_encoding_map[] = +{ + {SSPM_NO_ENCODING,""}, + {SSPM_QUOTED_PRINTABLE_ENCODING,"quoted-printable"}, + {SSPM_8BIT_ENCODING,"8bit"}, + {SSPM_7BIT_ENCODING,"7bit"}, + {SSPM_BINARY_ENCODING,"binary"}, + {SSPM_BASE64_ENCODING,"base64"}, + {SSPM_UNKNOWN_ENCODING,""} + +}; + + +char* sspm_get_parameter(char* line, char* parameter) +{ + char *p,*s,*q; + static char name[1024]; + + /* Find where the parameter name is in the line */ + p = strstr(line,parameter); + + if( p == 0){ + return 0; + } + + /* skip over the parameter name, the '=' and any blank spaces */ + + p+=strlen(parameter); + + while(*p==' ' || *p == '='){ + p++; + } + + /*now find the next semicolon*/ + + s = strchr(p,';'); + + /* Strip of leading quote */ + q = strchr(p,'\"'); + + if(q !=0){ + p = q+1; + } + + if(s != 0){ + strncpy(name,p,(size_t)s-(size_t)p); + } else { + strcpy(name,p); + } + + /* Strip off trailing quote, if it exists */ + + q = strrchr(name,'\"'); + + if (q != 0){ + *q='\0'; + } + + return name; +} + +char* sspm_property_name(char* line) +{ + static char name[1024]; + char *c = strchr(line,':'); + + if(c != 0){ + strncpy(name,line,(size_t)c-(size_t)line); + name[(size_t)c-(size_t)line] = '\0'; + return name; + } else { + return 0; + } +} + +char* sspm_value(char* line) +{ + static char value[1024]; + + char *c,*s, *p; + + /* Find the first colon and the next semicolon */ + + c = strchr(line,':'); + s = strchr(c,';'); + + /* Skip the colon */ + c++; + + if (s == 0){ + s = c+strlen(line); + } + + for(p=value; c != s; c++){ + if(*c!=' ' && *c!='\n'){ + *(p++) = *c; + } + } + + *p='\0'; + + return value; + +} + +char *mime_headers[] = { + "Content-Type", + "Content-Transfer-Encoding", + "Content-Disposition", + "Content-Id", + "Mime-Version", + 0 +}; + + +void* sspm_default_new_part() +{ + return 0; +} +void sspm_default_add_line(void *part, struct sspm_header *header, + char* line, size_t size) +{ +} + +void* sspm_default_end_part(void* part) +{ + return 0; +} + +void sspm_default_free_part(void *part) +{ +} + + + +struct sspm_action_map sspm_action_map[] = +{ + {SSPM_UNKNOWN_MAJOR_TYPE,SSPM_UNKNOWN_MINOR_TYPE,sspm_default_new_part,sspm_default_add_line,sspm_default_end_part,sspm_default_free_part}, +}; + +int sspm_is_mime_header(char *line) +{ + char *name = sspm_property_name(line); + int i; + + if(name == 0){ + return 0; + } + + for(i = 0; mime_headers[i] != 0; i++){ + if(strcasecmp(name, mime_headers[i]) == 0) + return 1; + } + + return 0; +} + +int sspm_is_mail_header(char* line) +{ + char *name = sspm_property_name(line); + + if (name != 0){ + return 1; + } + + return 0; + +} + +int sspm_is_blank(char* line) +{ + char *p; + char c =0; + + for(p=line; *p!=0; p++){ + if( ! (*p == ' '|| *p == '\t' || *p=='\n') ){ + c++; + } + } + + if (c==0){ + return 1; + } + + return 0; + +} + +int sspm_is_continuation_line(char* line) +{ + if (line[0] == ' '|| line[0] == '\t' ) { + return 1; + } + + return 0; +} + +int sspm_is_mime_boundary(char *line) +{ + if( line[0] == '-' && line[1] == '-') { + return 1; + } + + return 0; +} + +int sspm_is_mime_terminating_boundary(char *line) +{ + + + if (sspm_is_mime_boundary(line) && + strstr(line,"--\n")){ + return 1; + } + + return 0; +} + +enum line_type { + EMPTY, + BLANK, + MIME_HEADER, + MAIL_HEADER, + HEADER_CONTINUATION, + BOUNDARY, + TERMINATING_BOUNDARY, + UNKNOWN_TYPE +}; + + +enum line_type get_line_type(char* line){ + + if (line == 0){ + return EMPTY; + } else if(sspm_is_blank(line)){ + return BLANK; + } else if (sspm_is_mime_header(line)){ + return MIME_HEADER; + } else if (sspm_is_mail_header(line)){ + return MAIL_HEADER; + } else if (sspm_is_continuation_line(line)){ + return HEADER_CONTINUATION; + } else if (sspm_is_mime_terminating_boundary(line)){ + return TERMINATING_BOUNDARY; + } else if (sspm_is_mime_boundary(line)) { + return BOUNDARY; + } else { + return UNKNOWN_TYPE; + } + + +} + + +struct sspm_action_map get_action(struct mime_impl *impl, + enum sspm_major_type major, + enum sspm_minor_type minor) +{ + int i; + + /* Read caller suppled action map */ + + if (impl->actions != 0){ + for(i=0; impl->actions[i].major != SSPM_UNKNOWN_MAJOR_TYPE; i++){ + if((major == impl->actions[i].major && + minor == impl->actions[i].minor) || + (major == impl->actions[i].major && + minor == SSPM_ANY_MINOR_TYPE)){ + return impl->actions[i]; + } + } + } + + /* Else, read default action map */ + + for(i=0; sspm_action_map[i].major != SSPM_UNKNOWN_MAJOR_TYPE; i++){ + if((major == sspm_action_map[i].major && + minor == sspm_action_map[i].minor) || + (major == sspm_action_map[i].major && + minor == SSPM_ANY_MINOR_TYPE)){ + break; + } + } + + return sspm_action_map[i]; +} + + +char* sspm_lowercase(char* str) +{ + char* p = 0; + char* new = sspm_strdup(str); + + if(str ==0){ + return 0; + } + + for(p = new; *p!=0; p++){ + *p = tolower(*p); + } + + return new; +} + +enum sspm_major_type sspm_find_major_content_type(char* type) +{ + int i; + + char* ltype = sspm_lowercase(type); + + for (i=0; major_content_type_map[i].type != SSPM_UNKNOWN_MINOR_TYPE; i++){ + if(strncmp(ltype, major_content_type_map[i].str, + strlen(major_content_type_map[i].str))==0){ + free(ltype); + return major_content_type_map[i].type; + } + } + free(ltype); + return major_content_type_map[i].type; /* Should return SSPM_UNKNOWN_MINOR_TYPE */ +} + +enum sspm_minor_type sspm_find_minor_content_type(char* type) +{ + int i; + char* ltype = sspm_lowercase(type); + + char *p = strchr(ltype,'/'); + + if (p==0){ + return SSPM_UNKNOWN_MINOR_TYPE; + } + + p++; /* Skip the '/' */ + + for (i=0; minor_content_type_map[i].type != SSPM_UNKNOWN_MINOR_TYPE; i++){ + if(strncmp(p, minor_content_type_map[i].str, + strlen(minor_content_type_map[i].str))==0){ + free(ltype); + return minor_content_type_map[i].type; + } + } + + free(ltype); + return minor_content_type_map[i].type; /* Should return SSPM_UNKNOWN_MINOR_TYPE */ +} + +char* sspm_major_type_string(enum sspm_major_type type) +{ + int i; + + for (i=0; major_content_type_map[i].type != SSPM_UNKNOWN_MINOR_TYPE; + i++){ + + if(type == major_content_type_map[i].type){ + return major_content_type_map[i].str; + } + } + + return major_content_type_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */ +} + +char* sspm_minor_type_string(enum sspm_minor_type type) +{ + int i; + for (i=0; minor_content_type_map[i].type != SSPM_UNKNOWN_MINOR_TYPE; + i++){ + if(type == minor_content_type_map[i].type){ + return minor_content_type_map[i].str; + } + } + + return minor_content_type_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */ +} + + +char* sspm_encoding_string(enum sspm_encoding type) +{ + int i; + for (i=0; sspm_encoding_map[i].encoding != SSPM_UNKNOWN_ENCODING; + i++){ + if(type == sspm_encoding_map[i].encoding){ + return sspm_encoding_map[i].str; + } + } + + return sspm_encoding_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */ +} + +/* Interpret a header line and add its data to the header + structure. */ +void sspm_build_header(struct sspm_header *header, char* line) +{ + char *prop; + char *val; + + val = sspm_strdup(sspm_value(line)); + prop = sspm_strdup(sspm_property_name(line)); + + if(strcmp(prop,"Content-Type") == 0){ + + /* Create a new mime_header, fill in content-type + and possibly boundary */ + + char* boundary= sspm_get_parameter(line,"boundary"); + + header->def = 0; + header->major = sspm_find_major_content_type(val); + header->minor = sspm_find_minor_content_type(val); + + if(header->minor == SSPM_UNKNOWN_MINOR_TYPE){ + char *p = strchr(val,'/'); + + if (p != 0){ + p++; /* Skip the '/' */ + + header->minor_text = sspm_strdup(p); + } else { + /* Error, malformed content type */ + header->minor_text = sspm_strdup("unknown"); + } + } + if (boundary != 0){ + header->boundary = sspm_strdup(boundary); + } + + } else if(strcmp(prop,"Content-Transfer-Encoding")==0){ + char* encoding = sspm_value(line); + char* lencoding = sspm_lowercase(encoding); + + if(strcmp(lencoding,"base64")==0){ + header->encoding = SSPM_BASE64_ENCODING; + } else if(strcmp(lencoding,"quoted-printable")==0){ + header->encoding = SSPM_QUOTED_PRINTABLE_ENCODING; + } else if(strcmp(lencoding,"binary")==0){ + header->encoding = SSPM_BINARY_ENCODING; + } else if(strcmp(lencoding,"7bit")==0){ + header->encoding = SSPM_7BIT_ENCODING; + } else if(strcmp(lencoding,"8bit")==0){ + header->encoding = SSPM_8BIT_ENCODING; + } else { + header->encoding = SSPM_UNKNOWN_ENCODING; + } + + + free(lencoding); + + header->def = 0; + + } else if(strcmp(prop,"Content-Id")==0){ + char* cid = sspm_value(line); + header->content_id = sspm_strdup(cid); + header->def = 0; + + } + free(val); + free(prop); +} + +char* sspm_get_next_line(struct mime_impl *impl) +{ + char* s; + s = impl->get_string(impl->temp,TMP_BUF_SIZE,impl->get_string_data); + + if(s == 0){ + impl->state = END_OF_INPUT; + } + return s; +} + + +void sspm_store_part(struct mime_impl *impl, struct sspm_header header, + int level, void *part, size_t size) +{ + + impl->parts[impl->part_no].header = header; + impl->parts[impl->part_no].level = level; + impl->parts[impl->part_no].data = part; + impl->parts[impl->part_no].data_size = size; + impl->part_no++; +} + +void sspm_set_error(struct sspm_header* header, enum sspm_error error, + char* message) +{ + header->error = error; + + if(header->error_text!=0){ + free(header->error_text); + } + + header->def = 0; + + if(message != 0){ + header->error_text = sspm_strdup(message); + } else { + header->error_text = 0; + } + +} + +void* sspm_make_part(struct mime_impl *impl, + struct sspm_header *header, + struct sspm_header *parent_header, + void **end_part, + size_t *size) +{ + + /* For a single part type, read to the boundary, if there is a + boundary. Otherwise, read until the end of input. This routine + assumes that the caller has read the header and has left the input + at the first blank line */ + + char *line; + void *part; + int end = 0; + + struct sspm_action_map action = get_action( + impl, + header->major, + header->minor); + + *size = 0; + part =action.new_part(); + + impl->state = IN_BODY; + + while(end == 0 && (line = sspm_get_next_line(impl)) != 0){ + + if(sspm_is_mime_boundary(line)){ + + /* If there is a boundary, then this must be a multipart + part, so there must be a parent_header. */ + if(parent_header == 0){ + char* boundary; + end = 1; + *end_part = 0; + + sspm_set_error(header,SSPM_UNEXPECTED_BOUNDARY_ERROR,line); + + /* Read until the paired terminating boundary */ + if((boundary = (char*)malloc(strlen(line)+5)) == 0){ + fprintf(stderr,"Out of memory"); + abort(); + } + strcpy(boundary,line); + strcat(boundary,"--"); + while((line = sspm_get_next_line(impl)) != 0){ + /*printf("Error: %s\n",line);*/ + if(strcmp(boundary,line)==0){ + break; + } + } + free(boundary); + + break; + } + + if(strncmp((line+2),parent_header->boundary, + sizeof(parent_header->boundary)) == 0){ + *end_part = action.end_part(part); + + if(sspm_is_mime_boundary(line)){ + impl->state = END_OF_PART; + } else if ( sspm_is_mime_terminating_boundary(line)){ + impl->state = TERMINAL_END_OF_PART; + } + end = 1; + } else { + /* Error, this is not the correct terminating boundary*/ + + /* read and discard until we get the right boundary. */ + char* boundary; + char msg[256]; + + snprintf(msg,256, + "Expected: %s--. Got: %s", + parent_header->boundary,line); + + sspm_set_error(parent_header, + SSPM_WRONG_BOUNDARY_ERROR,msg); + + /* Read until the paired terminating boundary */ + if((boundary = (char*)malloc(strlen(line)+5)) == 0){ + fprintf(stderr,"Out of memory"); + abort(); + } + strcpy(boundary,line); + strcat(boundary,"--"); + while((line = sspm_get_next_line(impl)) != 0){ + if(strcmp(boundary,line)==0){ + break; + } + } + free(boundary); + + } + } else { + char* data=0; + char* rtrn=0; + *size = strlen(line); + + data = (char*)malloc(*size+2); + assert(data != 0); + if (header->encoding == SSPM_BASE64_ENCODING){ + rtrn = decode_base64(data,line,size); + } else if(header->encoding == SSPM_QUOTED_PRINTABLE_ENCODING){ + rtrn = decode_quoted_printable(data,line,size); + } + + if(rtrn == 0){ + strcpy(data,line); + } + + /* add a end-of-string after the data, just in case binary + data from decode64 gets passed to a tring handling + routine in add_line */ + data[*size+1]='\0'; + + action.add_line(part,header,data,*size); + + free(data); + } + } + + if (end == 0){ + /* End the part if the input is exhausted */ + *end_part = action.end_part(part); + } + + return end_part; +} + + +void* sspm_make_multipart_subpart(struct mime_impl *impl, + struct sspm_header *parent_header) +{ + struct sspm_header header; + char *line; + void* part; + size_t size; + + if(parent_header->boundary == 0){ + /* Error. Multipart headers must have a boundary*/ + + sspm_set_error(parent_header,SSPM_NO_BOUNDARY_ERROR,0); + /* read all of the reamining lines */ + while((line = sspm_get_next_line(impl)) != 0){ + } + + return 0; + } + + + /* Step 1: Read the opening boundary */ + + if(get_line_type(impl->temp) != BOUNDARY){ + while((line=sspm_get_next_line(impl)) != 0 ){ + if(sspm_is_mime_boundary(line)){ + + assert(parent_header != 0); + + /* Check if it is the right boundary */ + if(!sspm_is_mime_terminating_boundary(line) && + strncmp((line+2),parent_header->boundary, + sizeof(parent_header->boundary)) + == 0){ + /* The +2 in strncmp skips over the leading "--" */ + + break; + } else { + /* Got the wrong boundary, so read and discard + until we get the right boundary. */ + char* boundary; + char msg[256]; + + snprintf(msg,256, + "Expected: %s. Got: %s", + parent_header->boundary,line); + + sspm_set_error(parent_header, + SSPM_WRONG_BOUNDARY_ERROR,msg); + + /* Read until the paired terminating boundary */ + if((boundary = (char*)malloc(strlen(line)+5)) == 0){ + fprintf(stderr,"Out of memory"); + abort(); + } + strcpy(boundary,line); + strcat(boundary,"--"); + while((line = sspm_get_next_line(impl)) != 0){ + if(strcmp(boundary,line)==0){ + break; + } + } + free(boundary); + + return 0; + } + } + } + } + + /* Step 2: Get the part header */ + sspm_read_header(impl,&header); + + /* If the header is still listed as default, there was probably an + error */ + if(header.def == 1 && header.error != SSPM_NO_ERROR){ + sspm_set_error(&header,SSPM_NO_HEADER_ERROR,0); + return 0; + } + + if(header.error!= SSPM_NO_ERROR){ + sspm_store_part(impl,header,impl->level,0,0); + return 0; + } + + /* Step 3: read the body */ + + if(header.major == SSPM_MULTIPART_MAJOR_TYPE){ + struct sspm_header *child_header; + child_header = &(impl->parts[impl->part_no].header); + + /* Store the multipart part */ + sspm_store_part(impl,header,impl->level,0,0); + + /* now get all of the sub-parts */ + part = sspm_make_multipart_part(impl,child_header); + + if(get_line_type(impl->temp) != TERMINATING_BOUNDARY){ + + sspm_set_error(child_header,SSPM_NO_BOUNDARY_ERROR,impl->temp); + return 0; + } + + sspm_get_next_line(impl); /* Step past the terminating boundary */ + + } else { + sspm_make_part(impl, &header,parent_header,&part,&size); + + memset(&(impl->parts[impl->part_no]), 0, sizeof(struct sspm_part)); + + sspm_store_part(impl,header,impl->level,part,size); + + } + + return part; +} + +void* sspm_make_multipart_part(struct mime_impl *impl,struct sspm_header *header) +{ + void *part=0; + + /* Now descend a level into each of the children of this part */ + impl->level++; + + /* Now we are working on the CHILD */ + memset(&(impl->parts[impl->part_no]), 0, sizeof(struct sspm_part)); + + do{ + part = sspm_make_multipart_subpart(impl,header); + + if (part==0){ + /* Clean up the part in progress */ + impl->parts[impl->part_no].header.major + = SSPM_NO_MAJOR_TYPE; + impl->parts[impl->part_no].header.minor + = SSPM_NO_MINOR_TYPE; + + } + + + } while (get_line_type(impl->temp) != TERMINATING_BOUNDARY && + impl->state != END_OF_INPUT); + + impl->level--; + + return 0; +} + + +void sspm_read_header(struct mime_impl *impl,struct sspm_header *header) +{ +#define BUF_SIZE 1024 +#define MAX_HEADER_LINES 25 + + char *buf; + char header_lines[MAX_HEADER_LINES][BUF_SIZE]; /* HACK, hard limits */ + int current_line = -1; + int end = 0; + + memset(header_lines,0,sizeof(header_lines)); + memset(header,0,sizeof(struct sspm_header)); + + /* Set up default header */ + header->def = 1; + header->major = SSPM_TEXT_MAJOR_TYPE; + header->minor = SSPM_PLAIN_MINOR_TYPE; + header->error = SSPM_NO_ERROR; + header->error_text = 0; + + /* Read all of the lines into memory */ + while(end==0&& (buf=sspm_get_next_line(impl)) != 0){ + + enum line_type line_type = get_line_type(buf); + + switch(line_type){ + case BLANK: { + end = 1; + impl->state = END_OF_HEADER; + break; + } + + case MAIL_HEADER: + case MIME_HEADER: { + impl->state = IN_HEADER; + current_line++; + + assert(strlen(buf) < BUF_SIZE); + + strcpy(header_lines[current_line],buf); + + break; + } + + case HEADER_CONTINUATION: { + char* last_line, *end; + char *buf_start; + + if(current_line < 0){ + /* This is not really a continuation line, since + we have not see any header line yet */ + sspm_set_error(header,SSPM_MALFORMED_HEADER_ERROR,buf); + return; + } + + last_line = header_lines[current_line]; + end = (char*) ( (size_t)strlen(last_line)+ + (size_t)last_line); + + impl->state = IN_HEADER; + + + /* skip over the spaces in buf start, and remove the new + line at the end of the lat line */ + if (last_line[strlen(last_line)-1] == '\n'){ + last_line[strlen(last_line)-1] = '\0'; + } + buf_start = buf; + while(*buf_start == ' ' ||*buf_start == '\t' ){ + buf_start++; + } + + assert( strlen(buf_start) + strlen(last_line) < BUF_SIZE); + + strcat(last_line,buf_start); + + break; + } + + default: { + sspm_set_error(header,SSPM_MALFORMED_HEADER_ERROR,buf); + return; + } + } + } + + + for(current_line = 0; + current_line < MAX_HEADER_LINES && header_lines[current_line][0] != 0; + current_line++){ + + sspm_build_header(header,header_lines[current_line]); + } + + +} + +/* Root routine for parsing mime entries*/ +int sspm_parse_mime(struct sspm_part *parts, + size_t max_parts, + struct sspm_action_map *actions, + char* (*get_string)(char *s, size_t size, void* data), + void *get_string_data, + struct sspm_header *first_header + ) +{ + struct mime_impl impl; + struct sspm_header header; + void *part; + int i; + + /* Initialize all of the data */ + memset(&impl,0,sizeof(struct mime_impl)); + memset(&header,0,sizeof(struct sspm_header)); + + for(i = 0; i<(int)max_parts; i++){ + parts[i].header.major = SSPM_NO_MAJOR_TYPE; + parts[i].header.minor = SSPM_NO_MINOR_TYPE; + } + + impl.parts = parts; + impl.max_parts = max_parts; + impl.part_no = 0; + impl.actions = actions; + impl.get_string = get_string; + impl.get_string_data = get_string_data; + + /* Read the header of the message. This will be the email header, + unless first_header is specified. But ( HACK) that var is not + currently being used */ + sspm_read_header(&impl,&header); + + if(header.major == SSPM_MULTIPART_MAJOR_TYPE){ + struct sspm_header *child_header; + child_header = &(impl.parts[impl.part_no].header); + + sspm_store_part(&impl,header,impl.level,0,0); + + part = sspm_make_multipart_part(&impl,child_header); + + } else { + void *part; + size_t size; + sspm_make_part(&impl, &header, 0,&part,&size); + + memset(&(impl.parts[impl.part_no]), 0, sizeof(struct sspm_part)); + + sspm_store_part(&impl,header,impl.level,part,size); + } + + return 0; +} + +void sspm_free_parts(struct sspm_part *parts, size_t max_parts) +{ + int i; + + for(i = 0; i<(int)max_parts && parts[i].header.major != SSPM_NO_MAJOR_TYPE; + i++){ + sspm_free_header(&(parts[i].header)); + } +} + +void sspm_free_header(struct sspm_header *header) +{ + if(header->boundary!=0){ + free(header->boundary); + } + if(header->minor_text!=0){ + free(header->minor_text); + } + if(header->charset!=0){ + free(header->charset); + } + if(header->filename!=0){ + free(header->filename); + } + if(header->content_id!=0){ + free(header->content_id); + } + if(header->error_text!=0){ + free(header->error_text); + } +} + +/*********************************************************************** +The remaining code is beased on code from the mimelite distribution, +which has the following notice: + +| Authorship: +| Copyright (c) 1994 Gisle Hannemyr. +| Permission is granted to hack, make and distribute copies of this +| program as long as this copyright notice is not removed. +| Flames, bug reports, comments and improvements to: +| snail: Gisle Hannemyr, Brageveien 3A, 0452 Oslo, Norway +| email: Inet: gisle@oslonett.no + +The code is heavily modified by Eric Busboom. + +***********************************************************************/ + +char *decode_quoted_printable(char *dest, + char *src, + size_t *size) +{ + int cc; + size_t i=0; + + while (*src != 0 && i < *size) { + if (*src == '=') { + + src++; + if (!*src) { + break; + } + + /* remove soft line breaks*/ + if ((*src == '\n') || (*src == '\r')){ + src++; + if ((*src == '\n') || (*src == '\r')){ + src++; + } + continue; + } + + cc = isdigit(*src) ? (*src - '0') : (*src - 55); + cc *= 0x10; + src++; + if (!*src) { + break; + } + cc += isdigit(*src) ? (*src - '0') : (*src - 55); + + *dest = cc; + + } else { + *dest = *src; + } + + dest++; + src++; + i++; + } + + *dest = '\0'; + + *size = i; + return(dest); +} + +char *decode_base64(char *dest, + char *src, + size_t *size) +{ + int cc; + char buf[4] = {0,0,0,0}; + int p = 0; + int valid_data = 0; + size_t size_out=0; + + while (*src && p<(int)*size && (cc!= -1)) { + + /* convert a character into the Base64 alphabet */ + cc = *src++; + + if ((cc >= 'A') && (cc <= 'Z')) cc = cc - 'A'; + else if ((cc >= 'a') && (cc <= 'z')) cc = cc - 'a' + 26; + else if ((cc >= '0') && (cc <= '9')) cc = cc - '0' + 52; + else if (cc == '/') cc = 63; + else if (cc == '+') cc = 62; + else cc = -1; + + assert(cc<64); + + /* If we've reached the end, fill the remaining slots in + the bucket and do a final conversion */ + if(cc== -1){ + if(valid_data == 0){ + return 0; + } + + while(p%4!=3){ + p++; + buf[p%4] = 0; + } + } else { + buf[p%4] = cc; + size_out++; + valid_data = 1; + } + + + /* When we have 4 base64 letters, convert them into three + bytes */ + if (p%4 == 3) { + *dest++ =(buf[0]<< 2)|((buf[1] & 0x30) >> 4); + *dest++ =((buf[1] & 0x0F) << 4)|((buf[2] & 0x3C) >> 2); + *dest++ =((buf[2] & 0x03) << 6)|(buf[3] & 0x3F); + + memset(buf,0,4); + } + + p++; + + } + /* Calculate the size of the converted data*/ + *size = ((int)(size_out/4))*3; + if(size_out%4 == 2) *size+=1; + if(size_out%4 == 3) *size+=2; + + return(dest); +} + + +/*********************************************************************** + + Routines to output MIME + +**********************************************************************/ + + +struct sspm_buffer { + char* buffer; + char* pos; + size_t buf_size; + int line_pos; +}; + +void sspm_append_string(struct sspm_buffer* buf, char* string); +void sspm_write_part(struct sspm_buffer *buf,struct sspm_part *part, int *part_num); + +void sspm_append_hex(struct sspm_buffer* buf, char ch) +{ + char tmp[3]; + + sprintf(tmp,"=%02X",ch); + + sspm_append_string(buf,tmp); +} + +/* a copy of icalmemory_append_char */ +void sspm_append_char(struct sspm_buffer* buf, char ch) +{ + char *new_buf; + char *new_pos; + + size_t data_length, final_length; + + data_length = (size_t)buf->pos - (size_t)buf->buffer; + + final_length = data_length + 2; + + if ( final_length > (size_t) buf->buf_size ) { + + buf->buf_size = (buf->buf_size) * 2 + final_length +1; + + new_buf = realloc(buf->buffer,buf->buf_size); + + new_pos = (void*)((size_t)new_buf + data_length); + + buf->pos = new_pos; + buf->buffer = new_buf; + } + + *(buf->pos) = ch; + buf->pos += 1; + *(buf->pos) = 0; +} +/* A copy of icalmemory_append_string */ +void sspm_append_string(struct sspm_buffer* buf, char* string) +{ + char *new_buf; + char *new_pos; + + size_t data_length, final_length, string_length; + + string_length = strlen(string); + data_length = (size_t)buf->pos - (size_t)buf->buffer; + final_length = data_length + string_length; + + if ( final_length >= (size_t) buf->buf_size) { + + + buf->buf_size = (buf->buf_size) * 2 + final_length; + + new_buf = realloc(buf->buffer,buf->buf_size); + + new_pos = (void*)((size_t)new_buf + data_length); + + buf->pos = new_pos; + buf->buffer = new_buf; + } + + strcpy(buf->pos, string); + + buf->pos += string_length; +} + + + +static int sspm_is_printable(char c) +{ + return (c >= 33) && (c <= 126) && (c != '='); + +} + + +void sspm_encode_quoted_printable(struct sspm_buffer *buf, char* data) +{ + char *p; + int lpos = 0; + + for(p = data; *p != 0; p++){ + + if(sspm_is_printable(*p)){ + /* plain characters can represent themselves */ + /* RFC2045 Rule #2 */ + sspm_append_char(buf,*p); + lpos++; + } else if ( *p == '\t' || *p == ' ' ) { + + /* For tabs and spaces, only encode if they appear at the + end of the line */ + /* RFC2045 Rule #3 */ + + char n = *(p+1); + + if( n == '\n' || n == '\r'){ + sspm_append_hex(buf,*p); + lpos += 3; + } else { + sspm_append_char(buf,*p); + lpos++; + } + + } else if( *p == '\n' || *p == '\r'){ + sspm_append_char(buf,*p); + + lpos=0; + + } else { + /* All others need to be encoded */ + sspm_append_hex(buf,*p); + lpos+=3; + } + + + /* Add line breaks */ + if (lpos > 72){ + lpos = 0; + sspm_append_string(buf,"=\n"); + } + } +} + +static char BaseTable[64] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' +}; + +void sspm_write_base64(struct sspm_buffer *buf, char* inbuf,int size ) +{ + + char outbuf[4]; + int i; + + outbuf[0] = outbuf[1] = outbuf[2] = outbuf[3] = 65; + + switch(size){ + + case 4: + outbuf[3] = inbuf[2] & 0x3F; + + case 3: + outbuf[2] = ((inbuf[1] & 0x0F) << 2) | ((inbuf[2] & 0xC0) >> 6); + + case 2: + outbuf[0] = (inbuf[0] & 0xFC) >> 2; + outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf[1] & 0xF0) >> 4); + break; + + default: + assert(0); + } + + for(i = 0; i < 4; i++){ + + if(outbuf[i] == 65){ + sspm_append_char(buf,'='); + } else { + sspm_append_char(buf,BaseTable[(int)outbuf[i]]); + } + } +} + +void sspm_encode_base64(struct sspm_buffer *buf, char* data, size_t size) +{ + + char *p; + char inbuf[3]; + int i = 0; + int first = 1; + int lpos = 0; + + inbuf[0] = inbuf[1] = inbuf[2] = 0; + + for (p = data; *p !=0; p++){ + + if (i%3 == 0 && first == 0){ + + sspm_write_base64(buf, inbuf, 4); + lpos+=4; + + inbuf[0] = inbuf[1] = inbuf[2] = 0; + } + + assert(lpos%4 == 0); + + if (lpos == 72){ + sspm_append_string(buf,"\n"); + lpos = 0; + } + + inbuf[i%3] = *p; + + i++; + first = 0; + + } + + + /* If the inbuf was not exactly filled on the last byte, we need + to spit out the odd bytes that did get in -- either one or + two. This will result in an output of two bytes and '==' or + three bytes and '=', respectively */ + + if (i%3 == 1 && first == 0){ + sspm_write_base64(buf, inbuf, 2); + } else if (i%3 == 2 && first == 0){ + sspm_write_base64(buf, inbuf, 3); + } + +} + +void sspm_write_header(struct sspm_buffer *buf,struct sspm_header *header) +{ + + int i; + char temp[TMP_BUF_SIZE]; + char* major; + char* minor; + + /* Content-type */ + + major = sspm_major_type_string(header->major); + minor = sspm_minor_type_string(header->minor); + + if(header->minor == SSPM_UNKNOWN_MINOR_TYPE ){ + assert(header->minor_text !=0); + minor = header->minor_text; + } + + sprintf(temp,"Content-Type: %s/%s",major,minor); + + sspm_append_string(buf,temp); + + if(header->boundary != 0){ + sprintf(temp,";boundary=\"%s\"",header->boundary); + sspm_append_string(buf,temp); + } + + /* Append any content type parameters */ + if(header->content_type_params != 0){ + for(i=0; *(header->content_type_params[i])!= 0;i++){ + sprintf(temp,header->content_type_params[i]); + sspm_append_char(buf,';'); + sspm_append_string(buf,temp); + } + } + + sspm_append_char(buf,'\n'); + + /*Content-Transfer-Encoding */ + + if(header->encoding != SSPM_UNKNOWN_ENCODING && + header->encoding != SSPM_NO_ENCODING){ + sprintf(temp,"Content-Transfer-Encoding: %s\n", + sspm_encoding_string(header->encoding)); + } + + sspm_append_char(buf,'\n'); + +} + +void sspm_write_multipart_part(struct sspm_buffer *buf, + struct sspm_part *parts, + int* part_num) +{ + + int parent_level, level; + struct sspm_header *header = &(parts[*part_num].header); + /* Write the header for the multipart part */ + sspm_write_header(buf,header); + + parent_level = parts[*part_num].level; + + (*part_num)++; + + level = parts[*part_num].level; + + while(parts[*part_num].header.major != SSPM_NO_MAJOR_TYPE && + level == parent_level+1){ + + assert(header->boundary); + sspm_append_string(buf,header->boundary); + sspm_append_char(buf,'\n'); + + if (parts[*part_num].header.major == SSPM_MULTIPART_MAJOR_TYPE){ + sspm_write_multipart_part(buf,parts,part_num); + } else { + sspm_write_part(buf, &(parts[*part_num]), part_num); + } + + (*part_num)++; + level = parts[*part_num].level; + } + + sspm_append_string(buf,"\n\n--"); + sspm_append_string(buf,header->boundary); + sspm_append_string(buf,"\n"); + + (*part_num)--; /* undo last, spurious, increment */ +} + +void sspm_write_part(struct sspm_buffer *buf,struct sspm_part *part,int *part_num) +{ + + /* Write header */ + sspm_write_header(buf,&(part->header)); + + /* Write part data */ + + if(part->data == 0){ + return; + } + + if(part->header.encoding == SSPM_BASE64_ENCODING) { + assert(part->data_size != 0); + sspm_encode_base64(buf,part->data,part->data_size); + } else if(part->header.encoding == SSPM_QUOTED_PRINTABLE_ENCODING) { + sspm_encode_quoted_printable(buf,part->data); + } else { + sspm_append_string(buf,part->data); + } + + sspm_append_string(buf,"\n\n"); +} + +int sspm_write_mime(struct sspm_part *parts,size_t num_parts, + char **output_string, char* header) +{ + struct sspm_buffer buf; + int part_num =0; + + buf.buffer = malloc(4096); + buf.pos = buf.buffer; + buf.buf_size = 10; + buf.line_pos = 0; + + /* write caller's header */ + if(header != 0){ + sspm_append_string(&buf,header); + } + + if(buf.buffer[strlen(buf.buffer)-1] != '\n'){ + sspm_append_char(&buf,'\n'); + } + + /* write mime-version header */ + sspm_append_string(&buf,"Mime-Version: 1.0\n"); + + /* End of header */ + + /* Write body parts */ + while(parts[part_num].header.major != SSPM_NO_MAJOR_TYPE){ + if (parts[part_num].header.major == SSPM_MULTIPART_MAJOR_TYPE){ + sspm_write_multipart_part(&buf,parts,&part_num); + } else { + sspm_write_part(&buf, &(parts[part_num]), &part_num); + } + + part_num++; + } + + + *output_string = buf.buffer; + + return 0; +} + diff --git a/libical/src/libical/sspm.h b/libical/src/libical/sspm.h new file mode 100644 index 0000000..864a23a --- a/dev/null +++ b/libical/src/libical/sspm.h @@ -0,0 +1,143 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: sspm.h Mime Parser + CREATOR: eric 25 June 2000 + + $Id$ + $Locker$ + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Initial Developer of the Original Code is Eric Busboom + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + ======================================================================*/ + +#ifndef SSPM_H +#define SSPM_H + +enum sspm_major_type { + SSPM_NO_MAJOR_TYPE, + SSPM_TEXT_MAJOR_TYPE, + SSPM_IMAGE_MAJOR_TYPE, + SSPM_AUDIO_MAJOR_TYPE, + SSPM_VIDEO_MAJOR_TYPE, + SSPM_APPLICATION_MAJOR_TYPE, + SSPM_MULTIPART_MAJOR_TYPE, + SSPM_MESSAGE_MAJOR_TYPE, + SSPM_UNKNOWN_MAJOR_TYPE +}; + +enum sspm_minor_type { + SSPM_NO_MINOR_TYPE, + SSPM_ANY_MINOR_TYPE, + SSPM_PLAIN_MINOR_TYPE, + SSPM_RFC822_MINOR_TYPE, + SSPM_DIGEST_MINOR_TYPE, + SSPM_CALENDAR_MINOR_TYPE, + SSPM_MIXED_MINOR_TYPE, + SSPM_RELATED_MINOR_TYPE, + SSPM_ALTERNATIVE_MINOR_TYPE, + SSPM_PARALLEL_MINOR_TYPE, + SSPM_UNKNOWN_MINOR_TYPE +}; + +enum sspm_encoding { + SSPM_NO_ENCODING, + SSPM_QUOTED_PRINTABLE_ENCODING, + SSPM_8BIT_ENCODING, + SSPM_7BIT_ENCODING, + SSPM_BINARY_ENCODING, + SSPM_BASE64_ENCODING, + SSPM_UNKNOWN_ENCODING +}; + +enum sspm_error{ + SSPM_NO_ERROR, + SSPM_UNEXPECTED_BOUNDARY_ERROR, + SSPM_WRONG_BOUNDARY_ERROR, + SSPM_NO_BOUNDARY_ERROR, + SSPM_NO_HEADER_ERROR, + SSPM_MALFORMED_HEADER_ERROR +}; + + +struct sspm_header +{ + int def; + char* boundary; + enum sspm_major_type major; + enum sspm_minor_type minor; + char *minor_text; + char ** content_type_params; + char* charset; + enum sspm_encoding encoding; + char* filename; + char* content_id; + enum sspm_error error; + char* error_text; +}; + +struct sspm_part { + struct sspm_header header; + int level; + size_t data_size; + void *data; +}; + +struct sspm_action_map { + enum sspm_major_type major; + enum sspm_minor_type minor; + void* (*new_part)(); + void (*add_line)(void *part, struct sspm_header *header, + char* line, size_t size); + void* (*end_part)(void* part); + void (*free_part)(void *part); +}; + +char* sspm_major_type_string(enum sspm_major_type type); +char* sspm_minor_type_string(enum sspm_minor_type type); +char* sspm_encoding_string(enum sspm_encoding type); + +int sspm_parse_mime(struct sspm_part *parts, + size_t max_parts, + struct sspm_action_map *actions, + char* (*get_string)(char *s, size_t size, void* data), + void *get_string_data, + struct sspm_header *first_header + ); + +void sspm_free_parts(struct sspm_part *parts, size_t max_parts); + +char *decode_quoted_printable(char *dest, + char *src, + size_t *size); +char *decode_base64(char *dest, + char *src, + size_t *size); + + +int sspm_write_mime(struct sspm_part *parts,size_t num_parts, + char **output_string, char* header); + +#endif /*SSPM_H*/ diff --git a/libical/src/libical/vsnprintf.c b/libical/src/libical/vsnprintf.c new file mode 100644 index 0000000..88a8c63 --- a/dev/null +++ b/libical/src/libical/vsnprintf.c @@ -0,0 +1,180 @@ +#ifdef __osf__ +/* + * Revision 12: http://theos.com/~deraadt/snprintf.c + * + * Copyright (c) 1997 Theo de Raadt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <stdio.h> + +#include <unistd.h> +#include <sys/param.h> +#include <sys/mman.h> +#include <signal.h> + +#include <string.h> +#if __STDC__ +#include <stdarg.h> +#include <stdlib.h> +#else +#include <varargs.h> +#endif +#include <setjmp.h> + +#ifndef roundup +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#endif + +static int pgsize; +static char *curobj; +static sigjmp_buf bail; + +#define EXTRABYTES 2 /* XXX: why 2? you don't want to know */ + +static char * +msetup(str, n) + char *str; + size_t n; +{ + char *e; + + if (n == 0) + return NULL; + if (pgsize == 0) + pgsize = getpagesize(); + curobj = (char *)malloc(n + EXTRABYTES + pgsize * 2); + if (curobj == NULL) + return NULL; + e = curobj + n + EXTRABYTES; + e = (char *)roundup((unsigned long)e, pgsize); + if (mprotect(e, pgsize, PROT_NONE) == -1) { + free(curobj); + curobj = NULL; + return NULL; + } + e = e - n - EXTRABYTES; + *e = '\0'; + return (e); +} + +static void +mcatch(int i) +{ + siglongjmp(bail, 1); +} + +static void +mcleanup(str, n, p) + char *str; + size_t n; + char *p; +{ + strncpy(str, p, n-1); + str[n-1] = '\0'; + if (mprotect((caddr_t)(p + n + EXTRABYTES), pgsize, + PROT_READ|PROT_WRITE|PROT_EXEC) == -1) + mprotect((caddr_t)(p + n + EXTRABYTES), pgsize, + PROT_READ|PROT_WRITE); + free(curobj); +} + +int +#if __STDC__ +vsnprintf(char *str, size_t n, char const *fmt, va_list ap) +#else +vsnprintf(str, n, fmt, ap) + char *str; + size_t n; + char *fmt; + char *ap; +#endif +{ + struct sigaction osa, nsa; + char *p; + int ret = n + 1; /* if we bail, indicated we overflowed */ + + memset(&nsa, 0, sizeof nsa); + nsa.sa_handler = mcatch; + sigemptyset(&nsa.sa_mask); + + p = msetup(str, n); + if (p == NULL) { + *str = '\0'; + return 0; + } + if (sigsetjmp(bail, 1) == 0) { + if (sigaction(SIGSEGV, &nsa, &osa) == -1) { + mcleanup(str, n, p); + return (0); + } + ret = vsprintf(p, fmt, ap); + } + mcleanup(str, n, p); + (void) sigaction(SIGSEGV, &osa, NULL); + return (ret); +} + +int +#if __STDC__ +snprintf(char *str, size_t n, char const *fmt, ...) +#else +snprintf(str, n, fmt, va_alist) + char *str; + size_t n; + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + + return (vsnprintf(str, n, fmt, ap)); + va_end(ap); +} + +#elif defined ( _WIN32 ) + +#include <stdio.h> +#include <stdarg.h> + +int snprintf(char *str, size_t n, char const *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + return _snprintf(str, n, fmt, ap); +} + +#else +/* ANSI C forbids an empty source file... */ + +static void vsnprintf_dummy_func() { + vsnprintf_dummy_func(); +} + +#endif diff --git a/libical/src/libicalss/config.h b/libical/src/libicalss/config.h new file mode 100644 index 0000000..fa66c47 --- a/dev/null +++ b/libical/src/libicalss/config.h @@ -0,0 +1,7 @@ +#ifndef LIBICALSS_CONFIG_H +#define LIBICALSS_CONFIG_H + +#define PACKAGE "libicalss" +#define VERSION "0.23" + +#endif diff --git a/libical/src/libicalss/icalcalendar.h b/libical/src/libicalss/icalcalendar.h new file mode 100644 index 0000000..f07457c --- a/dev/null +++ b/libical/src/libicalss/icalcalendar.h @@ -0,0 +1,67 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcalendar.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALCALENDAR_H +#define ICALCALENDAR_H + +#include "ical.h" +#include "icalset.h" + +/* icalcalendar + * Routines for storing calendar data in a file system. The calendar + * has two icaldirsets, one for incoming components and one for booked + * components. It also has interfaces to access the free/busy list + * and a list of calendar properties */ + +typedef void icalcalendar; + +icalcalendar* icalcalendar_new(char* dir); + +void icalcalendar_free(icalcalendar* calendar); + +int icalcalendar_lock(icalcalendar* calendar); + +int icalcalendar_unlock(icalcalendar* calendar); + +int icalcalendar_islocked(icalcalendar* calendar); + +int icalcalendar_ownlock(icalcalendar* calendar); + +icalset* icalcalendar_get_booked(icalcalendar* calendar); + +icalset* icalcalendar_get_incoming(icalcalendar* calendar); + +icalset* icalcalendar_get_properties(icalcalendar* calendar); + +icalset* icalcalendar_get_freebusy(icalcalendar* calendar); + + +#endif /* !ICALCALENDAR_H */ + + + diff --git a/libical/src/libicalss/icalclassify.c b/libical/src/libicalss/icalclassify.c new file mode 100644 index 0000000..c029309 --- a/dev/null +++ b/libical/src/libicalss/icalclassify.c @@ -0,0 +1,792 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalclassify.c + CREATOR: ebusboom 23 aug 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalerror.h" +#include "ical.h" +#include "icalclassify.h" +#include "icalmemory.h" +#include <ctype.h> /* For tolower() */ +#include <string.h> /* for index() */ +#include <stdlib.h> /* for malloc and free */ + + + +struct icalclassify_parts { + icalcomponent *c; + icalcomponent_kind inner_kind; + icalproperty_method method; + char* organizer; + icalparameter_partstat reply_partstat; + char* reply_attendee; + char* uid; + int sequence; + struct icaltimetype dtstamp; + struct icaltimetype recurrence_id; +}; + + +char* icalclassify_lowercase(const char* str) +{ + char* p = 0; + char* new = icalmemory_strdup(str); + + if(str ==0){ + return 0; + } + + for(p = new; *p!=0; p++){ + *p = tolower(*p); + } + + return new; +} + +/* Return a set of components that intersect in time with comp. For +component X and Y to intersect: + X.DTSTART < Y.DTEND && X.DTEND > Y.DTSTART +*/ + + +icalcomponent* icalclassify_find_overlaps(icalset* set, icalcomponent* comp) +{ + icalcomponent *return_set; + icalcomponent *c; + struct icaltime_span span,compspan; + + icalerror_clear_errno(); + compspan = icalcomponent_get_span(comp); + + if(icalerrno != ICAL_NO_ERROR){ + return 0; + } + + + return_set = icalcomponent_new(ICAL_XROOT_COMPONENT); + + for(c = icalset_get_first_component(set); + c != 0; + c = icalset_get_next_component(set)){ + + icalerror_clear_errno(); + + span = icalcomponent_get_span(c); + + if(icalerrno != ICAL_NO_ERROR){ + continue; + } + + if (compspan.start < span.end && + compspan.end > span.start){ + + icalcomponent *clone = icalcomponent_new_clone(c); + + icalcomponent_add_component(return_set,clone); + } + } + + if(icalcomponent_count_components(return_set,ICAL_ANY_COMPONENT) !=0){ + return return_set; + } else { + icalcomponent_free(return_set); + return 0; + } +} + + + +icalproperty* icalclassify_find_attendee(icalcomponent *c, + const char* attendee) +{ + icalproperty *p; + icalcomponent* inner; + char* lattendee; + char* upn; + + if(attendee == 0){ + return 0; + } + + lattendee = icalclassify_lowercase(attendee); + upn = strchr(lattendee,':'); + + if (upn== 0){ + upn = lattendee; + } else { + upn++; /* skip the ";"*/ + } + + inner = icalcomponent_get_first_real_component(c); + + for(p = icalcomponent_get_first_property(inner,ICAL_ATTENDEE_PROPERTY); + p != 0; + p = icalcomponent_get_next_property(inner,ICAL_ATTENDEE_PROPERTY)) + { + const char* this_attendee + = icalclassify_lowercase(icalproperty_get_attendee(p)); + char* this_upn = strchr(this_attendee,':'); + + if(this_upn == 0){ + continue; + } else { + this_upn++; + } + + if(strcmp(this_upn,upn)==0){ + return p; + } + + } + + return 0; + +} + +void icalssutil_free_parts(struct icalclassify_parts *parts) +{ + if(parts == 0){ + return; + } + + if(parts->organizer != 0){ + free(parts->organizer); + } + + if(parts->uid != 0){ + free(parts->uid); + } + + if(parts->reply_attendee){ + free(parts->reply_attendee); + } +} + +void icalssutil_get_parts(icalcomponent* c, + struct icalclassify_parts* parts) +{ + icalproperty *p; + icalcomponent *inner; + + memset(parts,0,sizeof(struct icalclassify_parts)); + + parts->method = ICAL_METHOD_NONE; + parts->sequence = 0; + parts->reply_partstat = ICAL_PARTSTAT_NONE; + + if(c == 0){ + return; + } + + parts->c = c; + + p = icalcomponent_get_first_property(c,ICAL_METHOD_PROPERTY); + if(p!=0){ + parts->method = icalproperty_get_method(p); + } + + inner = icalcomponent_get_first_real_component(c); + + parts->inner_kind = icalcomponent_isa(inner); + + p = icalcomponent_get_first_property(inner,ICAL_ORGANIZER_PROPERTY); + if(p!=0){ + parts->organizer = strdup(icalproperty_get_organizer(p)); + } + + p = icalcomponent_get_first_property(inner,ICAL_SEQUENCE_PROPERTY); + if(p!=0){ + parts->sequence = icalproperty_get_sequence(p); + } + + p = icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY); + if(p!=0){ + parts->uid = strdup(icalproperty_get_uid(p)); + } + + p = icalcomponent_get_first_property(inner,ICAL_RECURRENCEID_PROPERTY); + if(p!=0){ + parts->recurrence_id = icalproperty_get_recurrenceid(p); + } + + p = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY); + if(p!=0){ + parts->dtstamp = icalproperty_get_dtstamp(p); + } + + if(parts->method==ICAL_METHOD_REPLY){ + icalparameter *param; + p = icalcomponent_get_first_property(inner,ICAL_ATTENDEE_PROPERTY); + + if(p!=0){ + + param = icalproperty_get_first_parameter(p,ICAL_PARTSTAT_PARAMETER); + + if(param != 0){ + parts->reply_partstat = + icalparameter_get_partstat(param); + } + + parts->reply_attendee = strdup(icalproperty_get_attendee(p)); + } + + } + + +} + + +int icalssutil_is_rescheduled(icalcomponent* a,icalcomponent* b) +{ + icalproperty *p1,*p2; + icalcomponent *i1,*i2; + int i; + + icalproperty_kind kind_array[] = { + ICAL_DTSTART_PROPERTY, + ICAL_DTEND_PROPERTY, + ICAL_DURATION_PROPERTY, + ICAL_DUE_PROPERTY, + ICAL_RRULE_PROPERTY, + ICAL_RDATE_PROPERTY, + ICAL_EXRULE_PROPERTY, + ICAL_EXDATE_PROPERTY, + ICAL_NO_PROPERTY + }; + + i1 = icalcomponent_get_first_real_component(a); + i2 = icalcomponent_get_first_real_component(b); + + for(i =0; kind_array[i] != ICAL_NO_PROPERTY; i++){ + p1 = icalcomponent_get_first_property(i1,kind_array[i]); + p2 = icalcomponent_get_first_property(i2,kind_array[i]); + + if( (p1!=0)^(p1!=0) ){ + /* Return true if the property exists in one component and not + the other */ + return 1; + } + + if(p1 && strcmp(icalproperty_as_ical_string(p1), + icalproperty_as_ical_string(p2)) != 0){ + return 1; + } + } + + return 0; + +} + +#define icalclassify_pre \ + int rtrn =0; + +#define icalclassify_post \ + return rtrn; + + +int icalclassify_publish_new(struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre; + + if(comp->method == ICAL_METHOD_PUBLISH && + match == 0 && comp->inner_kind != ICAL_VFREEBUSY_COMPONENT){ + rtrn = 1; + } + + icalclassify_post; + +} + +int icalclassify_publish_update(struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre; + + if(comp->method == ICAL_METHOD_PUBLISH && + match !=0 && comp->inner_kind != ICAL_VFREEBUSY_COMPONENT){ + rtrn = 1; + } + + icalclassify_post; + +} + +int icalclassify_publish_freebusy(struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre; + + if(comp->method == ICAL_METHOD_PUBLISH && + comp->inner_kind == ICAL_VFREEBUSY_COMPONENT){ + rtrn = 1; + } + + icalclassify_post; + +} + + +int icalclassify_request_new(struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + /* Method is REQUEST, and there is no match */ + + icalclassify_pre + + if(match->c==0 && comp->method == ICAL_METHOD_REQUEST){ + rtrn = 1; + } + + icalclassify_post + +} + +int icalclassify_request_update( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + /* REQUEST method, Higher SEQUENCE than match, and all + time-related properties are unchanged */ + + icalclassify_pre + + if (match != 0 && + comp->sequence >= match->sequence && + !icalssutil_is_rescheduled(comp->c,match->c)){ + rtrn = 1; + } + + icalclassify_post + +} + +int icalclassify_request_reschedule( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + /* REQUEST method, Higher SEQUENCE than match, and one or more + time-related properties are changed */ + icalclassify_pre + + if (match->c != 0 && + comp->sequence > match->sequence && + icalssutil_is_rescheduled(comp->c,match->c)){ + rtrn = 1; + } + + icalclassify_post + +} + +int icalclassify_request_delegate( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalproperty* attendee; + icalparameter* param; + icalclassify_pre; + + attendee = icalclassify_find_attendee(comp->c,user); + + if(attendee == 0){ + return 0; + } + + param = icalproperty_get_first_parameter(attendee,ICAL_DELEGATEDFROM_PARAMETER); + + if (param != 0){ + rtrn = 1; + } + + icalclassify_post + +} + +int icalclassify_request_new_organizer( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + /* Organizer has changed between match and component */ + icalclassify_pre + icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR); + icalclassify_post + +} + +int icalclassify_request_status( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR); + icalclassify_post +} + +int icalclassify_request_forward( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR); + icalclassify_post +} + +int icalclassify_request_freebusy( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR); + icalclassify_post +} + +int icalclassify_reply_accept( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalproperty* attendee; + icalclassify_pre; + + attendee = icalclassify_find_attendee(match->c,comp->reply_attendee); + + if(attendee != 0&& + comp->reply_partstat == ICAL_PARTSTAT_ACCEPTED){ + rtrn = 1; + } + + icalclassify_post +} +int icalclassify_reply_decline( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalproperty* attendee; + icalclassify_pre; + + attendee = icalclassify_find_attendee(match->c,comp->reply_attendee); + + + if( attendee != 0 && + comp->reply_partstat == ICAL_PARTSTAT_DECLINED){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_reply_delegate( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalproperty* attendee; + icalclassify_pre; + + attendee = icalclassify_find_attendee(match->c,comp->reply_attendee); + + if( attendee != 0 && + comp->reply_partstat == ICAL_PARTSTAT_DELEGATED){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_reply_crasher_accept( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalproperty* attendee; + icalclassify_pre; + + attendee= icalclassify_find_attendee(match->c,comp->reply_attendee); + + if(attendee == 0 && + comp->reply_partstat == ICAL_PARTSTAT_ACCEPTED){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_reply_crasher_decline( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalparameter_partstat partstat; + icalproperty* attendee; + icalclassify_pre; + + + attendee = icalclassify_find_attendee(match->c,comp->reply_attendee); + + if(attendee == 0 && + comp->reply_partstat == ICAL_PARTSTAT_DECLINED){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_add_instance( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_ADD){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_cancel_event( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_CANCEL){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_cancel_instance( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_CANCEL){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_cancel_all( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_CANCEL){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_refesh( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_REFRESH){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_counter( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_COUNTER){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_delinecounter( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + + if(comp->method == ICAL_METHOD_DECLINECOUNTER){ + rtrn = 1; + } + + icalclassify_post +} + +struct icalclassify_map { + icalproperty_method method; + int (*fn)(struct icalclassify_parts *comp,struct icalclassify_parts *match, const char* user); + ical_class class; +} icalclassify_map[] = +{ {ICAL_METHOD_PUBLISH,icalclassify_publish_new,ICAL_PUBLISH_NEW_CLASS}, + {ICAL_METHOD_PUBLISH,icalclassify_publish_update,ICAL_PUBLISH_UPDATE_CLASS}, + {ICAL_METHOD_PUBLISH,icalclassify_publish_freebusy,ICAL_PUBLISH_FREEBUSY_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_delegate,ICAL_REQUEST_DELEGATE_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_new,ICAL_REQUEST_NEW_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_update,ICAL_REQUEST_UPDATE_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_reschedule,ICAL_REQUEST_RESCHEDULE_CLASS}, + + {ICAL_METHOD_REQUEST,icalclassify_request_new_organizer,ICAL_REQUEST_NEW_ORGANIZER_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_forward,ICAL_REQUEST_FORWARD_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_status,ICAL_REQUEST_STATUS_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_freebusy,ICAL_REQUEST_FREEBUSY_CLASS}, + + {ICAL_METHOD_REPLY,icalclassify_reply_accept,ICAL_REPLY_ACCEPT_CLASS}, + {ICAL_METHOD_REPLY,icalclassify_reply_decline,ICAL_REPLY_DECLINE_CLASS}, + {ICAL_METHOD_REPLY,icalclassify_reply_delegate,ICAL_REPLY_DELEGATE_CLASS}, + {ICAL_METHOD_REPLY,icalclassify_reply_crasher_accept,ICAL_REPLY_CRASHER_ACCEPT_CLASS}, + {ICAL_METHOD_REPLY,icalclassify_reply_crasher_decline,ICAL_REPLY_CRASHER_DECLINE_CLASS}, + + {ICAL_METHOD_ADD,icalclassify_add_instance,ICAL_ADD_INSTANCE_CLASS}, + + {ICAL_METHOD_CANCEL,icalclassify_cancel_event,ICAL_CANCEL_EVENT_CLASS}, + {ICAL_METHOD_CANCEL,icalclassify_cancel_instance,ICAL_CANCEL_INSTANCE_CLASS}, + {ICAL_METHOD_CANCEL,icalclassify_cancel_all,ICAL_CANCEL_ALL_CLASS}, + + {ICAL_METHOD_REFRESH,icalclassify_refesh,ICAL_REFRESH_CLASS}, + {ICAL_METHOD_COUNTER,icalclassify_counter,ICAL_COUNTER_CLASS}, + {ICAL_METHOD_DECLINECOUNTER,icalclassify_delinecounter,ICAL_DECLINECOUNTER_CLASS}, + {ICAL_METHOD_NONE,0,ICAL_NO_CLASS} +}; + + +ical_class icalclassify(icalcomponent* c,icalcomponent* match, + const char* user) +{ + icalcomponent *inner; + icalproperty *p; + icalproperty_method method; + ical_class class = ICAL_UNKNOWN_CLASS; + + int i; + + struct icalclassify_parts comp_parts; + struct icalclassify_parts match_parts; + + inner = icalcomponent_get_first_real_component(c); + + if (inner == 0) { + return ICAL_NO_CLASS; + } + + icalssutil_get_parts(c,&comp_parts); + icalssutil_get_parts(match,&match_parts); + + /* Determine if the incoming component is obsoleted by the match */ + if(match != 0 && ( + comp_parts.method == ICAL_METHOD_REQUEST + )){ + assert ( ! ((comp_parts.dtstamp.is_utc==1)^ + (match_parts.dtstamp.is_utc==1))); + + if( comp_parts.sequence<match_parts.sequence && + icaltime_compare(comp_parts.dtstamp,match_parts.dtstamp)>0) + { + /* comp has a smaller sequence and a later DTSTAMP */ + return ICAL_MISSEQUENCED_CLASS; + } + + if( (comp_parts.sequence<match_parts.sequence ) + /*&&icaltime_compare(comp_parts.dtstamp,match_parts.dtstamp)<=0*/ + || + ( comp_parts.sequence == match_parts.sequence && + icaltime_compare(comp_parts.dtstamp,match_parts.dtstamp)<=0)){ + + return ICAL_OBSOLETE_CLASS; + } + + } + + p = icalcomponent_get_first_property(c,ICAL_METHOD_PROPERTY); + if (p == 0) { + return ICAL_UNKNOWN_CLASS; + } + method = icalproperty_get_method(p); + + for (i =0; icalclassify_map[i].method != ICAL_METHOD_NONE; i++){ + if(icalclassify_map[i].method == method){ + if( (*(icalclassify_map[i].fn))(&comp_parts,&match_parts,user)==1){ + class = icalclassify_map[i].class; + break; + } + } + } + + icalssutil_free_parts(&comp_parts); + icalssutil_free_parts(&match_parts); + + return class; + +} + +struct class_map { + ical_class class; + char *str; +} class_map[] = { + {ICAL_NO_CLASS,"No class"}, + {ICAL_PUBLISH_NEW_CLASS,"New Publish"}, + {ICAL_PUBLISH_UPDATE_CLASS,"Publish Update"}, + {ICAL_PUBLISH_FREEBUSY_CLASS,"Publish freebusy"}, + {ICAL_REQUEST_NEW_CLASS,"New request"}, + {ICAL_REQUEST_UPDATE_CLASS,"Update"}, + {ICAL_REQUEST_RESCHEDULE_CLASS,"Reschedule"}, + {ICAL_REQUEST_DELEGATE_CLASS,"Delegate request"}, + {ICAL_REQUEST_NEW_ORGANIZER_CLASS,"New Organizer"}, + {ICAL_REQUEST_FORWARD_CLASS,"Forward"}, + {ICAL_REQUEST_STATUS_CLASS,"Status request"}, + {ICAL_REPLY_ACCEPT_CLASS,"Accept reply"}, + {ICAL_REPLY_DECLINE_CLASS,"Decline reply"}, + {ICAL_REPLY_DELEGATE_CLASS,"Delegation reply"}, + {ICAL_REPLY_CRASHER_ACCEPT_CLASS,"Crasher's accept reply"}, + {ICAL_REPLY_CRASHER_DECLINE_CLASS,"Crasher's decline reply"}, + {ICAL_ADD_INSTANCE_CLASS,"Add instance"}, + {ICAL_CANCEL_EVENT_CLASS,"Cancel event"}, + {ICAL_CANCEL_INSTANCE_CLASS,"Cancel instance"}, + {ICAL_CANCEL_ALL_CLASS,"Cancel all instances"}, + {ICAL_REFRESH_CLASS,"Refresh"}, + {ICAL_COUNTER_CLASS,"Counter"}, + {ICAL_DECLINECOUNTER_CLASS,"Decline counter"}, + {ICAL_MALFORMED_CLASS,"Malformed"}, + {ICAL_OBSOLETE_CLASS,"Obsolete"}, + {ICAL_MISSEQUENCED_CLASS,"Missequenced"}, + {ICAL_UNKNOWN_CLASS,"Unknown"} +}; + +char* icalclassify_class_to_string(ical_class class) +{ + int i; + + for (i = 0;class_map[i].class != ICAL_UNKNOWN_CLASS;i++){ + if (class_map[i].class == class){ + return class_map[i].str; + } + } + + return "Unknown"; +} diff --git a/libical/src/libicalss/icalclassify.h b/libical/src/libicalss/icalclassify.h new file mode 100644 index 0000000..81188b3 --- a/dev/null +++ b/libical/src/libicalss/icalclassify.h @@ -0,0 +1,77 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalclassify.h + CREATOR: eric 21 Aug 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + =========================================================================*/ + +#ifndef ICALCLASSIFY_H +#define ICALCLASSIFY_H + +#include "ical.h" +#include "icalset.h" + + +typedef enum icalclass { + ICAL_NO_CLASS, + ICAL_PUBLISH_NEW_CLASS, + ICAL_PUBLISH_UPDATE_CLASS, + ICAL_PUBLISH_FREEBUSY_CLASS, + ICAL_REQUEST_NEW_CLASS, + ICAL_REQUEST_UPDATE_CLASS, + ICAL_REQUEST_RESCHEDULE_CLASS, + ICAL_REQUEST_DELEGATE_CLASS, + ICAL_REQUEST_NEW_ORGANIZER_CLASS, + ICAL_REQUEST_FORWARD_CLASS, + ICAL_REQUEST_STATUS_CLASS, + ICAL_REQUEST_FREEBUSY_CLASS, + ICAL_REPLY_ACCEPT_CLASS, + ICAL_REPLY_DECLINE_CLASS, + ICAL_REPLY_DELEGATE_CLASS, + ICAL_REPLY_CRASHER_ACCEPT_CLASS, + ICAL_REPLY_CRASHER_DECLINE_CLASS, + ICAL_ADD_INSTANCE_CLASS, + ICAL_CANCEL_EVENT_CLASS, + ICAL_CANCEL_INSTANCE_CLASS, + ICAL_CANCEL_ALL_CLASS, + ICAL_REFRESH_CLASS, + ICAL_COUNTER_CLASS, + ICAL_DECLINECOUNTER_CLASS, + ICAL_MALFORMED_CLASS, + ICAL_OBSOLETE_CLASS, /* 21 */ + ICAL_MISSEQUENCED_CLASS, /* 22 */ + ICAL_UNKNOWN_CLASS /* 23 */ +} ical_class; + +ical_class icalclassify(icalcomponent* c,icalcomponent* match, + const char* user); + +icalcomponent* icalclassify_find_overlaps(icalset* set, icalcomponent* comp); + +char* icalclassify_class_to_string(ical_class iclass); + + +#endif /* ICALCLASSIFY_H*/ + + + + + diff --git a/libical/src/libicalss/icalcstp.c b/libical/src/libicalss/icalcstp.c new file mode 100644 index 0000000..ed62b40 --- a/dev/null +++ b/libical/src/libicalss/icalcstp.c @@ -0,0 +1,122 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalcstps.c + CREATOR: ebusboom 23 Jun 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ical.h" +#include "icalcstp.h" +#include "pvl.h" + +// Eugen C. <eug@thekompany.com> +#include <defines.h> +#ifndef _QTWIN_ +#include <sys/types.h> /* For send(), others */ +#include <sys/socket.h> /* For send(), others. */ +#include <unistd.h> +#endif +// Eugen C. <eug@thekompany.com> +#include <errno.h> +#include <stdlib.h> /* for malloc */ +#include <string.h> + + +struct command_map { + enum icalcstp_command command; + char *str; +} command_map[] = +{ + {ICAL_ABORT_COMMAND,"ABORT"}, + {ICAL_AUTHENTICATE_COMMAND,"AUTHENTICATE"}, + {ICAL_CAPABILITY_COMMAND,"CAPABILITY"}, + {ICAL_CONTINUE_COMMAND,"CONTINUE"}, + {ICAL_CALIDEXPAND_COMMAND,"CALIDEXPAND"}, + {ICAL_IDENTIFY_COMMAND,"IDENTIFY"}, + {ICAL_DISCONNECT_COMMAND,"DISCONNECT"}, + {ICAL_SENDDATA_COMMAND,"SENDDATA"}, + {ICAL_STARTTLS_COMMAND,"STARTTLS"}, + {ICAL_UPNEXPAND_COMMAND,"UPNEXPAND"}, + {ICAL_UNKNOWN_COMMAND,"UNKNOWN"} +}; + + +icalcstp_command icalcstp_line_command(char* line) +{ + int i; + + for(i = 0; command_map[i].command != ICAL_UNKNOWN_COMMAND; i++){ + size_t l = strlen(command_map[i].str); + + if(strncmp(line, command_map[i].str, l) == 0){ + return command_map[i].command; + } + + } + + return ICAL_UNKNOWN_COMMAND; +} + +icalrequeststatus icalcstp_line_response_code(char* line) +{ + struct icalreqstattype rs; + + rs = icalreqstattype_from_string(line); + + return rs.code; +} + +int icalcstp_line_is_endofdata(char* line) +{ + if(line[0] == '.' && line[1] == '\n'){ + return 1; + } + + return 0; + +} + +int icalcstp_line_is_mime(char* line) +{ + return 0; +} + + +const char* icalcstp_command_to_string(icalcstp_command command){ + + int i; + + for(i = 0; command_map[i].command != ICAL_UNKNOWN_COMMAND; i++){ + size_t l = strlen(command_map[i].str); + + if(command_map[i].command == command){ + return command_map[i].str; + } + + } + + return command_map[i].str; + +} + diff --git a/libical/src/libicalss/icalcstp.h b/libical/src/libicalss/icalcstp.h new file mode 100644 index 0000000..dfc3618 --- a/dev/null +++ b/libical/src/libicalss/icalcstp.h @@ -0,0 +1,79 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcstp.h + CREATOR: eric 20 April 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalcstp.h + +======================================================================*/ + + +#ifndef ICALCSTP_H +#define ICALCSTP_H + +#include "ical.h" + + +/* Connection state, from the state machine in RFC2445 */ +enum cstps_state { + NO_STATE, + CONNECTED, + AUTHENTICATED, + IDENTIFIED, + DISCONNECTED, + RECEIVE +}; + +/* CSTP Commands that a client can issue to a server */ +typedef enum icalcstp_command { + ICAL_ABORT_COMMAND, + ICAL_AUTHENTICATE_COMMAND, + ICAL_CAPABILITY_COMMAND, + ICAL_CONTINUE_COMMAND, + ICAL_CALIDEXPAND_COMMAND, + ICAL_IDENTIFY_COMMAND, + ICAL_DISCONNECT_COMMAND, + ICAL_SENDDATA_COMMAND, + ICAL_STARTTLS_COMMAND, + ICAL_UPNEXPAND_COMMAND, + ICAL_COMPLETE_COMMAND, + ICAL_UNKNOWN_COMMAND +} icalcstp_command; + + + +/* A statement is a combination of command or response code and a + component that the server and client exchage with each other. */ +struct icalcstp_statement { + icalcstp_command command; + char* str_data; /* If non-NUll use as arguments to command */ + int int_data; /* If non-NULL use as arguments to command */ + + icalrequeststatus code; + + icalcomponent* data; +}; + +const char* icalcstp_command_to_string(icalcstp_command command); +icalcstp_command icalcstp_string_to_command(const char* str); + +#endif /* !ICALCSTP_H */ + + + diff --git a/libical/src/libicalss/icalcstpclient.c b/libical/src/libicalss/icalcstpclient.c new file mode 100644 index 0000000..03a70dd --- a/dev/null +++ b/libical/src/libicalss/icalcstpclient.c @@ -0,0 +1,350 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalcstps.c + CREATOR: ebusboom 23 Jun 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalerror.h" +#include "ical.h" +#include "icalcstp.h" +#include "icalcstpclient.h" +#include "pvl.h" + +// Eugen C. <eug@thekompany.com> +#include <defines.h> +#ifndef _QTWIN_ +#include <sys/types.h> /* For send(), others */ +#include <sys/socket.h> /* For send(), others. */ +#include<unistd.h> +#endif +// Eugen C. <eug@thekompany.com> + +#include <errno.h> +#include <stdlib.h> /* for malloc */ +#include <string.h> + +#define EOL "\n" + + +/* Client state machine */ + +typedef enum icalcstpc_line_type { + ICALCSTPC_RESPONSE_CODE_LINE, + ICALCSTPC_TERMINATOR_LINE, + ICALCSTPC_APPLICATION_DATA_LINE +} icalcstpc_line_type; + +typedef enum icalcstpc_state { + ICALCSTPC_SEND_STATE, + ICALCSTPC_RESPONSE_CODE_STATE, + ICALCSTPC_RESPONSE_DATA_STATE +} icalcstpc_state; + + + +struct icalcstpc_impl { + int timeout; + icalparser *parser; + icalcstp_command command; + icalcstpc_state state; + char* next_output; + char* next_input; +}; + +icalcstpc* icalcstpc_new() +{ + struct icalcstpc_impl *impl; + + impl = malloc(sizeof(struct icalcstpc_impl)); + + if(impl == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + memset(impl,0,sizeof(struct icalcstpc_impl)); + + return impl; +} + +void icalcstpc_free(icalcstpc* cstpc) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstpc; + + if(impl->next_output != 0){ + free(impl->next_output); + } + + if(impl->next_input != 0){ + free(impl->next_input); + } + + + if(impl->parser != 0){ + icalparser_free(impl->parser); + } +} + +/* Get the next string to send to the server */ +char* icalcstpc_next_output(icalcstpc* cstp, char * line) +{ + char* out; + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + if(impl->next_output == 0){ + return 0; + } + + out = impl->next_output; + + impl->next_output = 0; + + icalmemory_add_tmp_buffer(out); + + return out; +} + +/* process the next string sent by the server */ +int icalcstpc_next_input(icalcstpc* cstp, char* line) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + icalcstpc_line_type line_type; + + if(icalcstp_line_is_endofdata(line) || line == 0){ + return 0; + } + + switch (impl->command){ + case ICAL_ABORT_COMMAND:{ + break; + } + case ICAL_AUTHENTICATE_COMMAND:{ + break; + } + case ICAL_CAPABILITY_COMMAND:{ + break; + } + case ICAL_CONTINUE_COMMAND:{ + break; + } + case ICAL_CALIDEXPAND_COMMAND:{ + break; + } + case ICAL_IDENTIFY_COMMAND:{ + break; + } + case ICAL_DISCONNECT_COMMAND:{ + break; + } + case ICAL_SENDDATA_COMMAND:{ + break; + } + case ICAL_STARTTLS_COMMAND:{ + break; + } + case ICAL_UPNEXPAND_COMMAND:{ + break; + } + case ICAL_COMPLETE_COMMAND:{ + break; + } + case ICAL_UNKNOWN_COMMAND:{ + break; + } + default: + break; + } +} + +/* After icalcstpc_next_input returns a 0, there are responses + ready. use these to get them */ +icalcstpc_response icalcstpc_first_response(icalcstpc* cstp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + +} + + +icalcstpc_response icalcstpc_next_response(icalcstpc* cstp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; +} + + +int icalcstpc_set_timeout(icalcstpc* cstp, int sec) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; +} + +icalerrorenum icalcstpc_abort(icalcstpc* cstp) +{ + struct icalcstpc_impl* impl = (struct icalcstpc_impl*)cstp; + + icalerror_check_arg_re(cstp!=0,"cstp",ICAL_BADARG_ERROR); + + impl->next_output = "ABORT\n"; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpclient_setup_output(icalcstpc* cstp, size_t sz) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + if(impl->next_output != 0){ + icalerror_set_errno(ICAL_USAGE_ERROR); + return ICAL_USAGE_ERROR; + } + + impl->next_output = malloc(sz); + + if(impl->next_output == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return ICAL_NEWFAILED_ERROR; + } + + return ICAL_NO_ERROR; + +} + +icalerrorenum icalcstpc_authenticate(icalcstpc* cstp, char* mechanism, + char* data, char* f(char*)) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + char* command_str; + icalerrorenum error; + size_t sz; + + icalerror_check_arg_re(cstp!=0,"cstp",ICAL_BADARG_ERROR); + icalerror_check_arg_re(mechanism!=0,"mechanism",ICAL_BADARG_ERROR); + icalerror_check_arg_re(data!=0,"data",ICAL_BADARG_ERROR); + icalerror_check_arg_re(f!=0,"f",ICAL_BADARG_ERROR); + + impl->command = ICAL_AUTHENTICATE_COMMAND; + + command_str = icalcstp_command_to_string(impl->command); + + sz = strlen(command_str) + strlen(mechanism) + strlen(data) + 4; + + if((error=icalcstpclient_setup_output(cstp,sz)) != ICAL_NO_ERROR){ + return error; + } + + sprintf(impl->next_output,"%s %s %s%s",command_str,mechanism,data,EOL); + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_capability(icalcstpc* cstp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + char* command_str; + icalerrorenum error; + size_t sz; + + icalerror_check_arg_re(cstp!=0,"cstp",ICAL_BADARG_ERROR); + + impl->command = ICAL_CAPABILITY_COMMAND; + + command_str = icalcstp_command_to_string(impl->command); + + sz = strlen(command_str); + + if((error=icalcstpclient_setup_output(cstp,sz)) != ICAL_NO_ERROR){ + return error; + } + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_calidexpand(icalcstpc* cstp,char* calid) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + impl->command = ICAL_CALIDEXPAND_COMMAND; + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_continue(icalcstpc* cstp, unsigned int time) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + impl->command = ICAL_CONTINUE_COMMAND; + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_disconnect(icalcstpc* cstp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + + impl->command = ICAL_DISCONNECT_COMMAND; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_identify(icalcstpc* cstp, char* id) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + + impl->command = ICAL_IDENTIFY_COMMAND; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_starttls(icalcstpc* cstp, char* command, + char* data, char * f(char*)) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + impl->command = ICAL_STARTTLS_COMMAND; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_upnexpand(icalcstpc* cstp,char* calid) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + + impl->command = ICAL_UPNEXPAND_COMMAND; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_sendata(icalcstpc* cstp, unsigned int time, + icalcomponent *comp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + impl->command = ICAL_SENDDATA_COMMAND; + + return ICAL_NO_ERROR; +} + + + + diff --git a/libical/src/libicalss/icalcstpclient.h b/libical/src/libicalss/icalcstpclient.h new file mode 100644 index 0000000..8d9d0c9 --- a/dev/null +++ b/libical/src/libicalss/icalcstpclient.h @@ -0,0 +1,100 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcstpclient.h + CREATOR: eric 4 Feb 01 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalcstp.h + +======================================================================*/ + + +#ifndef ICALCSTPC_H +#define ICALCSTPC_H + +#include "ical.h" +#include "icalcstp.h" + +/********************** Client (Sender) Interfaces **************************/ + +/* How to use: + + 1) Construct a new icalcstpc + 2) Issue a command by calling one of the command routines. + 3) Repeat until both call icalcstpc_next_output and + icalcstpc_next_input return 0: + 3a) Call icalcstpc_next_output. Send string to server. + 3b) Get string from server, & give to icalcstp_next_input() + 4) Iterate with icalcstpc_first_response & icalcstp_next_response to + get the servers responses + 5) Repeat at #2 +*/ + + +typedef void icalcstpc; + +/* Response code sent by the server. */ +typedef struct icalcstpc_response { + icalrequeststatus code; + char *arg; /* These strings are owned by libical */ + char *debug_text; + char *more_text; + void* result; +} icalcstpc_response; + + +icalcstpc* icalcstpc_new(); + +void icalcstpc_free(icalcstpc* cstpc); + +int icalcstpc_set_timeout(icalcstpc* cstp, int sec); + + +/* Get the next string to send to the server */ +char* icalcstpc_next_output(icalcstpc* cstp, char* line); + +/* process the next string from the server */ +int icalcstpc_next_input(icalcstpc* cstp, char * line); + +/* After icalcstpc_next_input returns a 0, there are responses + ready. use these to get them */ +icalcstpc_response icalcstpc_first_response(icalcstpc* cstp); +icalcstpc_response icalcstpc_next_response(icalcstpc* cstp); + +/* Issue a command */ +icalerrorenum icalcstpc_abort(icalcstpc* cstp); +icalerrorenum icalcstpc_authenticate(icalcstpc* cstp, char* mechanism, + char* init_data, char* f(char*) ); +icalerrorenum icalcstpc_capability(icalcstpc* cstp); +icalerrorenum icalcstpc_calidexpand(icalcstpc* cstp,char* calid); +icalerrorenum icalcstpc_continue(icalcstpc* cstp, unsigned int time); +icalerrorenum icalcstpc_disconnect(icalcstpc* cstp); +icalerrorenum icalcstpc_identify(icalcstpc* cstp, char* id); +icalerrorenum icalcstpc_starttls(icalcstpc* cstp, char* command, + char* init_data, char* f(char*)); +icalerrorenum icalcstpc_senddata(icalcstpc* cstp, unsigned int time, + icalcomponent *comp); +icalerrorenum icalcstpc_upnexpand(icalcstpc* cstp,char* calid); +icalerrorenum icalcstpc_sendata(icalcstpc* cstp, unsigned int time, + icalcomponent *comp); + + +#endif /* !ICALCSTPC_H */ + + + diff --git a/libical/src/libicalss/icalcstpserver.c b/libical/src/libicalss/icalcstpserver.c new file mode 100644 index 0000000..cd8b3bb --- a/dev/null +++ b/libical/src/libicalss/icalcstpserver.c @@ -0,0 +1,285 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalcstpserver.c + CREATOR: ebusboom 13 Feb 01 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalerror.h" +#include "ical.h" +#include "icalcstp.h" +#include "icalcstpserver.h" +#include "pvl.h" + +// Eugen C. <eug@thekompany.com> +#include <defines.h> +#ifndef _QTWIN_ +#include <sys/types.h> /* For send(), others */ +#include <sys/socket.h> /* For send(), others. */ +#include<unistd.h> +#endif +// Eugen C. <eug@thekompany.com> + +#include <errno.h> +#include <stdlib.h> /* for malloc */ +#include <string.h> + + + +struct icalcstps_impl { + int timeout; + icalparser *parser; + enum cstps_state major_state; + struct icalcstps_commandfp commandfp; +}; + + + + +/* This state machine is a Mealy-type: actions occur on the + transitions, not in the states. + + Here is the state machine diagram from the CAP draft: + + + STARTTLS / + CAPABILITY + +-------+ + | | +---------------+ + | +-----------+ AUTHENTICATE | | + +-->| Connected |-------------->| Authenticated | + +-----------+ | | + | +---------------+ + | | + | | + | | + | | +-----+ STARTTLS / + | V | | CAPABILITY / + | +---------------+ | IDENTIFY + | | |<-+ + | | Identified |<----+ + | +--------| | | + | | +---------------+ | command + | | | | completes + V |DISCONNECT | | + +--------------+ | |SENDDATA | + | Disconnected |<--+ | | + +--------------+ | | ABORT + A | | + | V | + | DISCONNECT +---------------+ | + +--------------------| Receive |--+ + | |<--+ + +---------------+ | + | | CONTINUTE + +----+ + + In this implmenetation, the transition from CONNECTED to IDENTIFIED + is non-standard. The spec specifies that on the ATHENTICATE + command, the machine transitions from CONNECTED to AUTHENTICATED, + and then immediately goes to IDENTIFIED. This makes AUTHENTICATED a + useless state, so I removed it */ + +struct state_table { + enum cstps_state major_state; + enum icalcstp_command command; + void (*action)(); + enum cstps_state next_state; + +} server_state_table[] = +{ + { CONNECTED, ICAL_CAPABILITY_COMMAND , 0, CONNECTED}, + { CONNECTED, ICAL_AUTHENTICATE_COMMAND , 0, IDENTIFIED}, /* Non-standard */ + { IDENTIFIED, ICAL_STARTTLS_COMMAND, 0, IDENTIFIED}, + { IDENTIFIED, ICAL_IDENTIFY_COMMAND, 0, IDENTIFIED}, + { IDENTIFIED, ICAL_CAPABILITY_COMMAND, 0, IDENTIFIED}, + { IDENTIFIED, ICAL_SENDDATA_COMMAND, 0, RECEIVE}, + { IDENTIFIED, ICAL_DISCONNECT_COMMAND, 0, DISCONNECTED}, + { DISCONNECTED, 0, 0, 0}, + { RECEIVE, ICAL_DISCONNECT_COMMAND, 0, DISCONNECTED}, + { RECEIVE, ICAL_CONTINUE_COMMAND, 0, RECEIVE}, + { RECEIVE, ICAL_ABORT_COMMAND , 0, IDENTIFIED}, + { RECEIVE, ICAL_COMPLETE_COMMAND , 0, IDENTIFIED} +}; + + +/**********************************************************************/ + + + +icalcstps* icalcstps_new(struct icalcstps_commandfp cfp) +{ + struct icalcstps_impl* impl; + + if ( ( impl = (struct icalcstps_impl*) + malloc(sizeof(struct icalcstps_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + impl->commandfp = cfp; + impl->timeout = 10; + + return (icalcstps*)impl; + +} + +void icalcstps_free(icalcstps* cstp); + +int icalcstps_set_timeout(icalcstps* cstp, int sec) +{ + struct icalcstps_impl *impl = (struct icalcstps_impl *) cstp; + + icalerror_check_arg_rz( (cstp!=0), "cstp"); + + impl->timeout = sec; + + return sec; +} + +typedef struct icalcstps_response { + icalrequeststatus code; + char caluid[1024]; + void* result; +} icalcstps_response; + + +icalerrorenum prep_abort(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_authenticate(struct icalcstps_impl* impl, char* data) +{ return ICAL_NO_ERROR; +} +icalerrorenum prep_capability(struct icalcstps_impl* impl, char* data) +{ return ICAL_NO_ERROR; +} +icalerrorenum prep_calidexpand(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_continue(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_disconnect(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_identify(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_starttls(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_upnexpand(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_sendata(struct icalcstps_impl* impl, char* data) +{ return ICAL_NO_ERROR; +} + +char* icalcstps_process_incoming(icalcstps* cstp, char* input) +{ + struct icalcstps_impl *impl = (struct icalcstps_impl *) cstp; + char *i; + char *cmd_or_resp; + char *data; + char *input_cpy; + icalerrorenum error; + + icalerror_check_arg_rz(cstp !=0,"cstp"); + icalerror_check_arg_rz(input !=0,"input"); + + if ((input_cpy = (char*)strdup(input)) == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + i = (char*)strstr(" ",input_cpy); + + cmd_or_resp = input_cpy; + + if (i != 0){ + *i = '\0'; + data = ++i; + } else { + data = 0; + } + + printf("cmd: %s\n",cmd_or_resp); + printf("data: %s\n",data); + + /* extract the command, look up in the state table, and dispatch + to the proper handler */ + + if(strcmp(cmd_or_resp,"ABORT") == 0){ + error = prep_abort(impl,data); + } else if(strcmp(cmd_or_resp,"AUTHENTICATE") == 0){ + error = prep_authenticate(impl,data); + } else if(strcmp(cmd_or_resp,"CAPABILITY") == 0){ + error = prep_capability(impl,data); + } else if(strcmp(cmd_or_resp,"CALIDEXPAND") == 0){ + error = prep_calidexpand(impl,data); + } else if(strcmp(cmd_or_resp,"CONTINUE") == 0){ + error = prep_continue(impl,data); + } else if(strcmp(cmd_or_resp,"DISCONNECT") == 0){ + error = prep_disconnect(impl,data); + } else if(strcmp(cmd_or_resp,"IDENTIFY") == 0){ + error = prep_identify(impl,data); + } else if(strcmp(cmd_or_resp,"STARTTLS") == 0){ + error = prep_starttls(impl,data); + } else if(strcmp(cmd_or_resp,"UPNEXPAND") == 0){ + error = prep_upnexpand(impl,data); + } else if(strcmp(cmd_or_resp,"SENDDATA") == 0){ + error = prep_sendata(impl,data); + } + + return 0; +} + + /* Read data until we get a end of data marker */ + + + +struct icalcstps_server_stubs { + icalerrorenum (*abort)(icalcstps* cstp); + icalerrorenum (*authenticate)(icalcstps* cstp, char* mechanism, + char* data); + icalerrorenum (*calidexpand)(icalcstps* cstp, char* calid); + icalerrorenum (*capability)(icalcstps* cstp); + icalerrorenum (*cont)(icalcstps* cstp, unsigned int time); + icalerrorenum (*identify)(icalcstps* cstp, char* id); + icalerrorenum (*disconnect)(icalcstps* cstp); + icalerrorenum (*sendata)(icalcstps* cstp, unsigned int time, + icalcomponent *comp); + icalerrorenum (*starttls)(icalcstps* cstp, char* command, + char* data); + icalerrorenum (*upnexpand)(icalcstps* cstp, char* upn); + icalerrorenum (*unknown)(icalcstps* cstp, char* command, char* data); +}; + diff --git a/libical/src/libicalss/icalcstpserver.h b/libical/src/libicalss/icalcstpserver.h new file mode 100644 index 0000000..6fa2254 --- a/dev/null +++ b/libical/src/libicalss/icalcstpserver.h @@ -0,0 +1,101 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcstpserver.h + CREATOR: eric 13 Feb 01 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalcstp.h + +======================================================================*/ + + +#ifndef ICALCSTPS_H +#define ICALCSTPS_H + +#include "ical.h" + + +/********************** Server (Reciever) Interfaces *************************/ + +/* On the server side, the caller will recieve data from the incoming + socket and pass it to icalcstps_next_input. The caller then takes + the return from icalcstps_next_outpu and sends it out through the + socket. This gives the caller a point of control. If the cstp code + connected to the socket itself, it would be hard for the caller to + do anything else after the cstp code was started. + + All of the server and client command routines will generate + response codes. On the server side, these responses will be turned + into text and sent to the client. On the client side, the reponse + is the one sent from the server. + + Since each command can return multiple responses, the responses are + stored in the icalcstps object and are accesses by + icalcstps_first_response() and icalcstps_next_response() + + How to use: + + 1) Construct a new icalcstps, bound to your code via stubs + 2) Repeat forever: + 2a) Get string from client & give to icalcstps_next_input() + 2b) Repeat until icalcstp_next_output returns 0: + 2b1) Call icalcstps_next_output. + 2b2) Send string to client. +*/ + + + +typedef void icalcstps; + +/* Pointers to the rountines that + icalcstps_process_incoming will call when it recognizes a CSTP + command in the data. BTW, the CONTINUE command is named 'cont' + because 'continue' is a C keyword */ + +struct icalcstps_commandfp { + icalerrorenum (*abort)(icalcstps* cstp); + icalerrorenum (*authenticate)(icalcstps* cstp, char* mechanism, + char* data); + icalerrorenum (*calidexpand)(icalcstps* cstp, char* calid); + icalerrorenum (*capability)(icalcstps* cstp); + icalerrorenum (*cont)(icalcstps* cstp, unsigned int time); + icalerrorenum (*identify)(icalcstps* cstp, char* id); + icalerrorenum (*disconnect)(icalcstps* cstp); + icalerrorenum (*sendata)(icalcstps* cstp, unsigned int time, + icalcomponent *comp); + icalerrorenum (*starttls)(icalcstps* cstp, char* command, + char* data); + icalerrorenum (*upnexpand)(icalcstps* cstp, char* upn); + icalerrorenum (*unknown)(icalcstps* cstp, char* command, char* data); +}; + + + +icalcstps* icalcstps_new(struct icalcstps_commandfp stubs); + +void icalcstps_free(icalcstps* cstp); + +int icalcstps_set_timeout(icalcstps* cstp, int sec); + +/* Get the next string to send to the client */ +char* icalcstps_next_output(icalcstps* cstp); + +/* process the next string from the client */ +int icalcstps_next_input(icalcstps* cstp); + +#endif /* ICALCSTPS */ diff --git a/libical/src/libicalss/icaldirset.c b/libical/src/libicalss/icaldirset.c new file mode 100644 index 0000000..b6cb673 --- a/dev/null +++ b/libical/src/libicalss/icaldirset.c @@ -0,0 +1,777 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icaldirset.c + CREATOR: eric 28 November 1999 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +/* + + icaldirset manages a database of ical components and offers + interfaces for reading, writting and searching for components. + + icaldirset groups components in to clusters based on their DTSTAMP + time -- all components that start in the same month are grouped + together in a single file. All files in a sotre are kept in a single + directory. + + The primary interfaces are icaldirset_first and icaldirset_next. These + routine iterate through all of the components in the store, subject + to the current gauge. A gauge is an icalcomponent that is tested + against other componets for a match. If a gauge has been set with + icaldirset_select, icaldirset_first and icaldirset_next will only + return componentes that match the gauge. + + The Store generated UIDs for all objects that are stored if they do + not already have a UID. The UID is the name of the cluster (month & + year as MMYYYY) plus a unique serial number. The serial number is + stored as a property of the cluster. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include "icalerror.h" +#include "ical.h" +#include "icaldirset.h" +#include "pvl.h" +#include "icalparser.h" +#include "icaldirset.h" +#include "icalfileset.h" +#include "icalfilesetimpl.h" +#include "icalgauge.h" + +#include <limits.h> /* For PATH_MAX */ +#include <errno.h> +#include <sys/types.h> /* for opendir() */ +#include <sys/stat.h> /* for stat */ + +int snprintf(char *str, size_t n, char const *fmt, ...); + +// Eugen C. <eug@thekompany.com> +#include <defines.h> +#ifndef _QTWIN_ +#include <dirent.h> /* for opendir() */ +#include <unistd.h> +#include <sys/utsname.h> /* for uname */ +#endif +// Eugen C. <eug@thekompany.com> + +#include <time.h> /* for clock() */ +#include <stdlib.h> /* for rand(), srand() */ +#include <string.h> /* for strdup */ +#include "icaldirsetimpl.h" + + +struct icaldirset_impl* icaldirset_new_impl() +{ + struct icaldirset_impl* impl; + + if ( ( impl = (struct icaldirset_impl*) + malloc(sizeof(struct icaldirset_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + strcpy(impl->id,ICALDIRSET_ID); + + return impl; +} + +const char* icaldirset_path(icaldirset* cluster) +{ + struct icaldirset_impl *impl = icaldirset_new_impl(); + + return impl->dir; + +} + +void icaldirset_mark(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + icalfileset_mark(impl->cluster); +} + + +icalerrorenum icaldirset_commit(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + return icalfileset_commit(impl->cluster); + +} + +void icaldirset_lock(const char* dir) +{ +} + + +void icaldirset_unlock(const char* dir) +{ +} + +/* Load the contents of the store directory into the store's internal directory list*/ +icalerrorenum icaldirset_read_directory(struct icaldirset_impl* impl) +{ +#ifndef _QTWIN_ + struct dirent *de; + DIR* dp; + char *str; + + dp = opendir(impl->dir); + + if ( dp == 0) { + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + + /* clear contents of directory list */ + while((str = pvl_pop(impl->directory))){ + free(str); + } + + /* load all of the cluster names in the directory list */ + for(de = readdir(dp); + de != 0; + de = readdir(dp)){ + + /* Remove known directory names '.' and '..'*/ + if (strcmp(de->d_name,".") == 0 || + strcmp(de->d_name,"..") == 0 ){ + continue; + } + + pvl_push(impl->directory, (void*)strdup(de->d_name)); + } + + closedir(dp); + + return ICAL_NO_ERROR; +#else + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; +#endif +} + +icaldirset* icaldirset_new(const char* dir) +{ + struct icaldirset_impl *impl = icaldirset_new_impl(); + struct stat sbuf; + + if (impl == 0){ + return 0; + } + + icalerror_check_arg_rz( (dir!=0), "dir"); + + if (stat(dir,&sbuf) != 0){ + icalerror_set_errno(ICAL_FILE_ERROR); + return 0; + } + +#ifndef _QTWIN_ + /* dir is not the name of a direectory*/ + if (!S_ISDIR(sbuf.st_mode)){ + icalerror_set_errno(ICAL_USAGE_ERROR); + return 0; + } +#endif + + icaldirset_lock(dir); + + impl = icaldirset_new_impl(); + + if (impl ==0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + impl->directory = pvl_newlist(); + impl->directory_iterator = 0; + impl->dir = (char*)strdup(dir); + impl->gauge = 0; + impl->first_component = 0; + impl->cluster = 0; + + icaldirset_read_directory(impl); + + return (icaldirset*) impl; +} + +void icaldirset_free(icaldirset* s) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)s; + char* str; + + icaldirset_unlock(impl->dir); + + if(impl->dir !=0){ + free(impl->dir); + } + + if(impl->gauge !=0){ + icalcomponent_free(impl->gauge); + } + + if(impl->cluster !=0){ + icalfileset_free(impl->cluster); + } + + while(impl->directory !=0 && (str=pvl_pop(impl->directory)) != 0){ + free(str); + } + + if(impl->directory != 0){ + pvl_free(impl->directory); + } + + impl->directory = 0; + impl->directory_iterator = 0; + impl->dir = 0; + impl->gauge = 0; + impl->first_component = 0; + + free(impl); + +} + +/* icaldirset_next_uid_number updates a serial number in the Store + directory in a file called SEQUENCE */ + +int icaldirset_next_uid_number(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + char sequence = 0; + char temp[128]; + char filename[ICAL_PATH_MAX]; + char *r; + FILE *f; + struct stat sbuf; + + icalerror_check_arg_rz( (store!=0), "store"); + + sprintf(filename,"%s/%s",impl->dir,"SEQUENCE"); + + /* Create the file if it does not exist.*/ +#ifndef _QTWIN_ + if (stat(filename,&sbuf) == -1 || !S_ISREG(sbuf.st_mode)){ +#else + if (stat(filename,&sbuf) == -1){ +#endif + + f = fopen(filename,"w"); + if (f != 0){ + fprintf(f,"0"); + fclose(f); + } else { + icalerror_warn("Can't create SEQUENCE file in icaldirset_next_uid_number"); + return 0; + } + + } + + if ( (f = fopen(filename,"r+")) != 0){ + + rewind(f); + r = fgets(temp,128,f); + + if (r == 0){ + sequence = 1; + } else { + sequence = atoi(temp)+1; + } + + rewind(f); + + fprintf(f,"%d",sequence); + + fclose(f); + + return sequence; + + } else { + icalerror_warn("Can't create SEQUENCE file in icaldirset_next_uid_number"); + return 0; + } + +} + +icalerrorenum icaldirset_next_cluster(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + char path[ICAL_PATH_MAX]; + + if (impl->directory_iterator == 0){ + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return ICAL_INTERNAL_ERROR; + } + impl->directory_iterator = pvl_next(impl->directory_iterator); + + if (impl->directory_iterator == 0){ + /* There are no more clusters */ + if(impl->cluster != 0){ + icalfileset_free(impl->cluster); + impl->cluster = 0; + } + return ICAL_NO_ERROR; + } + + sprintf(path,"%s/%s",impl->dir,(char*)pvl_data(impl->directory_iterator)); + + icalfileset_free(impl->cluster); + + impl->cluster = icalfileset_new(path); + + return icalerrno; +} + +void icaldirset_add_uid(icaldirset* store, icaldirset* comp) +{ +#ifndef _QTWIN_ + + char uidstring[ICAL_PATH_MAX]; + icalproperty *uid; + struct utsname unamebuf; + + icalerror_check_arg_rv( (store!=0), "store"); + icalerror_check_arg_rv( (comp!=0), "comp"); + + uid = icalcomponent_get_first_property(comp,ICAL_UID_PROPERTY); + + if (uid == 0) { + + uname(&unamebuf); + + sprintf(uidstring,"%d-%s",(int)getpid(),unamebuf.nodename); + + uid = icalproperty_new_uid(uidstring); + icalcomponent_add_property(comp,uid); + } else { + + strcpy(uidstring,icalproperty_get_uid(uid)); + } + +#endif +} + + +/* This assumes that the top level component is a VCALENDAR, and there + is an inner component of type VEVENT, VTODO or VJOURNAL. The inner + component must have a DTAMP property */ + +icalerrorenum icaldirset_add_component(icaldirset* store, icaldirset* comp) +{ + struct icaldirset_impl *impl; + char clustername[ICAL_PATH_MAX]; + icalproperty *dt; + icalvalue *v; + struct icaltimetype tm; + icalerrorenum error = ICAL_NO_ERROR; + icalcomponent *inner; + + impl = (struct icaldirset_impl*)store; + icalerror_check_arg_rz( (store!=0), "store"); + icalerror_check_arg_rz( (comp!=0), "comp"); + + errno = 0; + + icaldirset_add_uid(store,comp); + + /* Determine which cluster this object belongs in. This is a HACK */ + + for(inner = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT); + inner != 0; + inner = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)){ + + dt = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY); + + if (dt != 0){ + break; + } + } + + if (dt == 0){ + + for(inner = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT); + inner != 0; + inner = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)){ + + dt = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY); + + if (dt != 0){ + break; + } + } + + } + + if (dt == 0){ + + + icalerror_warn("The component does not have a DTSTAMP or DTSTART property, so it cannot be added to the store"); + icalerror_set_errno(ICAL_BADARG_ERROR); + return ICAL_BADARG_ERROR; + } + + v = icalproperty_get_value(dt); + + tm = icalvalue_get_datetime(v); + + snprintf(clustername,ICAL_PATH_MAX,"%s/%04d%02d",impl->dir,tm.year,tm.month); + + /* Load the cluster and insert the object */ + + if(impl->cluster != 0 && + strcmp(clustername,icalfileset_path(impl->cluster)) != 0 ){ + icalfileset_free(impl->cluster); + impl->cluster = 0; + } + + if (impl->cluster == 0){ + impl->cluster = icalfileset_new(clustername); + + if (impl->cluster == 0){ + error = icalerrno; + } + } + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return error; + } + + /* Add the component to the cluster */ + + icalfileset_add_component(impl->cluster,comp); + + icalfileset_mark(impl->cluster); + + return ICAL_NO_ERROR; +} + +/* Remove a component in the current cluster. HACK. This routine is a + "friend" of icalfileset, and breaks its encapsulation. It was + either do it this way, or add several layers of interfaces that had + no other use. */ +icalerrorenum icaldirset_remove_component(icaldirset* store, icaldirset* comp) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + struct icalfileset_impl *filesetimpl = + (struct icalfileset_impl*)impl->cluster; + + icalcomponent *filecomp = filesetimpl->cluster; + + icalcompiter i; + int found = 0; + + icalerror_check_arg_re((store!=0),"store",ICAL_BADARG_ERROR); + icalerror_check_arg_re((comp!=0),"comp",ICAL_BADARG_ERROR); + icalerror_check_arg_re((impl->cluster!=0),"Cluster pointer",ICAL_USAGE_ERROR); + + for(i = icalcomponent_begin_component(filecomp,ICAL_ANY_COMPONENT); + icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){ + + icalcomponent *this = icalcompiter_deref(&i); + + if (this == comp){ + found = 1; + break; + } + } + + if (found != 1){ + icalerror_warn("icaldirset_remove_component: component is not part of current cluster"); + icalerror_set_errno(ICAL_USAGE_ERROR); + return ICAL_USAGE_ERROR; + } + + icalfileset_remove_component(impl->cluster,comp); + + icalfileset_mark(impl->cluster); + + /* If the removal emptied the fileset, get the next fileset */ + if( icalfileset_count_components(impl->cluster,ICAL_ANY_COMPONENT)==0){ + + icalerrorenum error = icaldirset_next_cluster(store); + + if(impl->cluster != 0 && error == ICAL_NO_ERROR){ + icalfileset_get_first_component(impl->cluster); + } else { + /* HACK. Not strictly correct for impl->cluster==0 */ + return error; + } + } else { + /* Do nothing */ + } + + return ICAL_NO_ERROR; +} + + + +int icaldirset_count_components(icaldirset* store, + icalcomponent_kind kind) +{ + /* HACK, not implemented */ + + assert(0); + + return 0; +} + + +icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent *c) +{ + fprintf(stderr," icaldirset_fetch_match is not implemented\n"); + assert(0); +} + + +icalcomponent* icaldirset_fetch(icaldirset* store, const char* uid) +{ + icalcomponent *gauge; + icalcomponent *old_gauge; + icalcomponent *c; + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + icalerror_check_arg_rz( (store!=0), "store"); + icalerror_check_arg_rz( (uid!=0), "uid"); + + gauge = + icalcomponent_vanew( + ICAL_VCALENDAR_COMPONENT, + icalcomponent_vanew( + ICAL_VEVENT_COMPONENT, + icalproperty_vanew_uid( + uid, + icalparameter_new_xliccomparetype( + ICAL_XLICCOMPARETYPE_EQUAL), + 0), + 0), + 0); + + old_gauge = impl->gauge; + impl->gauge = gauge; + + c= icaldirset_get_first_component(store); + + impl->gauge = old_gauge; + + icalcomponent_free(gauge); + + return c; +} + + +int icaldirset_has_uid(icaldirset* store, const char* uid) +{ + icalcomponent *c; + + icalerror_check_arg_rz( (store!=0), "store"); + icalerror_check_arg_rz( (uid!=0), "uid"); + + /* HACK. This is a temporary implementation. _has_uid should use a + database, and _fetch should use _has_uid, not the other way + around */ + c = icaldirset_fetch(store,uid); + + return c!=0; + +} + + +icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge) + { + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + icalerror_check_arg_re( (store!=0), "store",ICAL_BADARG_ERROR); + icalerror_check_arg_re( (gauge!=0), "gauge",ICAL_BADARG_ERROR); + + if (!icalcomponent_is_valid(gauge)){ + return ICAL_BADARG_ERROR; + } + + impl->gauge = gauge; + + return ICAL_NO_ERROR; +} + + +icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *old, + icalcomponent *new) +{ + assert(0); + return ICAL_NO_ERROR; /* HACK, not implemented */ + +} + + +void icaldirset_clear(icaldirset* store) +{ + + assert(0); + return; + /* HACK, not implemented */ +} + +icalcomponent* icaldirset_get_current_component(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + if(impl->cluster == 0){ + icaldirset_get_first_component(store); + } + + return icalfileset_get_current_component(impl->cluster); + +} + + +icalcomponent* icaldirset_get_first_component(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + icalerrorenum error; + char path[ICAL_PATH_MAX]; + + error = icaldirset_read_directory(impl); + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return 0; + } + + impl->directory_iterator = pvl_head(impl->directory); + + if (impl->directory_iterator == 0){ + icalerror_set_errno(error); + return 0; + } + + snprintf(path,ICAL_PATH_MAX,"%s/%s",impl->dir,(char*)pvl_data(impl->directory_iterator)); + + /* If the next cluster we need is different than the current cluster, + delete the current one and get a new one */ + + if(impl->cluster != 0 && strcmp(path,icalfileset_path(impl->cluster)) != 0 ){ + icalfileset_free(impl->cluster); + impl->cluster = 0; + } + + if (impl->cluster == 0){ + impl->cluster = icalfileset_new(path); + + if (impl->cluster == 0){ + error = icalerrno; + } + } + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return 0; + } + + impl->first_component = 1; + + return icaldirset_get_next_component(store); +} + +icalcomponent* icaldirset_get_next_component(icaldirset* store) +{ + struct icaldirset_impl *impl; + icalcomponent *c; + icalerrorenum error; + + icalerror_check_arg_rz( (store!=0), "store"); + + impl = (struct icaldirset_impl*)store; + + if(impl->cluster == 0){ + + icalerror_warn("icaldirset_get_next_component called with a NULL cluster (Caller must call icaldirset_get_first_component first"); + icalerror_set_errno(ICAL_USAGE_ERROR); + return 0; + + } + + /* Set the component iterator for the following for loop */ + if (impl->first_component == 1){ + icalfileset_get_first_component(impl->cluster); + impl->first_component = 0; + } else { + icalfileset_get_next_component(impl->cluster); + } + + + while(1){ + /* Iterate through all of the objects in the cluster*/ + for( c = icalfileset_get_current_component(impl->cluster); + c != 0; + c = icalfileset_get_next_component(impl->cluster)){ + + /* If there is a gauge defined and the component does not + pass the gauge, skip the rest of the loop */ + +#if 0 /* HACK */ + if (impl->gauge != 0 && icalgauge_test(c,impl->gauge) == 0){ + continue; + } +#else + assert(0); /* icalgauge_test needs to be fixed */ +#endif + /* Either there is no gauge, or the component passed the + gauge, so return it*/ + + return c; + } + + /* Fell through the loop, so the component we want is not + in this cluster. Load a new cluster and try again.*/ + + error = icaldirset_next_cluster(store); + + if(impl->cluster == 0 || error != ICAL_NO_ERROR){ + /* No more clusters */ + return 0; + } else { + c = icalfileset_get_first_component(impl->cluster); + + return c; + } + + } + + return 0; /* Should never get here */ +} + + + + + + + diff --git a/libical/src/libicalss/icaldirset.h b/libical/src/libicalss/icaldirset.h new file mode 100644 index 0000000..7d205ec --- a/dev/null +++ b/libical/src/libicalss/icaldirset.h @@ -0,0 +1,82 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icaldirset.h + CREATOR: eric 28 November 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALDIRSET_H +#define ICALDIRSET_H + +#include "ical.h" + +/* icaldirset Routines for storing, fetching, and searching for ical + * objects in a database */ + +typedef void icaldirset; + + +icaldirset* icaldirset_new(const char* path); + +void icaldirset_free(icaldirset* store); + +const char* icaldirset_path(icaldirset* store); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately*/ +void icaldirset_mark(icaldirset* store); +icalerrorenum icaldirset_commit(icaldirset* store); + +icalerrorenum icaldirset_add_component(icaldirset* store, icalcomponent* comp); +icalerrorenum icaldirset_remove_component(icaldirset* store, icalcomponent* comp); + +int icaldirset_count_components(icaldirset* store, + icalcomponent_kind kind); + +/* Restrict the component returned by icaldirset_first, _next to those + that pass the gauge. _clear removes the gauge. */ +icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge); +void icaldirset_clear(icaldirset* store); + +/* Get a component by uid */ +icalcomponent* icaldirset_fetch(icaldirset* store, const char* uid); +int icaldirset_has_uid(icaldirset* store, const char* uid); +icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent *c); + +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *oldc, + icalcomponent *newc); + +/* Iterate through the components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icaldirset_get_current_component(icaldirset* store); +icalcomponent* icaldirset_get_first_component(icaldirset* store); +icalcomponent* icaldirset_get_next_component(icaldirset* store); + +#endif /* !ICALDIRSET_H */ + + + diff --git a/libical/src/libicalss/icaldirsetimpl.h b/libical/src/libicalss/icaldirsetimpl.h new file mode 100644 index 0000000..0e69ba2 --- a/dev/null +++ b/libical/src/libicalss/icaldirsetimpl.h @@ -0,0 +1,47 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icaldirsetimpl.h + CREATOR: eric 21 Aug 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* This definition is in its own file so it can be kept out of the + main header file, but used by "friend classes" like icalset*/ + +#define ICALDIRSET_ID "dset" + +struct icaldirset_impl +{ + char id[5]; /* "dset" */ + char* dir; + icalcomponent* gauge; + icaldirset* cluster; + int first_component; + pvl_list directory; + pvl_elem directory_iterator; +}; diff --git a/libical/src/libicalss/icalfileset.c b/libical/src/libicalss/icalfileset.c new file mode 100644 index 0000000..943071d --- a/dev/null +++ b/libical/src/libicalss/icalfileset.c @@ -0,0 +1,659 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalfileset.c + CREATOR: eric 23 December 1999 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <fcntl.h> /* For open() flags and mode */ +#include <sys/types.h> /* For open() flags and mode */ +#include <sys/stat.h> /* For open() flags and mode */ + +#include "icalfileset.h" +#include "icalfilesetimpl.h" + +// Eugen C. <eug@thekompany.com> +#include <defines.h> +// + +int snprintf(char *str, size_t n, char const *fmt, ...); + +//extern int errno; + +int icalfileset_lock(icalfileset *cluster); +int icalfileset_unlock(icalfileset *cluster); +icalerrorenum icalfileset_read_file(icalfileset* cluster, mode_t mode); +int icalfileset_filesize(icalfileset* cluster); + +icalerrorenum icalfileset_create_cluster(const char *path); + +icalfileset* icalfileset_new_impl() +{ + struct icalfileset_impl* impl; + + if ( ( impl = (struct icalfileset_impl*) + malloc(sizeof(struct icalfileset_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + errno = ENOMEM; + return 0; + } + + memset(impl,0,sizeof(struct icalfileset_impl)); + + strcpy(impl->id,ICALFILESET_ID); + + return impl; +} + + +icalfileset* icalfileset_new(const char* path) +{ + return icalfileset_new_open(path, O_RDWR|O_CREAT, 0664); +} + +icalfileset* icalfileset_new_open(const char* path, int flags, mode_t mode) +{ + struct icalfileset_impl *impl = icalfileset_new_impl(); + struct icaltimetype tt; + off_t cluster_file_size; + + memset(&tt,0,sizeof(struct icaltimetype)); + + icalerror_clear_errno(); + icalerror_check_arg_rz( (path!=0), "path"); + + if (impl == 0){ + return 0; + } + + impl->path = strdup(path); + + cluster_file_size = icalfileset_filesize(impl); + + if(cluster_file_size < 0){ + icalfileset_free(impl); + return 0; + } + + impl->fd = open(impl->path,flags, mode); + + if (impl->fd < 0){ + icalerror_set_errno(ICAL_FILE_ERROR); + icalfileset_free(impl); + return 0; + } + + icalfileset_lock(impl); + + if(cluster_file_size > 0 ){ + icalerrorenum error; + if((error = icalfileset_read_file(impl,mode))!= ICAL_NO_ERROR){ + icalfileset_free(impl); + return 0; + } + } + + if(impl->cluster == 0){ + impl->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT); + } + + return impl; +} + +char* icalfileset_read_from_file(char *s, size_t size, void *d) +{ + + char* p = s; + int fd = (int)d; + + /* Simulate fgets -- read single characters and stop at '\n' */ + + for(p=s; p<s+size-1;p++){ + + if(read(fd,p,1) != 1 || *p=='\n'){ + p++; + break; + } + } + + *p = '\0'; + + if(*s == 0){ + return 0; + } else { + return s; + } + +} + + +icalerrorenum icalfileset_read_file(icalfileset* cluster,mode_t mode) +{ + + icalparser *parser; + + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + + parser = icalparser_new(); + icalparser_set_gen_data(parser,(void*)impl->fd); + impl->cluster = icalparser_parse(parser,icalfileset_read_from_file); + icalparser_free(parser); + + if (impl->cluster == 0 || icalerrno != ICAL_NO_ERROR){ + icalerror_set_errno(ICAL_PARSE_ERROR); + return ICAL_PARSE_ERROR; + } + + if (icalcomponent_isa(impl->cluster) != ICAL_XROOT_COMPONENT){ + /* The parser got a single component, so it did not put it in + an XROOT. */ + icalcomponent *cl = impl->cluster; + impl->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT); + icalcomponent_add_component(impl->cluster,cl); + } + + return ICAL_NO_ERROR; + +} + +int icalfileset_filesize(icalfileset* cluster) +{ + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + int cluster_file_size; + struct stat sbuf; + + if (stat(impl->path,&sbuf) != 0){ + + /* A file by the given name does not exist, or there was + another error */ + cluster_file_size = 0; + if (errno == ENOENT) { + /* It was because the file does not exist */ + return 0; + } else { + /* It was because of another error */ + icalerror_set_errno(ICAL_FILE_ERROR); + return -1; + } + } else { + /* A file by the given name exists, but is it a regular file? */ + +#ifndef _QTWIN_ + if (!S_ISREG(sbuf.st_mode)){ + /* Nope, not a regular file */ + icalerror_set_errno(ICAL_FILE_ERROR); + return -1; + } else { + /* Lets assume that it is a file of the right type */ + return sbuf.st_size; + } +#else + return sbuf.st_size; +#endif + + } + + /*return -1; not reached*/ +} + +void icalfileset_free(icalfileset* cluster) +{ + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rv((cluster!=0),"cluster"); + + if (impl->cluster != 0){ + icalfileset_commit(cluster); + icalcomponent_free(impl->cluster); + impl->cluster=0; + } + + if(impl->fd > 0){ + icalfileset_unlock(impl); + close(impl->fd); + impl->fd = -1; + } + + if(impl->path != 0){ + free(impl->path); + impl->path = 0; + } + + free(impl); +} + +const char* icalfileset_path(icalfileset* cluster) +{ + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return impl->path; +} + + +int icalfileset_lock(icalfileset *cluster) +{ +#ifndef _WIN32 + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + struct flock lock; + int rtrn; + + icalerror_check_arg_rz((impl->fd>0),"impl->fd"); + errno = 0; + lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */ + lock.l_start = 0; /* byte offset relative to l_whence */ + lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */ + lock.l_len = 0; /* #bytes (0 means to EOF) */ + + rtrn = fcntl(impl->fd, F_SETLKW, &lock); + + return rtrn; +#else + return -1; +#endif +} + +int icalfileset_unlock(icalfileset *cluster) +{ +#ifndef _WIN32 + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + struct flock lock; + icalerror_check_arg_rz((impl->fd>0),"impl->fd"); + + lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */ + lock.l_start = 0; /* byte offset relative to l_whence */ + lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */ + lock.l_len = 0; /* #bytes (0 means to EOF) */ + + return (fcntl(impl->fd, F_UNLCK, &lock)); +#else + return -1; +#endif +} + +#ifdef ICAL_SAFESAVES +int icalfileset_safe_saves=1; +#else +int icalfileset_safe_saves=0; +#endif + +icalerrorenum icalfileset_commit(icalfileset* cluster) +{ + char tmp[ICAL_PATH_MAX]; + char *str; + icalcomponent *c; + off_t write_size=0; + + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR); + + icalerror_check_arg_re((impl->fd>0),"impl->fd is invalid", + ICAL_INTERNAL_ERROR) ; + + if (impl->changed == 0 ){ + return ICAL_NO_ERROR; + } + + if(icalfileset_safe_saves == 1){ + snprintf(tmp,ICAL_PATH_MAX,"cp %s %s.bak",impl->path,impl->path); + + if(system(tmp) < 0){ + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + } + + if(lseek(impl->fd,SEEK_SET,0) < 0){ + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + + for(c = icalcomponent_get_first_component(impl->cluster,ICAL_ANY_COMPONENT); + c != 0; + c = icalcomponent_get_next_component(impl->cluster,ICAL_ANY_COMPONENT)){ + int sz; + + str = icalcomponent_as_ical_string(c); + + sz=write(impl->fd,str,strlen(str)); + + if ( sz != strlen(str)){ + perror("write"); + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + + write_size += sz; + } + + impl->changed = 0; + +#ifndef _QTWIN_ + if(ftruncate(impl->fd,write_size) < 0){ + return ICAL_FILE_ERROR; + } +#endif + + return ICAL_NO_ERROR; + +} + +void icalfileset_mark(icalfileset* cluster){ + + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rv((impl!=0),"cluster"); + + impl->changed = 1; + +} + +icalcomponent* icalfileset_get_component(icalfileset* cluster){ + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR); + + return impl->cluster; +} + + +/* manipulate the components in the cluster */ + +icalerrorenum icalfileset_add_component(icalfileset *cluster, + icalcomponent* child) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_re((cluster!=0),"cluster", ICAL_BADARG_ERROR); + icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR); + + icalcomponent_add_component(impl->cluster,child); + + icalfileset_mark(cluster); + + return ICAL_NO_ERROR; + +} + +icalerrorenum icalfileset_remove_component(icalfileset *cluster, + icalcomponent* child) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_re((cluster!=0),"cluster",ICAL_BADARG_ERROR); + icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR); + + icalcomponent_remove_component(impl->cluster,child); + + icalfileset_mark(cluster); + + return ICAL_NO_ERROR; +} + +int icalfileset_count_components(icalfileset *cluster, + icalcomponent_kind kind) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + if(cluster == 0){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return -1; + } + + return icalcomponent_count_components(impl->cluster,kind); +} + +icalerrorenum icalfileset_select(icalfileset* set, icalgauge* gauge) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)set; + + icalerror_check_arg_re(gauge!=0,"guage",ICAL_BADARG_ERROR); + + impl->gauge = gauge; + + return ICAL_NO_ERROR; +} + +void icalfileset_clear(icalfileset* gauge) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)gauge; + + impl->gauge = 0; + +} + +icalcomponent* icalfileset_fetch(icalfileset* store,const char* uid) +{ + icalcompiter i; + struct icalfileset_impl* impl = (struct icalfileset_impl*)store; + + for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT); + icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){ + + icalcomponent *this = icalcompiter_deref(&i); + icalcomponent *inner = icalcomponent_get_first_real_component(this); + icalcomponent *p; + const char *this_uid; + + if(inner != 0){ + p = icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY); + this_uid = icalproperty_get_uid(p); + + if(this_uid==0){ + icalerror_warn("icalfileset_fetch found a component with no UID"); + continue; + } + + if (strcmp(uid,this_uid)==0){ + return this; + } + } + } + + return 0; +} + +int icalfileset_has_uid(icalfileset* store,const char* uid) +{ + assert(0); /* HACK, not implemented */ + return 0; +} + +/******* support routines for icalfileset_fetch_match *********/ + +struct icalfileset_id{ + char* uid; + char* recurrence_id; + int sequence; +}; + +void icalfileset_id_free(struct icalfileset_id *id) +{ + if(id->recurrence_id != 0){ + free(id->recurrence_id); + } + + if(id->uid != 0){ + free(id->uid); + } + +} + +struct icalfileset_id icalfileset_get_id(icalcomponent* comp) +{ + + icalcomponent *inner; + struct icalfileset_id id; + icalproperty *p; + + inner = icalcomponent_get_first_real_component(comp); + + p = icalcomponent_get_first_property(inner, ICAL_UID_PROPERTY); + + assert(p!= 0); + + id.uid = strdup(icalproperty_get_uid(p)); + + p = icalcomponent_get_first_property(inner, ICAL_SEQUENCE_PROPERTY); + + if(p == 0) { + id.sequence = 0; + } else { + id.sequence = icalproperty_get_sequence(p); + } + + p = icalcomponent_get_first_property(inner, ICAL_RECURRENCEID_PROPERTY); + + if (p == 0){ + id.recurrence_id = 0; + } else { + icalvalue *v; + v = icalproperty_get_value(p); + id.recurrence_id = strdup(icalvalue_as_ical_string(v)); + + assert(id.recurrence_id != 0); + } + + return id; +} + +/* Find the component that is related to the given + component. Currently, it just matches based on UID and + RECURRENCE-ID */ +icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *comp) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)set; + icalcompiter i; + + struct icalfileset_id comp_id, match_id; + + comp_id = icalfileset_get_id(comp); + + for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT); + icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){ + + icalcomponent *match = icalcompiter_deref(&i); + + match_id = icalfileset_get_id(match); + + if(strcmp(comp_id.uid, match_id.uid) == 0 && + ( comp_id.recurrence_id ==0 || + strcmp(comp_id.recurrence_id, match_id.recurrence_id) ==0 )){ + + /* HACK. What to do with SEQUENCE? */ + + icalfileset_id_free(&match_id); + icalfileset_id_free(&comp_id); + return match; + + } + + icalfileset_id_free(&match_id); + } + + icalfileset_id_free(&comp_id); + return 0; + +} + + +icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *old, + icalcomponent *new) +{ + assert(0); /* HACK, not implemented */ + return ICAL_NO_ERROR; +} + + +/* Iterate through components */ +icalcomponent* icalfileset_get_current_component (icalfileset* cluster) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return icalcomponent_get_current_component(impl->cluster); +} + + +icalcomponent* icalfileset_get_first_component(icalfileset* cluster) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + icalcomponent *c=0; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + + do { + if (c == 0){ + c = icalcomponent_get_first_component(impl->cluster, + ICAL_ANY_COMPONENT); + } else { + c = icalcomponent_get_next_component(impl->cluster, + ICAL_ANY_COMPONENT); + } + + if(c != 0 && (impl->gauge == 0 || + icalgauge_compare(impl->gauge,c) == 1)){ + return c; + } + + } while(c != 0); + + + return 0; +} + +icalcomponent* icalfileset_get_next_component(icalfileset* cluster) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + icalcomponent *c; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + + do { + c = icalcomponent_get_next_component(impl->cluster, + ICAL_ANY_COMPONENT); + + if(c != 0 && (impl->gauge == 0 || + icalgauge_compare(impl->gauge,c) == 1)){ + return c; + } + + } while(c != 0); + + + return 0; +} + diff --git a/libical/src/libicalss/icalfileset.h b/libical/src/libicalss/icalfileset.h new file mode 100644 index 0000000..51254d2 --- a/dev/null +++ b/libical/src/libicalss/icalfileset.h @@ -0,0 +1,107 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalfileset.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALFILESET_H +#define ICALFILESET_H + +#include "icalerror.h" +#include "ical.h" +#include "icalset.h" +#include "icalgauge.h" + +extern int icalfileset_safe_saves; + +typedef void icalfileset; + + +/* icalfileset + icalfilesetfile + icalfilesetdir +*/ + + +icalfileset* icalfileset_new(const char* path); + +#ifdef _WIN32 +#define mode_t int +#endif + +/* Like _new, but takes open() flags for opening the file */ +icalfileset* icalfileset_new_open(const char* path, + int flags, mode_t mode); + +void icalfileset_free(icalfileset* cluster); + +const char* icalfileset_path(icalfileset* cluster); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately. */ +void icalfileset_mark(icalfileset* cluster); +icalerrorenum icalfileset_commit(icalfileset* cluster); + +icalerrorenum icalfileset_add_component(icalfileset* cluster, + icalcomponent* child); + +icalerrorenum icalfileset_remove_component(icalfileset* cluster, + icalcomponent* child); + +int icalfileset_count_components(icalfileset* cluster, + icalcomponent_kind kind); + +/* Restrict the component returned by icalfileset_first, _next to those + that pass the gauge. _clear removes the gauge */ +icalerrorenum icalfileset_select(icalfileset* store, icalgauge* gauge); +void icalfileset_clear(icalfileset* store); + +/* Get and search for a component by uid */ +icalcomponent* icalfileset_fetch(icalfileset* cluster, const char* uid); +int icalfileset_has_uid(icalfileset* cluster, const char* uid); +icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *c); + + +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *oldcomp, + icalcomponent *newcomp); + +/* Iterate through components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icalfileset_get_current_component (icalfileset* cluster); +icalcomponent* icalfileset_get_first_component(icalfileset* cluster); +icalcomponent* icalfileset_get_next_component(icalfileset* cluster); +/* Return a reference to the internal component. You probably should + not be using this. */ + +icalcomponent* icalfileset_get_component(icalfileset* cluster); + + +#endif /* !ICALFILESET_H */ + + + diff --git a/libical/src/libicalss/icalfilesetimpl.h b/libical/src/libicalss/icalfilesetimpl.h new file mode 100644 index 0000000..fcd3415 --- a/dev/null +++ b/libical/src/libicalss/icalfilesetimpl.h @@ -0,0 +1,49 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalfilesetimpl.h + CREATOR: eric 23 December 1999 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalgauge.h" + +/* This definition is in its own file so it can be kept out of the + main header file, but used by "friend classes" like icaldirset*/ + +#define ICALFILESET_ID "fset" + +struct icalfileset_impl { + + char id[5]; /*fset*/ + char *path; + icalcomponent* cluster; + icalgauge* gauge; + int changed; + int fd; /* file descriptor */ +}; + diff --git a/libical/src/libicalss/icalgauge.c b/libical/src/libicalss/icalgauge.c new file mode 100644 index 0000000..b958ecf --- a/dev/null +++ b/libical/src/libicalss/icalgauge.c @@ -0,0 +1,447 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalgauge.c + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#include "ical.h" +#include "icalgauge.h" +#include "icalgaugeimpl.h" +#include <stdlib.h> + +extern char* input_buffer; +extern char* input_buffer_p; +int ssparse(void); + +struct icalgauge_impl *icalss_yy_gauge; + +icalgauge* icalgauge_new_from_sql(char* sql) +{ + struct icalgauge_impl *impl; + + int r; + + if ( ( impl = (struct icalgauge_impl*) + malloc(sizeof(struct icalgauge_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + impl->select = pvl_newlist(); + impl->from = pvl_newlist(); + impl->where = pvl_newlist(); + + icalss_yy_gauge = impl; + + input_buffer_p = input_buffer = sql; + r = ssparse(); + + return impl; +} + + +void icalgauge_free(icalgauge* gauge) +{ + struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge; + struct icalgauge_where *w; + + assert(impl->select != 0); + assert(impl->where != 0); + assert(impl->from != 0); + + if(impl->select){ + while( (w=pvl_pop(impl->select)) != 0){ + if(w->value != 0){ + free(w->value); + } + free(w); + } + pvl_free(impl->select); + } + + if(impl->where){ + while( (w=pvl_pop(impl->where)) != 0){ + + if(w->value != 0){ + free(w->value); + } + free(w); + } + pvl_free(impl->where); + } + + if(impl->from){ + pvl_free(impl->from); + } + +} + +/* Convert a VQUERY component into a gauge */ +icalcomponent* icalgauge_make_gauge(icalcomponent* query); + +/* icaldirset_test compares a component against a gauge, and returns + true if the component passes the test + + The gauge is a VCALENDAR component that specifies how to test the + target components. The guage holds a collection of VEVENT, VTODO or + VJOURNAL sub-components. Each of the sub-components has a + collection of properties that are compared to corresponding + properties in the target component, according to the + X-LIC-COMPARETYPE parameters to the gauge's properties. + + When a gauge has several sub-components, the results of testing the + target against each of them is ORed together - the target + component will pass if it matches any of the sub-components in the + gauge. However, the results of matching the properties in a + sub-component are ANDed -- the target must match every property in + a gauge sub-component to match the sub-component. + + Here is an example: + + BEGIN:XROOT + DTSTART;X-LIC-COMPARETYPE=LESS:19981025T020000 + ORGANIZER;X-LIC-COMPARETYPE=EQUAL:mrbig@host.com + END:XROOT + BEGIN:XROOT + LOCATION;X-LIC-COMPARETYPE=EQUAL:McNary's Pub + END:XROOT + + This gauge has two sub-components; one which will match a VEVENT + based on start time, and organizer, and another that matches based + on LOCATION. A target component will pass the test if it matched + either of the sub-components. + + */ + + +int icalgauge_compare_recurse(icalcomponent* comp, icalcomponent* gauge) +{ + int pass = 1,localpass = 0; + icalproperty *p; + icalcomponent *child,*subgauge; + icalcomponent_kind gaugekind, compkind; + + icalerror_check_arg_rz( (comp!=0), "comp"); + icalerror_check_arg_rz( (gauge!=0), "gauge"); + + gaugekind = icalcomponent_isa(gauge); + compkind = icalcomponent_isa(comp); + + if( ! (gaugekind == compkind || gaugekind == ICAL_ANY_COMPONENT) ){ + return 0; + } + + /* Test properties. For each property in the gauge, search through + the component for a similar property. If one is found, compare + the two properties value with the comparison specified in the + gauge with the X-LIC-COMPARETYPE parameter */ + + for(p = icalcomponent_get_first_property(gauge,ICAL_ANY_PROPERTY); + p != 0; + p = icalcomponent_get_next_property(gauge,ICAL_ANY_PROPERTY)){ + + icalproperty* targetprop; + icalparameter* compareparam; + icalparameter_xliccomparetype compare; + int rel; /* The relationship between the gauge and target values.*/ + + /* Extract the comparison type from the gauge. If there is no + comparison type, assume that it is "EQUAL" */ + + compareparam = icalproperty_get_first_parameter( + p, + ICAL_XLICCOMPARETYPE_PARAMETER); + + if (compareparam!=0){ + compare = icalparameter_get_xliccomparetype(compareparam); + } else { + compare = ICAL_XLICCOMPARETYPE_EQUAL; + } + + /* Find a property in the component that has the same type + as the gauge property. HACK -- multiples of a single + property type in the gauge will match only the first + instance in the component */ + + targetprop = icalcomponent_get_first_property(comp, + icalproperty_isa(p)); + + if(targetprop != 0){ + + /* Compare the values of the gauge property and the target + property */ + + rel = icalvalue_compare(icalproperty_get_value(p), + icalproperty_get_value(targetprop)); + + /* Now see if the comparison is equavalent to the comparison + specified in the gauge */ + + if (rel == compare){ + localpass++; + } else if (compare == ICAL_XLICCOMPARETYPE_LESSEQUAL && + ( rel == ICAL_XLICCOMPARETYPE_LESS || + rel == ICAL_XLICCOMPARETYPE_EQUAL)) { + localpass++; + } else if (compare == ICAL_XLICCOMPARETYPE_GREATEREQUAL && + ( rel == ICAL_XLICCOMPARETYPE_GREATER || + rel == ICAL_XLICCOMPARETYPE_EQUAL)) { + localpass++; + } else if (compare == ICAL_XLICCOMPARETYPE_NOTEQUAL && + ( rel == ICAL_XLICCOMPARETYPE_GREATER || + rel == ICAL_XLICCOMPARETYPE_LESS)) { + localpass++; + } else { + localpass = 0; + } + + pass = pass && (localpass>0); + } + } + + /* Test subcomponents. Look for a child component that has a + counterpart in the gauge. If one is found, recursively call + icaldirset_test */ + + for(subgauge = icalcomponent_get_first_component(gauge,ICAL_ANY_COMPONENT); + subgauge != 0; + subgauge = icalcomponent_get_next_component(gauge,ICAL_ANY_COMPONENT)){ + + gaugekind = icalcomponent_isa(subgauge); + + if (gaugekind == ICAL_ANY_COMPONENT){ + child = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT); + } else { + child = icalcomponent_get_first_component(comp,gaugekind); + } + + if(child !=0){ + localpass = icalgauge_compare_recurse(child,subgauge); + pass = pass && localpass; + } else { + pass = 0; + } + } + + return pass; +} + + +int icalgauge_compare(icalgauge* gauge,icalcomponent* comp) +{ + + struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge; + icalcomponent *inner; + int local_pass = 0; + int last_clause = 1, this_clause = 1; + pvl_elem e; + + icalerror_check_arg_rz( (comp!=0), "comp"); + icalerror_check_arg_rz( (gauge!=0), "gauge"); + + inner = icalcomponent_get_first_real_component(comp); + + if(inner == 0){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return 0; + } + + + /* Check that this component is one of the FROM types */ + local_pass = 0; + for(e = pvl_head(impl->from);e!=0;e=pvl_next(e)){ + icalcomponent_kind k = (icalcomponent_kind)pvl_data(e); + + if(k == icalcomponent_isa(inner)){ + local_pass=1; + } + } + + if(local_pass == 0){ + return 0; + } + + + /* Check each where clause against the component */ + for(e = pvl_head(impl->where);e!=0;e=pvl_next(e)){ + struct icalgauge_where *w = pvl_data(e); + icalcomponent *sub_comp; + icalvalue *v; + icalproperty *prop; + icalvalue_kind vk; + + if(w->prop == ICAL_NO_PROPERTY || w->value == 0){ + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return 0; + } + + /* First, create a value from the gauge */ + vk = icalenum_property_kind_to_value_kind(w->prop); + + if(vk == ICAL_NO_VALUE){ + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return 0; + } + + v = icalvalue_new_from_string(vk,w->value); + + if (v == 0){ + /* Keep error set by icalvalue_from-string*/ + return 0; + } + + /* Now find the corresponding property in the component, + descending into a sub-component if necessary */ + + if(w->comp == ICAL_NO_COMPONENT){ + sub_comp = inner; + } else { + sub_comp = icalcomponent_get_first_component(inner,w->comp); + if(sub_comp == 0){ + return 0; + } + } + + this_clause = 0; + local_pass = 0; + for(prop = icalcomponent_get_first_property(sub_comp,w->prop); + prop != 0; + prop = icalcomponent_get_next_property(sub_comp,w->prop)){ + icalvalue* prop_value; + icalgaugecompare relation; + + prop_value = icalproperty_get_value(prop); + + relation = (icalgaugecompare)icalvalue_compare(prop_value,v); + + if (relation == w->compare){ + local_pass++; + } else if (w->compare == ICALGAUGECOMPARE_LESSEQUAL && + ( relation == ICALGAUGECOMPARE_LESS || + relation == ICALGAUGECOMPARE_EQUAL)) { + local_pass++; + } else if (w->compare == ICALGAUGECOMPARE_GREATEREQUAL && + ( relation == ICALGAUGECOMPARE_GREATER || + relation == ICALGAUGECOMPARE_EQUAL)) { + local_pass++; + } else if (w->compare == ICALGAUGECOMPARE_NOTEQUAL && + ( relation == ICALGAUGECOMPARE_GREATER || + relation == ICALGAUGECOMPARE_LESS)) { + local_pass++; + } else { + local_pass = 0; + } + } + + this_clause = local_pass > 0 ? 1 : 0; + + /* Now look at the logic operator for this clause to see how + the value should be merge with the previous clause */ + + if(w->logic == ICALGAUGELOGIC_AND){ + last_clause = this_clause && last_clause; + } else if(w->logic == ICALGAUGELOGIC_AND) { + last_clause = this_clause || last_clause; + } else { + last_clause = this_clause; + } + } + + return last_clause; + +} + + +void icalgauge_dump(icalcomponent* gauge) +{ + + pvl_elem *p; + struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge; + + + printf("--- Select ---\n"); + for(p = pvl_head(impl->select);p!=0;p=pvl_next(p)){ + struct icalgauge_where *w = pvl_data(p); + + if(w->comp != ICAL_NO_COMPONENT){ + printf("%s ",icalenum_component_kind_to_string(w->comp)); + } + + if(w->prop != ICAL_NO_PROPERTY){ + printf("%s ",icalenum_property_kind_to_string(w->prop)); + } + + if (w->compare != ICALGAUGECOMPARE_NONE){ + printf("%d ",w->compare); + } + + + if (w->value!=0){ + printf("%s",w->value); + } + + + printf("\n"); + } + + printf("--- From ---\n"); + for(p = pvl_head(impl->from);p!=0;p=pvl_next(p)){ + icalcomponent_kind k = (icalcomponent_kind)pvl_data(p); + + printf("%s\n",icalenum_component_kind_to_string(k)); + } + + printf("--- Where ---\n"); + for(p = pvl_head(impl->where);p!=0;p=pvl_next(p)){ + struct icalgauge_where *w = pvl_data(p); + + if(w->logic != ICALGAUGELOGIC_NONE){ + printf("%d ",w->logic); + } + + if(w->comp != ICAL_NO_COMPONENT){ + printf("%s ",icalenum_component_kind_to_string(w->comp)); + } + + if(w->prop != ICAL_NO_PROPERTY){ + printf("%s ",icalenum_property_kind_to_string(w->prop)); + } + + if (w->compare != ICALGAUGECOMPARE_NONE){ + printf("%d ",w->compare); + } + + + if (w->value!=0){ + printf("%s",w->value); + } + + + printf("\n"); + } + + +} + diff --git a/libical/src/libicalss/icalgauge.h b/libical/src/libicalss/icalgauge.h new file mode 100644 index 0000000..1caf0ac --- a/dev/null +++ b/libical/src/libicalss/icalgauge.h @@ -0,0 +1,51 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalgauge.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALGAUGE_H +#define ICALGAUGE_H + +typedef void icalgauge; + +icalgauge* icalgauge_new_from_sql(char* sql); + +void icalgauge_free(icalgauge* gauge); + +char* icalgauge_as_sql(icalcomponent* gauge); + +void icalgauge_dump(icalcomponent* gauge); + +/* Return true is comp matches the gauge. The component must be in + cannonical form -- a VCALENDAR with one VEVENT, VTODO or VJOURNAL + sub component */ +int icalgauge_compare(icalgauge* g, icalcomponent* comp); + +/* Clone the component, but only return the properties specified in + the gauge */ +icalcomponent* icalgauge_new_clone(icalgauge* g, icalcomponent* comp); + +#endif /* ICALGAUGE_H*/ diff --git a/libical/src/libicalss/icalgaugeimpl.h b/libical/src/libicalss/icalgaugeimpl.h new file mode 100644 index 0000000..73a2813 --- a/dev/null +++ b/libical/src/libicalss/icalgaugeimpl.h @@ -0,0 +1,63 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalgaugeimpl.h + CREATOR: eric 09 Aug 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + +======================================================================*/ + +#include "ical.h" + +#include "pvl.h" + +typedef enum icalgaugecompare { + ICALGAUGECOMPARE_EQUAL=ICAL_XLICCOMPARETYPE_EQUAL, + ICALGAUGECOMPARE_LESS=ICAL_XLICCOMPARETYPE_LESS, + ICALGAUGECOMPARE_LESSEQUAL=ICAL_XLICCOMPARETYPE_LESSEQUAL, + ICALGAUGECOMPARE_GREATER=ICAL_XLICCOMPARETYPE_GREATER, + ICALGAUGECOMPARE_GREATEREQUAL=ICAL_XLICCOMPARETYPE_GREATEREQUAL, + ICALGAUGECOMPARE_NOTEQUAL=ICAL_XLICCOMPARETYPE_NOTEQUAL, + ICALGAUGECOMPARE_REGEX=ICAL_XLICCOMPARETYPE_REGEX, + ICALGAUGECOMPARE_NONE=0 +} icalgaugecompare; + +typedef enum icalgaugelogic { + ICALGAUGELOGIC_NONE, + ICALGAUGELOGIC_AND, + ICALGAUGELOGIC_OR +} icalgaugelogic; + + +struct icalgauge_where { + icalgaugelogic logic; + icalcomponent_kind comp; + icalproperty_kind prop; + icalgaugecompare compare; + char* value; +}; + +struct icalgauge_impl +{ + + pvl_list select; /*Of icalgaugecompare, using only prop and comp fields*/ + pvl_list from; /* List of component_kinds, as integers */ + pvl_list where; /* List of icalgaugecompare */ +}; + + diff --git a/libical/src/libicalss/icalmessage.c b/libical/src/libicalss/icalmessage.c new file mode 100644 index 0000000..d5c57c1 --- a/dev/null +++ b/libical/src/libicalss/icalmessage.c @@ -0,0 +1,373 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalmessage.c + CREATOR: ebusboom 07 Nov 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalmessage.h" +#include "icalenums.h" +#include <ctype.h> /* for tolower()*/ +#include <string.h> /* for strstr */ +#include <stdlib.h> /* for free(), malloc() */ +icalcomponent* icalmessage_get_inner(icalcomponent* comp) +{ + if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){ + return icalcomponent_get_first_real_component(comp); + } else { + return comp; + } +} + +char* lowercase(const char* str) +{ + char* p = 0; + char* n = icalmemory_strdup(str); + + if(str ==0){ + return 0; + } + + for(p = n; *p!=0; p++){ + *p = tolower(*p); + } + + return n; +} + +icalproperty* icalmessage_find_attendee(icalcomponent* comp, const char* user) +{ + icalcomponent *inner = icalmessage_get_inner(comp); + icalproperty *p,*attendee = 0; + char* luser = lowercase(user); + + for(p = icalcomponent_get_first_property(inner, ICAL_ATTENDEE_PROPERTY); + p != 0; + p = icalcomponent_get_next_property(inner, ICAL_ATTENDEE_PROPERTY) + ){ + + char* lattendee; + + lattendee = lowercase(icalproperty_get_attendee(p)); + + if (strstr(lattendee,user) != 0){ + attendee = p; + break; + } + + free(lattendee); + + } + + free(luser); + + return attendee; + +} + +void icalmessage_copy_properties(icalcomponent* to, icalcomponent* from, + icalproperty_kind kind) +{ + icalcomponent *to_inner = icalmessage_get_inner(to); + icalcomponent *from_inner = icalmessage_get_inner(from); + + if (to_inner == 0 && from_inner == 0){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return; + } + + if(!icalcomponent_get_first_property(from_inner,kind)){ + return; + } + + icalcomponent_add_property(to_inner, + icalproperty_new_clone( + icalcomponent_get_first_property( + from_inner, + kind) + ) + ); +} + +icalcomponent *icalmessage_new_reply_base(icalcomponent* c, + const char* user, + const char* msg) +{ + icalproperty *attendee; + char tmp[45]; + + icalcomponent *reply = icalcomponent_vanew( + ICAL_VCALENDAR_COMPONENT, + icalproperty_new_method(ICAL_METHOD_REPLY), + icalcomponent_vanew( + ICAL_VEVENT_COMPONENT, + icalproperty_new_dtstamp(icaltime_from_timet(time(0),0)), + 0), + 0); + + icalcomponent *inner = icalmessage_get_inner(reply); + + icalerror_check_arg_rz(c,"c"); + + icalmessage_copy_properties(reply,c,ICAL_UID_PROPERTY); + icalmessage_copy_properties(reply,c,ICAL_ORGANIZER_PROPERTY); + icalmessage_copy_properties(reply,c,ICAL_RECURRENCEID_PROPERTY); + icalmessage_copy_properties(reply,c,ICAL_SUMMARY_PROPERTY); + icalmessage_copy_properties(reply,c,ICAL_SEQUENCE_PROPERTY); + + icalcomponent_set_dtstamp(reply,icaltime_from_timet(time(0),0)); + + if(msg != 0){ + icalcomponent_add_property(inner,icalproperty_new_comment(msg)); + } + + /* Copy this user's attendee property */ + + attendee = icalmessage_find_attendee(c,user); + + if (attendee == 0){ + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + icalcomponent_free(reply); + return 0; + } + + icalcomponent_add_property(inner,icalproperty_new_clone(attendee)); + + /* Add PRODID and VERSION */ + + icalcomponent_add_property(reply,icalproperty_new_version("2.0")); + + sprintf(tmp, + "-//SoftwareStudio//NONSGML %s %s //EN",PACKAGE,VERSION); + icalcomponent_add_property(reply,icalproperty_new_prodid(tmp)); + + return reply; + +} + +icalcomponent* icalmessage_new_accept_reply(icalcomponent* c, + const char* user, + const char* msg) +{ + + icalcomponent *reply; + icalproperty *attendee; + icalcomponent *inner; + + icalerror_check_arg_rz(c,"c"); + + reply = icalmessage_new_reply_base(c,user,msg); + + if(reply == 0){ + return 0; + } + + inner = icalmessage_get_inner(reply); + + attendee = icalcomponent_get_first_property(inner, + ICAL_ATTENDEE_PROPERTY); + + icalproperty_set_parameter(attendee, + icalparameter_new_partstat(ICAL_PARTSTAT_ACCEPTED)); + + return reply; +} + +icalcomponent* icalmessage_new_decline_reply(icalcomponent* c, + const char* user, + const char* msg) +{ + icalcomponent *reply; + icalproperty *attendee; + icalcomponent *inner; + + icalerror_check_arg_rz(c,"c"); + + reply = icalmessage_new_reply_base(c,user,msg); + inner = icalmessage_get_inner(reply); + if(reply == 0){ + return 0; + } + + attendee = icalcomponent_get_first_property(inner, + ICAL_ATTENDEE_PROPERTY); + + icalproperty_set_parameter(attendee, + icalparameter_new_partstat(ICAL_PARTSTAT_DECLINED)); + + return reply; +} + +/* New is modified version of old */ +icalcomponent* icalmessage_new_counterpropose_reply(icalcomponent* oldc, + icalcomponent* newc, + const char* user, + const char* msg) +{ + icalcomponent *reply; + + icalerror_check_arg_rz(oldc,"oldc"); + icalerror_check_arg_rz(newc,"newc"); + + reply = icalcomponent_new_clone(newc); + + icalcomponent_set_method(reply,ICAL_METHOD_COUNTER); + + return newc; + +} + + +icalcomponent* icalmessage_new_delegate_reply(icalcomponent* c, + const char* user, + const char* delegatee, + const char* msg) +{ + + icalcomponent *reply; + icalproperty *attendee; + icalcomponent *inner; + + icalerror_check_arg_rz(c,"c"); + + reply = icalmessage_new_reply_base(c,user,msg); + inner = icalmessage_get_inner(reply); + if(reply == 0){ + return 0; + } + + attendee = icalcomponent_get_first_property(inner, + ICAL_ATTENDEE_PROPERTY); + + icalproperty_set_parameter(attendee, + icalparameter_new_partstat(ICAL_PARTSTAT_DELEGATED)); + + icalproperty_set_parameter(attendee, + icalparameter_new_delegatedto(delegatee)); + + return reply; + +} + +icalcomponent* icalmessage_new_delegate_request(icalcomponent* c, + const char* user, + const char* delegatee, + const char* msg) +{ + + icalcomponent *reply; + icalproperty *attendee; + icalcomponent *inner; + + icalerror_check_arg_rz(c,"c"); + + reply = icalmessage_new_reply_base(c,user,msg); + inner = icalmessage_get_inner(reply); + + if(reply == 0){ + return 0; + } + + icalcomponent_set_method(reply,ICAL_METHOD_REQUEST); + + attendee = icalcomponent_get_first_property(inner, + ICAL_ATTENDEE_PROPERTY); + + icalproperty_set_parameter(attendee, + icalparameter_new_partstat(ICAL_PARTSTAT_DELEGATED)); + + icalproperty_set_parameter(attendee, + icalparameter_new_delegatedto(delegatee)); + + icalcomponent_add_property( + inner, + icalproperty_vanew_attendee( + delegatee, + icalparameter_new_delegatedfrom( + icalproperty_get_attendee(attendee) + ), + 0 + ) + ); + + + return reply; + +} + + +icalcomponent* icalmessage_new_cancel_event(icalcomponent* c, + const char* user, + const char* msg); +icalcomponent* icalmessage_new_cancel_instance(icalcomponent* c, + const char* user, + const char* msg); +icalcomponent* icalmessage_new_cancel_all(icalcomponent* c, + const char* user, + const char* msg); + + + +icalcomponent* icalmessage_new_error_reply(icalcomponent* c, + const char* user, + const char* msg, + const char* debug, + icalrequeststatus code) +{ + icalcomponent *reply; + icalcomponent *inner, *cinner; + struct icalreqstattype rs; + + icalerror_check_arg_rz(c,"c"); + + reply = icalmessage_new_reply_base(c,user,msg); + inner = icalmessage_get_inner(reply); + cinner = icalmessage_get_inner(c); + if(reply == 0){ + return 0; + } + + if( code != ICAL_UNKNOWN_STATUS){ + rs.code = code; + rs.debug = debug; + + icalcomponent_add_property(inner, + icalproperty_new_requeststatus(rs)); + } else { /* code == ICAL_UNKNOWN_STATUS */ + + /* Copy all of the request status properties */ + icalproperty *p; + for(p = icalcomponent_get_first_property(cinner, + ICAL_REQUESTSTATUS_PROPERTY); + p != 0; + p = icalcomponent_get_next_property(cinner, + ICAL_REQUESTSTATUS_PROPERTY)){ + + + icalcomponent_add_property(inner,icalproperty_new_clone(p)); + } + } + + return reply; +} diff --git a/libical/src/libicalss/icalmessage.h b/libical/src/libicalss/icalmessage.h new file mode 100644 index 0000000..24f1c9f --- a/dev/null +++ b/libical/src/libicalss/icalmessage.h @@ -0,0 +1,71 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalmessage.h + CREATOR: eric 07 Nov 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + =========================================================================*/ + +#include "ical.h" + +#ifndef ICALMESSAGE_H +#define ICALMESSAGE_H + + +icalcomponent* icalmessage_new_accept_reply(icalcomponent* c, + const char* user, + const char* msg); + +icalcomponent* icalmessage_new_decline_reply(icalcomponent* c, + const char* user, + const char* msg); + +/* New is modified version of old */ +icalcomponent* icalmessage_new_counterpropose_reply(icalcomponent* oldc, + icalcomponent* newc, + const char* user, + const char* msg); + + +icalcomponent* icalmessage_new_delegate_reply(icalcomponent* c, + const char* user, + const char* delegatee, + const char* msg); + + +icalcomponent* icalmessage_new_cancel_event(icalcomponent* c, + const char* user, + const char* msg); +icalcomponent* icalmessage_new_cancel_instance(icalcomponent* c, + const char* user, + const char* msg); +icalcomponent* icalmessage_new_cancel_all(icalcomponent* c, + const char* user, + const char* msg); + + +icalcomponent* icalmessage_new_error_reply(icalcomponent* c, + const char* user, + const char* msg, + const char* debug, + icalrequeststatus rs); + + +#endif /* ICALMESSAGE_H*/ diff --git a/libical/src/libicalss/icalset.c b/libical/src/libicalss/icalset.c new file mode 100644 index 0000000..2120609 --- a/dev/null +++ b/libical/src/libicalss/icalset.c @@ -0,0 +1,367 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalset.c + CREATOR: eric 17 Jul 2000 + + + Icalset is the "base class" for representations of a collection of + iCal components. Derived classes (actually delegates) include: + + icalfileset Store components in a single file + icaldirset Store components in multiple files in a directory + icalheapset Store components on the heap + icalmysqlset Store components in a mysql database. + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#include "ical.h" +#include "icalset.h" +#include "icalfileset.h" +#include "icalfilesetimpl.h" +#include "icaldirset.h" +#include "icaldirsetimpl.h" +#include <stdlib.h> +/*#include "icalheapset.h"*/ +/*#include "icalmysqlset.h"*/ + +#define ICALSET_ID "set " + +struct icalset_fp { + void (*free)(icalset* set); + const char* (*path)(icalset* set); + void (*mark)(icalset* set); + icalerrorenum (*commit)(icalset* set); + icalerrorenum (*add_component)(icalset* set, icalcomponent* comp); + icalerrorenum (*remove_component)(icalset* set, icalcomponent* comp); + int (*count_components)(icalset* set, + icalcomponent_kind kind); + icalerrorenum (*select)(icalset* set, icalcomponent* gauge); + void (*clear)(icalset* set); + icalcomponent* (*fetch)(icalset* set, const char* uid); + icalcomponent* (*fetch_match)(icalset* set, icalcomponent *comp); + int (*has_uid)(icalset* set, const char* uid); + icalerrorenum (*modify)(icalset* set, icalcomponent *old, + icalcomponent *new); + icalcomponent* (*get_current_component)(icalset* set); + icalcomponent* (*get_first_component)(icalset* set); + icalcomponent* (*get_next_component)(icalset* set); +}; + +struct icalset_fp icalset_dirset_fp = { + icaldirset_free, + icaldirset_path, + icaldirset_mark, + icaldirset_commit, + icaldirset_add_component, + icaldirset_remove_component, + icaldirset_count_components, + icaldirset_select, + icaldirset_clear, + icaldirset_fetch, + icaldirset_fetch_match, + icaldirset_has_uid, + icaldirset_modify, + icaldirset_get_current_component, + icaldirset_get_first_component, + icaldirset_get_next_component +}; + + +struct icalset_fp icalset_fileset_fp = { + icalfileset_free, + icalfileset_path, + icalfileset_mark, + icalfileset_commit, + icalfileset_add_component, + icalfileset_remove_component, + icalfileset_count_components, + icalfileset_select, + icalfileset_clear, + icalfileset_fetch, + icalfileset_fetch_match, + icalfileset_has_uid, + icalfileset_modify, + icalfileset_get_current_component, + icalfileset_get_first_component, + icalfileset_get_next_component +}; + +struct icalset_impl { + + char id[5]; /* "set " */ + + void *derived_impl; + struct icalset_fp *fp; +}; + +/* Figure out what was actually passed in as the set. This could be a + set or and of the derived types such as dirset or fileset. Note + this routine returns a value, not a reference, to avoid memory + leaks in the methods */ +struct icalset_impl icalset_get_impl(icalset* set) +{ + struct icalset_impl impl; + + memset(&impl,0,sizeof(impl)); + icalerror_check_arg_re( (set!=0),"set",impl); + + if(strcmp((char*)set,ICALSET_ID)==0) { + /* It is actually a set, so just sent the reference back out. */ + return *(struct icalset_impl*)set; + } else if(strcmp((char*)set,ICALFILESET_ID)==0) { + /* Make a new set from the fileset */ + impl.fp = &icalset_fileset_fp; + impl.derived_impl = set; + strcpy(impl.id,ICALFILESET_ID);/* HACK. Is this necessary? */ + return impl; + } else if(strcmp((char*)set,ICALDIRSET_ID)==0) { + /* Make a new set from the dirset */ + impl.fp = &icalset_dirset_fp; + impl.derived_impl = set; + strcpy(impl.id,ICALDIRSET_ID);/* HACK. Is this necessary? */ + return impl; + } else { + /* The type of set is unknown, so throw an error */ + icalerror_assert((0),"Unknown set type"); + return impl; + } +} + + +struct icalset_impl* icalset_new_impl() +{ + + struct icalset_impl* impl; + + if ( ( impl = (struct icalset_impl*) + malloc(sizeof(struct icalset_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + strcpy(impl->id,ICALSET_ID); + + impl->derived_impl = 0; + impl->fp = 0; + + return impl; +} + +struct icalset_impl* icalset_new_file_from_ref(icalfileset *fset) +{ + struct icalset_impl *impl = icalset_new_impl(); + + icalerror_check_arg_rz( (fset!=0),"fset"); + + if(impl == 0){ + free(impl); + return 0; + } + + impl->derived_impl = fset; + + if (impl->derived_impl == 0){ + free(impl); + return 0; + } + + impl->fp = &icalset_fileset_fp; + + return (struct icalset_impl*)impl; +} + +icalset* icalset_new_file(const char* path) +{ + icalfileset *fset = icalfileset_new(path); + + if(fset == 0){ + return 0; + } + + return (icalset*)icalset_new_file_from_ref(fset); +} + +icalset* icalset_new_dir_from_ref(icaldirset *dset) +{ + + struct icalset_impl *impl = icalset_new_impl(); + + icalerror_check_arg_rz( (dset!=0),"dset"); + + if(impl == 0){ + return 0; + } + + impl->derived_impl = dset; + + if (impl->derived_impl == 0){ + free(impl); + return 0; + } + + impl->fp = &icalset_dirset_fp; + + return impl; +} + +icalset* icalset_new_dir(const char* path) +{ + icaldirset *dset = icaldirset_new(path); + + if(dset == 0){ + return 0; + } + + return icalset_new_dir_from_ref(dset); +} + +icalset* icalset_new_heap(void) +{ + struct icalset_impl *impl = icalset_new_impl(); + + + if(impl == 0){ + free(impl); + return 0; + } + + return 0; +} + +icalset* icalset_new_mysql(const char* path) +{ + struct icalset_impl *impl = icalset_new_impl(); + + if(impl == 0){ + free(impl); + return 0; + } + + return 0; +} + +void icalset_free(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + (*(impl.fp->free))(impl.derived_impl); + + if(strcmp((char*)set,ICALSET_ID)) { + free(set); + } +} + +const char* icalset_path(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->path))(impl.derived_impl); +} + +void icalset_mark(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + (*(impl.fp->mark))(impl.derived_impl); +} + +icalerrorenum icalset_commit(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->commit))(impl.derived_impl); +} + +icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->add_component))(impl.derived_impl,comp); +} + +icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->remove_component))(impl.derived_impl,comp); +} + +int icalset_count_components(icalset* set,icalcomponent_kind kind) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->count_components))(impl.derived_impl,kind); +} + +icalerrorenum icalset_select(icalset* set, icalcomponent* gauge) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->select))(impl.derived_impl,gauge); +} + +void icalset_clear(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + (*(impl.fp->clear))(impl.derived_impl); +} + +icalcomponent* icalset_fetch(icalset* set, const char* uid) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->fetch))(impl.derived_impl,uid); +} + +icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *comp) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->fetch_match))(impl.derived_impl,comp); +} + + +int icalset_has_uid(icalset* set, const char* uid) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->has_uid))(impl.derived_impl,uid); +} + +icalerrorenum icalset_modify(icalset* set, icalcomponent *old, + icalcomponent *new) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->modify))(impl.derived_impl,old,new); +} + +icalcomponent* icalset_get_current_component(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->get_current_component))(impl.derived_impl); +} + +icalcomponent* icalset_get_first_component(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->get_first_component))(impl.derived_impl); +} + +icalcomponent* icalset_get_next_component(icalset* set) +{ + struct icalset_impl impl = icalset_get_impl(set); + return (*(impl.fp->get_next_component))(impl.derived_impl); +} + + + + diff --git a/libical/src/libicalss/icalset.h b/libical/src/libicalss/icalset.h new file mode 100644 index 0000000..7b083da --- a/dev/null +++ b/libical/src/libicalss/icalset.h @@ -0,0 +1,111 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalset.h + CREATOR: eric 28 November 1999 + + + Icalset is the "base class" for representations of a collection of + iCal components. Derived classes (actually delegatees) include: + + icalfileset Store componetns in a single file + icaldirset Store components in multiple files in a directory + icalheapset Store components on the heap + icalmysqlset Store components in a mysql database. + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALSET_H +#define ICALSET_H + +#include <limits.h> /* For PATH_MAX */ +#include "ical.h" +#include "icalerror.h" + +#ifdef PATH_MAX +#define ICAL_PATH_MAX PATH_MAX +#else +#define ICAL_PATH_MAX 1024 +#endif + + + + +typedef void icalset; + +typedef enum icalset_kind { + ICAL_FILE_SET, + ICAL_DIR_SET, + ICAL_HEAP_SET, + ICAL_MYSQL_SET, + ICAL_CAP_SET +} icalset_kind; + + +/* Create a specific derived type of set */ +icalset* icalset_new_file(const char* path); +icalset* icalset_new_dir(const char* path); +icalset* icalset_new_heap(void); +icalset* icalset_new_mysql(const char* path); +/*icalset* icalset_new_cap(icalcstp* cstp);*/ + +void icalset_free(icalset* set); + +const char* icalset_path(icalset* set); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately*/ +void icalset_mark(icalset* set); +icalerrorenum icalset_commit(icalset* set); + +icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp); +icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp); + +int icalset_count_components(icalset* set, + icalcomponent_kind kind); + +/* Restrict the component returned by icalset_first, _next to those + that pass the gauge. _clear removes the gauge. */ +icalerrorenum icalset_select(icalset* set, icalcomponent* gauge); +void icalset_clear_select(icalset* set); + +/* Get a component by uid */ +icalcomponent* icalset_fetch(icalset* set, const char* uid); +int icalset_has_uid(icalset* set, const char* uid); +icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *c); + +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icalset_modify(icalset* set, icalcomponent *oldc, + icalcomponent *newc); + +/* Iterate through the components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icalset_get_current_component(icalset* set); +icalcomponent* icalset_get_first_component(icalset* set); +icalcomponent* icalset_get_next_component(icalset* set); + +#endif /* !ICALSET_H */ + + + diff --git a/libical/src/libicalss/icalspanlist.c b/libical/src/libicalss/icalspanlist.c new file mode 100644 index 0000000..cab6a81 --- a/dev/null +++ b/libical/src/libicalss/icalspanlist.c @@ -0,0 +1,309 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalspanlist.c + CREATOR: ebusboom 23 aug 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ical.h" +#include "icalspanlist.h" +#include "pvl.h" +#include <stdlib.h> /* for free and malloc */ + +struct icalspanlist_impl { + pvl_list spans; +}; + +int compare_span(void* a, void* b) +{ + struct icaltime_span *span_a = (struct icaltime_span *)a ; + struct icaltime_span *span_b = (struct icaltime_span *)b ; + + if(span_a->start == span_b->start){ + return 0; + } else if(span_a->start < span_b->start){ + return -1; + } else { /*if(span_a->start > span->b.start)*/ + return 1; + } +} + +icalcomponent* icalspanlist_get_inner(icalcomponent* comp) +{ + if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){ + return icalcomponent_get_first_real_component(comp); + } else { + return comp; + } +} + + +void print_span(int c, struct icaltime_span span ); + + +/* Make a free list from a set of component */ +icalspanlist* icalspanlist_new(icalset *set, + struct icaltimetype start, + struct icaltimetype end) +{ + struct icaltime_span range; + pvl_elem itr; + icalcomponent *c,*inner; + icalcomponent_kind kind, inner_kind; + struct icalspanlist_impl *sl; + struct icaltime_span *freetime; + + if ( ( sl = (struct icalspanlist_impl*) + malloc(sizeof(struct icalspanlist_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + sl->spans = pvl_newlist(); + + range.start = icaltime_as_timet(start); + range.end = icaltime_as_timet(end); + + printf("Range start: %s",ctime(&range.start)); + printf("Range end : %s",ctime(&range.end)); + + + /* Get a list of spans of busy time from the events in the set + and order the spans based on the start time */ + + for(c = icalset_get_first_component(set); + c != 0; + c = icalset_get_next_component(set)){ + + struct icaltime_span span; + + kind = icalcomponent_isa(c); + inner = icalcomponent_get_inner(c); + + if(!inner){ + continue; + } + + inner_kind = icalcomponent_isa(inner); + + if( kind != ICAL_VEVENT_COMPONENT && + inner_kind != ICAL_VEVENT_COMPONENT){ + continue; + } + + icalerror_clear_errno(); + + span = icalcomponent_get_span(c); + span.is_busy = 1; + + if(icalerrno != ICAL_NO_ERROR){ + continue; + } + + if ((range.start < span.end && icaltime_is_null_time(end)) || + (range.start < span.end && range.end > span.start )){ + + struct icaltime_span *s; + + if ((s=(struct icaltime_span *) + malloc(sizeof(struct icaltime_span))) == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + memcpy(s,&span,sizeof(span)); + + pvl_insert_ordered(sl->spans,compare_span,(void*)s); + + } + } + + /* Now Fill in the free time spans. loop through the spans. if the + start of the range is not within the span, create a free entry + that runs from the start of the range to the start of the + span. */ + + for( itr = pvl_head(sl->spans); + itr != 0; + itr = pvl_next(itr)) + { + struct icaltime_span *s = (icalproperty*)pvl_data(itr); + + if ((freetime=(struct icaltime_span *) + malloc(sizeof(struct icaltime_span))) == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + if(range.start < s->start){ + freetime->start = range.start; + freetime->end = s->start; + + freetime->is_busy = 0; + + + pvl_insert_ordered(sl->spans,compare_span,(void*)freetime); + } else { + free(freetime); + } + + range.start = s->end; + } + + /* If the end of the range is null, then assume that everything + after the last item in the calendar is open and add a span + that indicates this */ + + if( icaltime_is_null_time(end)){ + struct icaltime_span* last_span; + + last_span = pvl_data(pvl_tail(sl->spans)); + + if (last_span != 0){ + + if ((freetime=(struct icaltime_span *) + malloc(sizeof(struct icaltime_span))) == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + freetime->is_busy = 0; + freetime->start = last_span->end; + freetime->end = freetime->start; + pvl_insert_ordered(sl->spans,compare_span,(void*)freetime); + } + } + + + return sl; + +} + +void icalspanlist_free(icalspanlist* s) +{ + struct icaltime_span *span; + struct icalspanlist_impl* impl = (struct icalspanlist_impl*)s; + + while( (span=pvl_pop(impl->spans)) != 0){ + free(span); + } + + pvl_free(impl->spans); + + impl->spans = 0; +} + + +void icalspanlist_dump(icalspanlist* s){ + + int i = 0; + struct icalspanlist_impl* sl = (struct icalspanlist_impl*)s; + pvl_elem itr; + + for( itr = pvl_head(sl->spans); + itr != 0; + itr = pvl_next(itr)) + { + struct icaltime_span *s = (icalproperty*)pvl_data(itr); + + printf("#%02d %d start: %s",++i,s->is_busy,ctime(&s->start)); + printf(" end : %s",ctime(&s->end)); + + } +} + +icalcomponent* icalspanlist_make_free_list(icalspanlist* sl); +icalcomponent* icalspanlist_make_busy_list(icalspanlist* sl); + +struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl, + struct icaltimetype t) +{ + struct icalspanlist_impl* impl = (struct icalspanlist_impl*)sl; + pvl_elem itr; + struct icalperiodtype period; + struct icaltime_span *s; + + time_t rangett= icaltime_as_timet(t); + + period.start = icaltime_null_time(); + period.end = icaltime_null_time(); + + /* Is the reference time before the first span? If so, assume + that the reference time is free */ + itr = pvl_head(impl->spans); + s = (icalproperty*)pvl_data(itr); + + if (s == 0){ + /* No elements in span */ + return period; + } + + if(rangett <s->start ){ + /* End of period is start of first span if span is busy, end + of the span if it is free */ + period.start = t; + + if (s->is_busy == 0){ + period.end = icaltime_from_timet(s->start,0); + } else { + period.end = icaltime_from_timet(s->end,0); + } + + return period; + } + + /* Otherwise, find the first free span that contains the + reference time. */ + + for( itr = pvl_head(impl->spans); + itr != 0; + itr = pvl_next(itr)) + { + s = (icalproperty*)pvl_data(itr); + + if(s->is_busy == 0 && s->start >= rangett && + ( rangett < s->end || s->end == s->start)){ + + if (rangett < s->start){ + period.start = icaltime_from_timet(s->start,0); + } else { + period.start = icaltime_from_timet(rangett,0); + } + + period.end = icaltime_from_timet(s->end,0); + + return period; + } + + } + + period.start = icaltime_null_time(); + period.end = icaltime_null_time(); + + return period; +} + +struct icalperiodtype icalspanlist_next_busy_time(icalspanlist* sl, + struct icaltimetype t); + diff --git a/libical/src/libicalss/icalspanlist.h b/libical/src/libicalss/icalspanlist.h new file mode 100644 index 0000000..83cb1c8 --- a/dev/null +++ b/libical/src/libicalss/icalspanlist.h @@ -0,0 +1,54 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalspanlist.h + CREATOR: eric 21 Aug 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + =========================================================================*/ +#ifndef ICALSPANLIST_H +#define ICALSPANLIST_H + +#include "ical.h" +#include "icalset.h" + +typedef void icalspanlist; + +/* Make a free list from a set of component. Start and end should be in UTC */ +icalspanlist* icalspanlist_new(icalset *set, + struct icaltimetype start, + struct icaltimetype end); + +void icalspanlist_free(icalspanlist* spl); + +icalcomponent* icalspanlist_make_free_list(icalspanlist* sl); +icalcomponent* icalspanlist_make_busy_list(icalspanlist* sl); + +/* Get first free or busy time after time t. all times are in UTC */ +struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl, + struct icaltimetype t); +struct icalperiodtype icalspanlist_next_busy_time(icalspanlist* sl, + struct icaltimetype t); + +void icalspanlist_dump(icalspanlist* s); + +#endif + + + diff --git a/libical/src/libicalss/icalss.h b/libical/src/libicalss/icalss.h new file mode 100644 index 0000000..cd07919 --- a/dev/null +++ b/libical/src/libicalss/icalss.h @@ -0,0 +1,885 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalgauge.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALGAUGE_H +#define ICALGAUGE_H + +typedef void icalgauge; + +icalgauge* icalgauge_new_from_sql(char* sql); + +void icalgauge_free(icalgauge* gauge); + +char* icalgauge_as_sql(icalcomponent* gauge); + +void icalgauge_dump(icalcomponent* gauge); + +/* Return true is comp matches the gauge. The component must be in + cannonical form -- a VCALENDAR with one VEVENT, VTODO or VJOURNAL + sub component */ +int icalgauge_compare(icalgauge* g, icalcomponent* comp); + +/* Clone the component, but only return the properties specified in + the gauge */ +icalcomponent* icalgauge_new_clone(icalgauge* g, icalcomponent* comp); + +#endif /* ICALGAUGE_H*/ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalset.h + CREATOR: eric 28 November 1999 + + + Icalset is the "base class" for representations of a collection of + iCal components. Derived classes (actually delegatees) include: + + icalfileset Store componetns in a single file + icaldirset Store components in multiple files in a directory + icalheapset Store components on the heap + icalmysqlset Store components in a mysql database. + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALSET_H +#define ICALSET_H + +#include <limits.h> /* For PATH_MAX */ + +#ifdef PATH_MAX +#define ICAL_PATH_MAX PATH_MAX +#else +#define ICAL_PATH_MAX 1024 +#endif + + +#ifdef _WIN32 +#define mode_t int +#endif + + + +typedef void icalset; + +typedef enum icalset_kind { + ICAL_FILE_SET, + ICAL_DIR_SET, + ICAL_HEAP_SET, + ICAL_MYSQL_SET, + ICAL_CAP_SET +} icalset_kind; + + +/* Create a specific derived type of set */ +icalset* icalset_new_file(const char* path); +icalset* icalset_new_dir(const char* path); +icalset* icalset_new_heap(void); +icalset* icalset_new_mysql(const char* path); +/*icalset* icalset_new_cap(icalcstp* cstp);*/ + +void icalset_free(icalset* set); + +const char* icalset_path(icalset* set); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately*/ +void icalset_mark(icalset* set); +icalerrorenum icalset_commit(icalset* set); + +icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp); +icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp); + +int icalset_count_components(icalset* set, + icalcomponent_kind kind); + +/* Restrict the component returned by icalset_first, _next to those + that pass the gauge. _clear removes the gauge. */ +icalerrorenum icalset_select(icalset* set, icalcomponent* gauge); +void icalset_clear_select(icalset* set); + +/* Get a component by uid */ +icalcomponent* icalset_fetch(icalset* set, const char* uid); +int icalset_has_uid(icalset* set, const char* uid); +icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *c); + +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icalset_modify(icalset* set, icalcomponent *oldc, + icalcomponent *newc); + +/* Iterate through the components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icalset_get_current_component(icalset* set); +icalcomponent* icalset_get_first_component(icalset* set); +icalcomponent* icalset_get_next_component(icalset* set); + +#endif /* !ICALSET_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalfileset.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALFILESET_H +#define ICALFILESET_H + +#include <sys/types.h> /* For open() flags and mode */ +#include <sys/stat.h> /* For open() flags and mode */ +#include <fcntl.h> /* For open() flags and mode */ + +extern int icalfileset_safe_saves; + +typedef void icalfileset; + + +/* icalfileset + icalfilesetfile + icalfilesetdir +*/ + + +icalfileset* icalfileset_new(const char* path); + +/* Like _new, but takes open() flags for opening the file */ +icalfileset* icalfileset_new_open(const char* path, + int flags, mode_t mode); + +void icalfileset_free(icalfileset* cluster); + +const char* icalfileset_path(icalfileset* cluster); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately. */ +void icalfileset_mark(icalfileset* cluster); +icalerrorenum icalfileset_commit(icalfileset* cluster); + +icalerrorenum icalfileset_add_component(icalfileset* cluster, + icalcomponent* child); + +icalerrorenum icalfileset_remove_component(icalfileset* cluster, + icalcomponent* child); + +int icalfileset_count_components(icalfileset* cluster, + icalcomponent_kind kind); + +/* Restrict the component returned by icalfileset_first, _next to those + that pass the gauge. _clear removes the gauge */ +icalerrorenum icalfileset_select(icalfileset* store, icalgauge* gauge); +void icalfileset_clear(icalfileset* store); + +/* Get and search for a component by uid */ +icalcomponent* icalfileset_fetch(icalfileset* cluster, const char* uid); +int icalfileset_has_uid(icalfileset* cluster, const char* uid); +icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *c); + + +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *oldcomp, + icalcomponent *newcomp); + +/* Iterate through components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icalfileset_get_current_component (icalfileset* cluster); +icalcomponent* icalfileset_get_first_component(icalfileset* cluster); +icalcomponent* icalfileset_get_next_component(icalfileset* cluster); +/* Return a reference to the internal component. You probably should + not be using this. */ + +icalcomponent* icalfileset_get_component(icalfileset* cluster); + + +#endif /* !ICALFILESET_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icaldirset.h + CREATOR: eric 28 November 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALDIRSET_H +#define ICALDIRSET_H + + +/* icaldirset Routines for storing, fetching, and searching for ical + * objects in a database */ + +typedef void icaldirset; + + +icaldirset* icaldirset_new(const char* path); + +void icaldirset_free(icaldirset* store); + +const char* icaldirset_path(icaldirset* store); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately*/ +void icaldirset_mark(icaldirset* store); +icalerrorenum icaldirset_commit(icaldirset* store); + +icalerrorenum icaldirset_add_component(icaldirset* store, icalcomponent* comp); +icalerrorenum icaldirset_remove_component(icaldirset* store, icalcomponent* comp); + +int icaldirset_count_components(icaldirset* store, + icalcomponent_kind kind); + +/* Restrict the component returned by icaldirset_first, _next to those + that pass the gauge. _clear removes the gauge. */ +icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge); +void icaldirset_clear(icaldirset* store); + +/* Get a component by uid */ +icalcomponent* icaldirset_fetch(icaldirset* store, const char* uid); +int icaldirset_has_uid(icaldirset* store, const char* uid); +icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent *c); + +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *oldc, + icalcomponent *newc); + +/* Iterate through the components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icaldirset_get_current_component(icaldirset* store); +icalcomponent* icaldirset_get_first_component(icaldirset* store); +icalcomponent* icaldirset_get_next_component(icaldirset* store); + +#endif /* !ICALDIRSET_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcalendar.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALCALENDAR_H +#define ICALCALENDAR_H + + +/* icalcalendar + * Routines for storing calendar data in a file system. The calendar + * has two icaldirsets, one for incoming components and one for booked + * components. It also has interfaces to access the free/busy list + * and a list of calendar properties */ + +typedef void icalcalendar; + +icalcalendar* icalcalendar_new(char* dir); + +void icalcalendar_free(icalcalendar* calendar); + +int icalcalendar_lock(icalcalendar* calendar); + +int icalcalendar_unlock(icalcalendar* calendar); + +int icalcalendar_islocked(icalcalendar* calendar); + +int icalcalendar_ownlock(icalcalendar* calendar); + +icalset* icalcalendar_get_booked(icalcalendar* calendar); + +icalset* icalcalendar_get_incoming(icalcalendar* calendar); + +icalset* icalcalendar_get_properties(icalcalendar* calendar); + +icalset* icalcalendar_get_freebusy(icalcalendar* calendar); + + +#endif /* !ICALCALENDAR_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalclassify.h + CREATOR: eric 21 Aug 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + =========================================================================*/ + +#ifndef ICALCLASSIFY_H +#define ICALCLASSIFY_H + + + +typedef enum icalclass { + ICAL_NO_CLASS, + ICAL_PUBLISH_NEW_CLASS, + ICAL_PUBLISH_UPDATE_CLASS, + ICAL_PUBLISH_FREEBUSY_CLASS, + ICAL_REQUEST_NEW_CLASS, + ICAL_REQUEST_UPDATE_CLASS, + ICAL_REQUEST_RESCHEDULE_CLASS, + ICAL_REQUEST_DELEGATE_CLASS, + ICAL_REQUEST_NEW_ORGANIZER_CLASS, + ICAL_REQUEST_FORWARD_CLASS, + ICAL_REQUEST_STATUS_CLASS, + ICAL_REQUEST_FREEBUSY_CLASS, + ICAL_REPLY_ACCEPT_CLASS, + ICAL_REPLY_DECLINE_CLASS, + ICAL_REPLY_DELEGATE_CLASS, + ICAL_REPLY_CRASHER_ACCEPT_CLASS, + ICAL_REPLY_CRASHER_DECLINE_CLASS, + ICAL_ADD_INSTANCE_CLASS, + ICAL_CANCEL_EVENT_CLASS, + ICAL_CANCEL_INSTANCE_CLASS, + ICAL_CANCEL_ALL_CLASS, + ICAL_REFRESH_CLASS, + ICAL_COUNTER_CLASS, + ICAL_DECLINECOUNTER_CLASS, + ICAL_MALFORMED_CLASS, + ICAL_OBSOLETE_CLASS, /* 21 */ + ICAL_MISSEQUENCED_CLASS, /* 22 */ + ICAL_UNKNOWN_CLASS /* 23 */ +} ical_class; + +ical_class icalclassify(icalcomponent* c,icalcomponent* match, + const char* user); + +icalcomponent* icalclassify_find_overlaps(icalset* set, icalcomponent* comp); + +char* icalclassify_class_to_string(ical_class iclass); + + +#endif /* ICALCLASSIFY_H*/ + + + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalspanlist.h + CREATOR: eric 21 Aug 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + =========================================================================*/ +#ifndef ICALSPANLIST_H +#define ICALSPANLIST_H + + +typedef void icalspanlist; + +/* Make a free list from a set of component. Start and end should be in UTC */ +icalspanlist* icalspanlist_new(icalset *set, + struct icaltimetype start, + struct icaltimetype end); + +void icalspanlist_free(icalspanlist* spl); + +icalcomponent* icalspanlist_make_free_list(icalspanlist* sl); +icalcomponent* icalspanlist_make_busy_list(icalspanlist* sl); + +/* Get first free or busy time after time t. all times are in UTC */ +struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl, + struct icaltimetype t); +struct icalperiodtype icalspanlist_next_busy_time(icalspanlist* sl, + struct icaltimetype t); + +void icalspanlist_dump(icalspanlist* s); + +#endif + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalmessage.h + CREATOR: eric 07 Nov 2000 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + =========================================================================*/ + + +#ifndef ICALMESSAGE_H +#define ICALMESSAGE_H + + +icalcomponent* icalmessage_new_accept_reply(icalcomponent* c, + const char* user, + const char* msg); + +icalcomponent* icalmessage_new_decline_reply(icalcomponent* c, + const char* user, + const char* msg); + +/* New is modified version of old */ +icalcomponent* icalmessage_new_counterpropose_reply(icalcomponent* oldc, + icalcomponent* newc, + const char* user, + const char* msg); + + +icalcomponent* icalmessage_new_delegate_reply(icalcomponent* c, + const char* user, + const char* delegatee, + const char* msg); + + +icalcomponent* icalmessage_new_cancel_event(icalcomponent* c, + const char* user, + const char* msg); +icalcomponent* icalmessage_new_cancel_instance(icalcomponent* c, + const char* user, + const char* msg); +icalcomponent* icalmessage_new_cancel_all(icalcomponent* c, + const char* user, + const char* msg); + + +icalcomponent* icalmessage_new_error_reply(icalcomponent* c, + const char* user, + const char* msg, + const char* debug, + icalrequeststatus rs); + + +#endif /* ICALMESSAGE_H*/ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcstp.h + CREATOR: eric 20 April 1999 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalcstp.h + +======================================================================*/ + + +#ifndef ICALCSTP_H +#define ICALCSTP_H + + + +/* Connection state, from the state machine in RFC2445 */ +enum cstps_state { + NO_STATE, + CONNECTED, + AUTHENTICATED, + IDENTIFIED, + DISCONNECTED, + RECEIVE +}; + +/* CSTP Commands that a client can issue to a server */ +typedef enum icalcstp_command { + ICAL_ABORT_COMMAND, + ICAL_AUTHENTICATE_COMMAND, + ICAL_CAPABILITY_COMMAND, + ICAL_CONTINUE_COMMAND, + ICAL_CALIDEXPAND_COMMAND, + ICAL_IDENTIFY_COMMAND, + ICAL_DISCONNECT_COMMAND, + ICAL_SENDDATA_COMMAND, + ICAL_STARTTLS_COMMAND, + ICAL_UPNEXPAND_COMMAND, + ICAL_COMPLETE_COMMAND, + ICAL_UNKNOWN_COMMAND +} icalcstp_command; + + + +/* A statement is a combination of command or response code and a + component that the server and client exchage with each other. */ +struct icalcstp_statement { + icalcstp_command command; + char* str_data; /* If non-NUll use as arguments to command */ + int int_data; /* If non-NULL use as arguments to command */ + + icalrequeststatus code; + + icalcomponent* data; +}; + +const char* icalcstp_command_to_string(icalcstp_command command); +icalcstp_command icalcstp_string_to_command(const char* str); + +#endif /* !ICALCSTP_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcstpclient.h + CREATOR: eric 4 Feb 01 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalcstp.h + +======================================================================*/ + + +#ifndef ICALCSTPC_H +#define ICALCSTPC_H + + +/********************** Client (Sender) Interfaces **************************/ + +/* How to use: + + 1) Construct a new icalcstpc + 2) Issue a command by calling one of the command routines. + 3) Repeat until both call icalcstpc_next_output and + icalcstpc_next_input return 0: + 3a) Call icalcstpc_next_output. Send string to server. + 3b) Get string from server, & give to icalcstp_next_input() + 4) Iterate with icalcstpc_first_response & icalcstp_next_response to + get the servers responses + 5) Repeat at #2 +*/ + + +typedef void icalcstpc; + +/* Response code sent by the server. */ +typedef struct icalcstpc_response { + icalrequeststatus code; + char *arg; /* These strings are owned by libical */ + char *debug_text; + char *more_text; + void* result; +} icalcstpc_response; + + +icalcstpc* icalcstpc_new(); + +void icalcstpc_free(icalcstpc* cstpc); + +int icalcstpc_set_timeout(icalcstpc* cstp, int sec); + + +/* Get the next string to send to the server */ +char* icalcstpc_next_output(icalcstpc* cstp, char* line); + +/* process the next string from the server */ +int icalcstpc_next_input(icalcstpc* cstp, char * line); + +/* After icalcstpc_next_input returns a 0, there are responses + ready. use these to get them */ +icalcstpc_response icalcstpc_first_response(icalcstpc* cstp); +icalcstpc_response icalcstpc_next_response(icalcstpc* cstp); + +/* Issue a command */ +icalerrorenum icalcstpc_abort(icalcstpc* cstp); +icalerrorenum icalcstpc_authenticate(icalcstpc* cstp, char* mechanism, + char* init_data, char* f(char*) ); +icalerrorenum icalcstpc_capability(icalcstpc* cstp); +icalerrorenum icalcstpc_calidexpand(icalcstpc* cstp,char* calid); +icalerrorenum icalcstpc_continue(icalcstpc* cstp, unsigned int time); +icalerrorenum icalcstpc_disconnect(icalcstpc* cstp); +icalerrorenum icalcstpc_identify(icalcstpc* cstp, char* id); +icalerrorenum icalcstpc_starttls(icalcstpc* cstp, char* command, + char* init_data, char* f(char*)); +icalerrorenum icalcstpc_senddata(icalcstpc* cstp, unsigned int time, + icalcomponent *comp); +icalerrorenum icalcstpc_upnexpand(icalcstpc* cstp,char* calid); +icalerrorenum icalcstpc_sendata(icalcstpc* cstp, unsigned int time, + icalcomponent *comp); + + +#endif /* !ICALCSTPC_H */ + + + +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcstpserver.h + CREATOR: eric 13 Feb 01 + + $Id$ + + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The original code is icalcstp.h + +======================================================================*/ + + +#ifndef ICALCSTPS_H +#define ICALCSTPS_H + + + +/********************** Server (Reciever) Interfaces *************************/ + +/* On the server side, the caller will recieve data from the incoming + socket and pass it to icalcstps_next_input. The caller then takes + the return from icalcstps_next_outpu and sends it out through the + socket. This gives the caller a point of control. If the cstp code + connected to the socket itself, it would be hard for the caller to + do anything else after the cstp code was started. + + All of the server and client command routines will generate + response codes. On the server side, these responses will be turned + into text and sent to the client. On the client side, the reponse + is the one sent from the server. + + Since each command can return multiple responses, the responses are + stored in the icalcstps object and are accesses by + icalcstps_first_response() and icalcstps_next_response() + + How to use: + + 1) Construct a new icalcstps, bound to your code via stubs + 2) Repeat forever: + 2a) Get string from client & give to icalcstps_next_input() + 2b) Repeat until icalcstp_next_output returns 0: + 2b1) Call icalcstps_next_output. + 2b2) Send string to client. +*/ + + + +typedef void icalcstps; + +/* Pointers to the rountines that + icalcstps_process_incoming will call when it recognizes a CSTP + command in the data. BTW, the CONTINUE command is named 'cont' + because 'continue' is a C keyword */ + +struct icalcstps_commandfp { + icalerrorenum (*abort)(icalcstps* cstp); + icalerrorenum (*authenticate)(icalcstps* cstp, char* mechanism, + char* data); + icalerrorenum (*calidexpand)(icalcstps* cstp, char* calid); + icalerrorenum (*capability)(icalcstps* cstp); + icalerrorenum (*cont)(icalcstps* cstp, unsigned int time); + icalerrorenum (*identify)(icalcstps* cstp, char* id); + icalerrorenum (*disconnect)(icalcstps* cstp); + icalerrorenum (*sendata)(icalcstps* cstp, unsigned int time, + icalcomponent *comp); + icalerrorenum (*starttls)(icalcstps* cstp, char* command, + char* data); + icalerrorenum (*upnexpand)(icalcstps* cstp, char* upn); + icalerrorenum (*unknown)(icalcstps* cstp, char* command, char* data); +}; + + + +icalcstps* icalcstps_new(struct icalcstps_commandfp stubs); + +void icalcstps_free(icalcstps* cstp); + +int icalcstps_set_timeout(icalcstps* cstp, int sec); + +/* Get the next string to send to the client */ +char* icalcstps_next_output(icalcstps* cstp); + +/* process the next string from the client */ +int icalcstps_next_input(icalcstps* cstp); + +#endif /* ICALCSTPS */ diff --git a/libical/src/libicalss/icalsslexer.c b/libical/src/libicalss/icalsslexer.c new file mode 100644 index 0000000..e10bcd3 --- a/dev/null +++ b/libical/src/libicalss/icalsslexer.c @@ -0,0 +1,1713 @@ +#define yy_create_buffer ss_create_buffer +#define yy_delete_buffer ss_delete_buffer +#define yy_scan_buffer ss_scan_buffer +#define yy_scan_string ss_scan_string +#define yy_scan_bytes ss_scan_bytes +#define yy_flex_debug ss_flex_debug +#define yy_init_buffer ss_init_buffer +#define yy_flush_buffer ss_flush_buffer +#define yy_load_buffer_state ss_load_buffer_state +#define yy_switch_to_buffer ss_switch_to_buffer +#define yyin ssin +#define yyleng ssleng +#define yylex sslex +#define yyout ssout +#define yyrestart ssrestart +#define yytext sstext +#define yywrap sswrap + +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header$ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> +// Eugen C. <eug@thekompany.com> +#include <defines.h> +#ifndef _QTWIN_ +#include <unistd.h> +#else +#include <io.h> +#endif +// Eugen C. <eug@thekompany.com> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char yytext[]; + + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + if ( yyleng >= YYLMAX ) \ + YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \ + yy_flex_strncpy( yytext, yytext_ptr, yyleng + 1 ); \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 19 +#define YY_END_OF_BUFFER 20 +static yyconst short int yy_accept[47] = + { 0, + 0, 0, 0, 0, 0, 0, 20, 18, 14, 14, + 18, 13, 17, 4, 15, 7, 5, 8, 17, 17, + 17, 17, 17, 14, 6, 0, 17, 9, 10, 17, + 17, 12, 17, 17, 16, 11, 17, 17, 17, 2, + 17, 17, 17, 3, 1, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 1, 1, 1, 1, 1, 5, 1, + 1, 6, 1, 7, 6, 6, 1, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 1, 8, 9, + 10, 11, 1, 1, 12, 6, 13, 14, 15, 16, + 6, 17, 6, 6, 6, 18, 19, 20, 21, 6, + 6, 22, 23, 24, 6, 6, 25, 6, 6, 6, + 1, 1, 1, 1, 1, 1, 12, 6, 13, 14, + + 15, 16, 6, 17, 6, 6, 6, 18, 19, 20, + 21, 6, 6, 22, 23, 24, 6, 6, 25, 6, + 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[26] = + { 0, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2 + } ; + +static yyconst short int yy_base[49] = + { 0, + 0, 0, 0, 0, 0, 0, 53, 54, 24, 26, + 42, 0, 0, 54, 54, 41, 54, 40, 29, 26, + 25, 31, 28, 28, 54, 39, 0, 54, 54, 29, + 21, 0, 23, 25, 54, 0, 20, 23, 15, 0, + 23, 20, 10, 0, 0, 54, 31, 30 + } ; + +static yyconst short int yy_def[49] = + { 0, + 46, 1, 1, 1, 1, 1, 46, 46, 46, 46, + 46, 47, 48, 46, 46, 46, 46, 46, 48, 48, + 48, 48, 48, 46, 46, 47, 48, 46, 46, 48, + 48, 48, 48, 48, 46, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 0, 46, 46 + } ; + +static yyconst short int yy_nxt[80] = + { 0, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 13, 13, 13, 20, 13, 13, 13, 13, + 21, 13, 22, 13, 23, 24, 24, 24, 24, 24, + 24, 27, 26, 45, 44, 43, 42, 41, 40, 39, + 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, + 28, 25, 46, 7, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46 + } ; + +static yyconst short int yy_chk[80] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 9, 9, 10, 10, 24, + 24, 48, 47, 43, 42, 41, 39, 38, 37, 34, + 33, 31, 30, 26, 23, 22, 21, 20, 19, 18, + 16, 11, 7, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#ifndef YYLMAX +#define YYLMAX 8192 +#endif + +char yytext[YYLMAX]; +char *yytext_ptr; +#line 1 "icalsslexer.l" +#define INITIAL 0 +#line 2 "icalsslexer.l" +/* -*- Mode: C -*- + ====================================================================== + FILE: icalsslexer.l + CREATOR: eric 8 Aug 2000 + + DESCRIPTION: + + $Id$ + $Locker$ + +(C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + ======================================================================*/ + +#include "icalssyacc.h" +#include "icalgaugeimpl.h" +#include "assert.h" + +#include <string.h> /* For strdup() */ + +int icalparser_flex_input(char* buf, int max_size); +void icalparser_clear_flex_input(); + +#undef YY_INPUT +#define YY_INPUT(b,r,ms) ( r= icalparser_flex_input(b,ms)) + +#undef SS_FATAL_ERROR +#define SS_FATAL_ERROR(msg) sserror(msg) + + +#define sql 1 +#define string_value 2 + +#line 465 "icalsslexer.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp = NULL, *yy_bp = NULL; + register int yy_act; + +#line 69 "icalsslexer.l" + + + + + + +#line 623 "icalsslexer.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 47 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 54 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 75 "icalsslexer.l" +{ return SELECT; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 76 "icalsslexer.l" +{ return FROM; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 77 "icalsslexer.l" +{ return WHERE; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 78 "icalsslexer.l" +{ return COMMA; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 79 "icalsslexer.l" +{ return EQUALS; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 80 "icalsslexer.l" +{ return NOTEQUALS; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 81 "icalsslexer.l" +{ return LESS; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 82 "icalsslexer.l" +{ return GREATER; } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 83 "icalsslexer.l" +{ return LESSEQUALS; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 84 "icalsslexer.l" +{ return GREATEREQUALS; } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 85 "icalsslexer.l" +{ return AND; } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 86 "icalsslexer.l" +{ return OR; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 87 "icalsslexer.l" +{ return QUOTE; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 88 "icalsslexer.l" +; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 89 "icalsslexer.l" +{ return EOL; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 90 "icalsslexer.l" +{ + int c = input(); + unput(c); + if(c!='\''){ + sslval.v_string= icalmemory_tmp_copy(sstext); + return STRING; + } else { + /*ssmore();*/ + } +} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 101 "icalsslexer.l" +{ sslval.v_string= icalmemory_tmp_copy(sstext); + return STRING; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 105 "icalsslexer.l" +{ return yytext[0]; } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 107 "icalsslexer.l" +ECHO; + YY_BREAK +#line 811 "icalsslexer.c" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(sql): +case YY_STATE_EOF(string_value): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 47 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 47 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 46); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + +#ifdef _QTWIN_ + b->yy_is_interactive = file ? (_isatty( fileno(file) ) > 0) : 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif + +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 107 "icalsslexer.l" + + +int sswrap() +{ + return 1; +} + diff --git a/libical/src/libicalss/icalsslexer.l b/libical/src/libicalss/icalsslexer.l new file mode 100644 index 0000000..58aa162 --- a/dev/null +++ b/libical/src/libicalss/icalsslexer.l @@ -0,0 +1,113 @@ +%{ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalsslexer.l + CREATOR: eric 8 Aug 2000 + + DESCRIPTION: + + $Id$ + $Locker$ + +(C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + ======================================================================*/ + +#include "icalssyacc.h" +#include "icalgaugeimpl.h" +#include "assert.h" + +#include <string.h> /* For strdup() */ + +int icalparser_flex_input(char* buf, int max_size); +void icalparser_clear_flex_input(); + +#undef YY_INPUT +#define YY_INPUT(b,r,ms) ( r= icalparser_flex_input(b,ms)) + +#undef SS_FATAL_ERROR +#define SS_FATAL_ERROR(msg) sserror(msg) + + +%} + +crlf \x0D?\x0A +space [ ] +qsafechar [^\x00-\x1F\"] +safechar [^\x00-\x1F\"\:\;\,] +tsafechar [\x20-\x21\x23-\x2B\x2D-\x39\x3C-\x5B\x5D-\x7E] +valuechar [^\x00-\x08\x10-\x1F] +xname X-[a-zA-Z0-9\-]+ +xname2 [a-zA-Z0-9\-\ ] +paramtext {safechar}+ +value {valuechar}+ +quotedstring \"{qsafechar}+\" +digit [0-9] + +%array /* Make yytext an array. Slow, but handy. HACK */ + +%option caseless + +%s sql string_value + + + +%% + +%{ +%} + + +SELECT { return SELECT; } +FROM { return FROM; } +WHERE { return WHERE; } +, { return COMMA; } +"=" { return EQUALS; } +"!=" { return NOTEQUALS; } +"<" { return LESS; } +">" { return GREATER; } +"<=" { return LESSEQUALS; } +">=" { return GREATEREQUALS; } +AND { return AND; } +OR { return OR; } +\' { return QUOTE; } +[ \t\n\r]+ ; +; { return EOL; } +\'[\*A-Za-z0-9\-\.]+\' { + int c = input(); + unput(c); + if(c!='\''){ + sslval.v_string= icalmemory_tmp_copy(sstext); + return STRING; + } else { + /*ssmore();*/ + } +} + +[\*A-Za-z0-9\-\.]+ { sslval.v_string= icalmemory_tmp_copy(sstext); + return STRING; } + + +. { return yytext[0]; } + +%% + +int sswrap() +{ + return 1; +} + diff --git a/libical/src/libicalss/icalssyacc.c b/libical/src/libicalss/icalssyacc.c new file mode 100644 index 0000000..943123e --- a/dev/null +++ b/libical/src/libicalss/icalssyacc.c @@ -0,0 +1,1381 @@ +/* A Bison parser, made from icalssyacc.y + by GNU bison 1.35. */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define yyparse ssparse +#define yylex sslex +#define yyerror sserror +#define yylval sslval +#define yychar sschar +#define yydebug ssdebug +#define yynerrs ssnerrs +# define STRING 257 +# define SELECT 258 +# define FROM 259 +# define WHERE 260 +# define COMMA 261 +# define QUOTE 262 +# define EQUALS 263 +# define NOTEQUALS 264 +# define LESS 265 +# define GREATER 266 +# define LESSEQUALS 267 +# define GREATEREQUALS 268 +# define AND 269 +# define OR 270 +# define EOL 271 +# define END 272 + +#line 1 "icalssyacc.y" + +/* -*- Mode: C -*- + ====================================================================== + FILE: icalssyacc.y + CREATOR: eric 08 Aug 2000 + + DESCRIPTION: + + $Id$ + $Locker$ + +(C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + ======================================================================*/ + +#include <stdlib.h> +#include <string.h> /* for strdup() */ +#include <limits.h> /* for SHRT_MAX*/ +#include "ical.h" +#include "pvl.h" +#include "icalgauge.h" +#include "icalgaugeimpl.h" + + +extern struct icalgauge_impl *icalss_yy_gauge; + +void ssyacc_add_where(struct icalgauge_impl* impl, char* prop, + icalgaugecompare compare , char* value); +void ssyacc_add_select(struct icalgauge_impl* impl, char* str1); +void ssyacc_add_from(struct icalgauge_impl* impl, char* str1); +void set_logic(struct icalgauge_impl* impl,icalgaugelogic l); +void sserror(char *s); /* Don't know why I need this.... */ + + + + +#line 52 "icalssyacc.y" +#ifndef YYSTYPE +typedef union { + char* v_string; +} yystype; +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + + + +#define YYFINAL 34 +#define YYFLAG -32768 +#define YYNTBASE 19 + +/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ +#define YYTRANSLATE(x) ((unsigned)(x) <= 272 ? yytranslate[x] : 24) + +/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ +static const char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18 +}; + +#if YYDEBUG +static const short yyprhs[] = +{ + 0, 0, 7, 9, 11, 15, 17, 21, 22, 26, + 30, 34, 38, 42, 46, 48, 52 +}; +static const short yyrhs[] = +{ + 4, 20, 5, 21, 6, 23, 0, 1, 0, 3, + 0, 20, 7, 3, 0, 3, 0, 21, 7, 3, + 0, 0, 3, 9, 3, 0, 3, 10, 3, 0, + 3, 11, 3, 0, 3, 12, 3, 0, 3, 13, + 3, 0, 3, 14, 3, 0, 22, 0, 23, 15, + 22, 0, 23, 16, 22, 0 +}; + +#endif + +#if YYDEBUG +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const short yyrline[] = +{ + 0, 63, 64, 70, 72, 76, 78, 81, 83, 85, + 86, 87, 88, 89, 92, 94, 95 +}; +#endif + + +#if (YYDEBUG) || defined YYERROR_VERBOSE + +/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ +static const char *const yytname[] = +{ + "$", "error", "$undefined.", "STRING", "SELECT", "FROM", "WHERE", "COMMA", + "QUOTE", "EQUALS", "NOTEQUALS", "LESS", "GREATER", "LESSEQUALS", + "GREATEREQUALS", "AND", "OR", "EOL", "END", "query_min", "select_list", + "from_list", "where_clause", "where_list", 0 +}; +#endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const short yyr1[] = +{ + 0, 19, 19, 20, 20, 21, 21, 22, 22, 22, + 22, 22, 22, 22, 23, 23, 23 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const short yyr2[] = +{ + 0, 6, 1, 1, 3, 1, 3, 0, 3, 3, + 3, 3, 3, 3, 1, 3, 3 +}; + +/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE + doesn't specify something else to do. Zero means the default is an + error. */ +static const short yydefact[] = +{ + 0, 2, 0, 3, 0, 0, 0, 5, 0, 4, + 7, 0, 0, 14, 1, 6, 0, 0, 0, 0, + 0, 0, 7, 7, 8, 9, 10, 11, 12, 13, + 15, 16, 0, 0, 0 +}; + +static const short yydefgoto[] = +{ + 32, 4, 8, 13, 14 +}; + +static const short yypact[] = +{ + 5,-32768, 4,-32768, 3, 8, 15,-32768, 6,-32768, + 16, 17, -9,-32768, -1,-32768, 18, 19, 20, 21, + 22, 23, 16, 16,-32768,-32768,-32768,-32768,-32768,-32768, + -32768,-32768, 27, 28,-32768 +}; + +static const short yypgoto[] = +{ + -32768,-32768,-32768, -6,-32768 +}; + + +#define YYLAST 28 + + +static const short yytable[] = +{ + 16, 17, 18, 19, 20, 21, 1, 3, 5, 2, + 6, 7, 10, 11, 22, 23, 30, 31, 9, 12, + 15, 24, 25, 26, 27, 28, 29, 33, 34 +}; + +static const short yycheck[] = +{ + 9, 10, 11, 12, 13, 14, 1, 3, 5, 4, + 7, 3, 6, 7, 15, 16, 22, 23, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 0, 0 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/bison/bison.simple" + +/* Skeleton output parser for bison, + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software + Foundation, Inc. + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser when + the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; +# if YYLSP_NEEDED + YYLTYPE yyls; +# endif +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# if YYLSP_NEEDED +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAX) +# else +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAX) +# endif + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up"); \ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). + + When YYLLOC_DEFAULT is run, CURRENT is set the location of the + first token. By default, to implement support for ranges, extend + its range to the last symbol. */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#if YYPURE +# if YYLSP_NEEDED +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval, &yylloc) +# endif +# else /* !YYLSP_NEEDED */ +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval) +# endif +# endif /* !YYLSP_NEEDED */ +#else /* !YYPURE */ +# define YYLEX yylex () +#endif /* !YYPURE */ + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + +#ifdef YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif +#endif + +#line 315 "/usr/share/bison/bison.simple" + + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +# define YYPARSE_PARAM_DECL +# else +# define YYPARSE_PARAM_ARG YYPARSE_PARAM +# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +# endif +#else /* !YYPARSE_PARAM */ +# define YYPARSE_PARAM_ARG +# define YYPARSE_PARAM_DECL +#endif /* !YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +# ifdef YYPARSE_PARAM +int yyparse (void *); +# else +int yyparse (void); +# endif +#endif + +/* YY_DECL_VARIABLES -- depending whether we use a pure parser, + variables are global, or local to YYPARSE. */ + +#define YY_DECL_NON_LSP_VARIABLES \ +/* The lookahead symbol. */ \ +int yychar; \ + \ +/* The semantic value of the lookahead symbol. */ \ +YYSTYPE yylval; \ + \ +/* Number of parse errors so far. */ \ +int yynerrs; + +#if YYLSP_NEEDED +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES \ + \ +/* Location data for the lookahead symbol. */ \ +YYLTYPE yylloc; +#else +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES +#endif + + +/* If nonreentrant, generate the variables here. */ + +#if !YYPURE +YY_DECL_VARIABLES +#endif /* !YYPURE */ + +int +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + /* If reentrant, generate the variables here. */ +#if YYPURE + YY_DECL_VARIABLES +#endif /* !YYPURE */ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yychar1 = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + +#if YYLSP_NEEDED + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; +#endif + +#if YYLSP_NEEDED +# define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +# define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + YYSIZE_T yystacksize = YYINITDEPTH; + + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; +#if YYLSP_NEEDED + YYLTYPE yyloc; +#endif + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; +#if YYLSP_NEEDED + yylsp = yyls; +#endif + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. */ +# if YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + yyls = yyls1; +# else + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); +# endif + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + goto yyoverflowlab; + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); +# if YYLSP_NEEDED + YYSTACK_RELOCATE (yyls); +# endif +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; +#if YYLSP_NEEDED + yylsp = yyls + yysize - 1; +#endif + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yychar1 = YYTRANSLATE (yychar); + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables + which are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + YYFPRINTF (stderr, "Next token is %d (%s", + yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise + meaning of a token, for further debugging info. */ +# ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +# endif + YYFPRINTF (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %d (%s), ", + yychar, yytname[yychar1])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to the semantic value of + the lookahead token. This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + +#if YYLSP_NEEDED + /* Similarly for the default location. Let the user run additional + commands if for instance locations are ranges. */ + yyloc = yylsp[1-yylen]; + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); +#endif + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables which + are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + int yyi; + + YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + switch (yyn) { + +case 2: +#line 64 "icalssyacc.y" +{ + icalparser_clear_flex_input(); + yyclearin; + } + break; +case 3: +#line 71 "icalssyacc.y" +{ssyacc_add_select(icalss_yy_gauge,yyvsp[0].v_string);} + break; +case 4: +#line 72 "icalssyacc.y" +{ssyacc_add_select(icalss_yy_gauge,yyvsp[0].v_string);} + break; +case 5: +#line 77 "icalssyacc.y" +{ssyacc_add_from(icalss_yy_gauge,yyvsp[0].v_string);} + break; +case 6: +#line 78 "icalssyacc.y" +{ssyacc_add_from(icalss_yy_gauge,yyvsp[0].v_string);} + break; +case 8: +#line 83 "icalssyacc.y" +{ssyacc_add_where(icalss_yy_gauge,yyvsp[-2].v_string,ICALGAUGECOMPARE_EQUAL,yyvsp[0].v_string); } + break; +case 9: +#line 85 "icalssyacc.y" +{ssyacc_add_where(icalss_yy_gauge,yyvsp[-2].v_string,ICALGAUGECOMPARE_NOTEQUAL,yyvsp[0].v_string); } + break; +case 10: +#line 86 "icalssyacc.y" +{ssyacc_add_where(icalss_yy_gauge,yyvsp[-2].v_string,ICALGAUGECOMPARE_LESS,yyvsp[0].v_string); } + break; +case 11: +#line 87 "icalssyacc.y" +{ssyacc_add_where(icalss_yy_gauge,yyvsp[-2].v_string,ICALGAUGECOMPARE_GREATER,yyvsp[0].v_string); } + break; +case 12: +#line 88 "icalssyacc.y" +{ssyacc_add_where(icalss_yy_gauge,yyvsp[-2].v_string,ICALGAUGECOMPARE_LESSEQUAL,yyvsp[0].v_string); } + break; +case 13: +#line 89 "icalssyacc.y" +{ssyacc_add_where(icalss_yy_gauge,yyvsp[-2].v_string,ICALGAUGECOMPARE_GREATEREQUAL,yyvsp[0].v_string); } + break; +case 14: +#line 93 "icalssyacc.y" +{set_logic(icalss_yy_gauge,ICALGAUGELOGIC_NONE);} + break; +case 15: +#line 94 "icalssyacc.y" +{set_logic(icalss_yy_gauge,ICALGAUGELOGIC_AND);} + break; +case 16: +#line 95 "icalssyacc.y" +{set_logic(icalss_yy_gauge,ICALGAUGELOGIC_OR);} + break; +} + +#line 705 "/usr/share/bison/bison.simple" + + + yyvsp -= yylen; + yyssp -= yylen; +#if YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; +#if YYLSP_NEEDED + *++yylsp = yyloc; +#endif + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* defined (YYERROR_VERBOSE) */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*--------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action | +`--------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + + +/*-------------------------------------------------------------------. +| yyerrdefault -- current state does not do anything special for the | +| error token. | +`-------------------------------------------------------------------*/ +yyerrdefault: +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + + /* If its default is to accept any token, ok. Otherwise pop it. */ + yyn = yydefact[yystate]; + if (yyn) + goto yydefault; +#endif + + +/*---------------------------------------------------------------. +| yyerrpop -- pop the current state because it cannot handle the | +| error token | +`---------------------------------------------------------------*/ +yyerrpop: + if (yyssp == yyss) + YYABORT; + yyvsp--; + yystate = *--yyssp; +#if YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + +/*--------------. +| yyerrhandle. | +`--------------*/ +yyerrhandle: + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +/*---------------------------------------------. +| yyoverflowab -- parser overflow comes here. | +`---------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} +#line 99 "icalssyacc.y" + + +void ssyacc_add_where(struct icalgauge_impl* impl, char* str1, + icalgaugecompare compare , char* value_str) +{ + + struct icalgauge_where *where; + char *compstr, *propstr, *c, *s,*l; + + if ( (where = malloc(sizeof(struct icalgauge_where))) ==0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return; + } + + memset(where,0,sizeof(struct icalgauge_where)); + where->logic = ICALGAUGELOGIC_NONE; + where->compare = ICALGAUGECOMPARE_NONE; + where->comp = ICAL_NO_COMPONENT; + where->prop = ICAL_NO_PROPERTY; + + /* remove enclosing quotes */ + s = value_str; + if(*s == '\''){ + s++; + } + l = s+strlen(s)-1; + if(*l == '\''){ + *l=0; + } + + where->value = strdup(s); + + /* Is there a period in str1 ? If so, the string specified both a + component and a property*/ + if( (c = strrchr(str1,'.')) != 0){ + compstr = str1; + propstr = c+1; + *c = '\0'; + } else { + compstr = 0; + propstr = str1; + } + + + /* Handle the case where a component was specified */ + if(compstr != 0){ + where->comp = icalenum_string_to_component_kind(compstr); + } else { + where->comp = ICAL_NO_COMPONENT; + } + + where->prop = icalenum_string_to_property_kind(propstr); + + where->compare = compare; + + if(where->value == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + free(where->value); + return; + } + + pvl_push(impl->where,where); +} + +void set_logic(struct icalgauge_impl* impl,icalgaugelogic l) +{ + pvl_elem e = pvl_tail(impl->where); + struct icalgauge_where *where = pvl_data(e); + + where->logic = l; + +} + + + +void ssyacc_add_select(struct icalgauge_impl* impl, char* str1) +{ + char *c, *compstr, *propstr; + struct icalgauge_where *where; + + /* Uses only the prop and comp fields of the where structure */ + if ( (where = malloc(sizeof(struct icalgauge_where))) ==0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return; + } + + memset(where,0,sizeof(struct icalgauge_where)); + where->logic = ICALGAUGELOGIC_NONE; + where->compare = ICALGAUGECOMPARE_NONE; + where->comp = ICAL_NO_COMPONENT; + where->prop = ICAL_NO_PROPERTY; + + /* Is there a period in str1 ? If so, the string specified both a + component and a property*/ + if( (c = strrchr(str1,'.')) != 0){ + compstr = str1; + propstr = c+1; + *c = '\0'; + } else { + compstr = 0; + propstr = str1; + } + + + /* Handle the case where a component was specified */ + if(compstr != 0){ + where->comp = icalenum_string_to_component_kind(compstr); + } else { + where->comp = ICAL_NO_COMPONENT; + } + + + /* If the property was '*', then accept all properties */ + if(strcmp("*",propstr) == 0) { + where->prop = ICAL_ANY_PROPERTY; + } else { + where->prop = icalenum_string_to_property_kind(propstr); + } + + + if(where->prop == ICAL_NO_PROPERTY){ + icalgauge_free(where); + icalerror_set_errno(ICAL_BADARG_ERROR); + return; + } + + pvl_push(impl->select,where); +} + +void ssyacc_add_from(struct icalgauge_impl* impl, char* str1) +{ + icalcomponent_kind ckind; + + ckind = icalenum_string_to_component_kind(str1); + + if(ckind == ICAL_NO_COMPONENT){ + assert(0); + } + + pvl_push(impl->from,(void*)ckind); + +} + + +void sserror(char *s){ + fprintf(stderr,"Parse error \'%s\'\n", s); +} diff --git a/libical/src/libicalss/icalssyacc.h b/libical/src/libicalss/icalssyacc.h new file mode 100644 index 0000000..7d42f3c --- a/dev/null +++ b/libical/src/libicalss/icalssyacc.h @@ -0,0 +1,31 @@ +#ifndef BISON_ICALSSYACC_H +# define BISON_ICALSSYACC_H + +#ifndef YYSTYPE +typedef union { + char* v_string; +} yystype; +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif +# define STRING 257 +# define SELECT 258 +# define FROM 259 +# define WHERE 260 +# define COMMA 261 +# define QUOTE 262 +# define EQUALS 263 +# define NOTEQUALS 264 +# define LESS 265 +# define GREATER 266 +# define LESSEQUALS 267 +# define GREATEREQUALS 268 +# define AND 269 +# define OR 270 +# define EOL 271 +# define END 272 + + +extern YYSTYPE sslval; + +#endif /* not BISON_ICALSSYACC_H */ diff --git a/libical/src/libicalss/icalssyacc.y b/libical/src/libicalss/icalssyacc.y new file mode 100644 index 0000000..6482b58 --- a/dev/null +++ b/libical/src/libicalss/icalssyacc.y @@ -0,0 +1,245 @@ +%{ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalssyacc.y + CREATOR: eric 08 Aug 2000 + + DESCRIPTION: + + $Id$ + $Locker$ + +(C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + ======================================================================*/ + +#include <stdlib.h> +#include <string.h> /* for strdup() */ +#include <limits.h> /* for SHRT_MAX*/ +#include "ical.h" +#include "pvl.h" +#include "icalgauge.h" +#include "icalgaugeimpl.h" + + +extern struct icalgauge_impl *icalss_yy_gauge; + +void ssyacc_add_where(struct icalgauge_impl* impl, char* prop, + icalgaugecompare compare , char* value); +void ssyacc_add_select(struct icalgauge_impl* impl, char* str1); +void ssyacc_add_from(struct icalgauge_impl* impl, char* str1); +void set_logic(struct icalgauge_impl* impl,icalgaugelogic l); +void sserror(char *s); /* Don't know why I need this.... */ + + + +%} + +%union { + char* v_string; +} + + +%token <v_string> STRING +%token SELECT FROM WHERE COMMA QUOTE EQUALS NOTEQUALS LESS GREATER LESSEQUALS +%token GREATEREQUALS AND OR EOL END + +%% + +query_min: SELECT select_list FROM from_list WHERE where_list + | error { + icalparser_clear_flex_input(); + yyclearin; + } + ; + +select_list: + STRING {ssyacc_add_select(icalss_yy_gauge,$1);} + | select_list COMMA STRING {ssyacc_add_select(icalss_yy_gauge,$3);} + ; + + +from_list: + STRING {ssyacc_add_from(icalss_yy_gauge,$1);} + | from_list COMMA STRING {ssyacc_add_from(icalss_yy_gauge,$3);} + ; + +where_clause: + /* Empty */ + | STRING EQUALS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_EQUAL,$3); } + + | STRING NOTEQUALS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_NOTEQUAL,$3); } + | STRING LESS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_LESS,$3); } + | STRING GREATER STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_GREATER,$3); } + | STRING LESSEQUALS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_LESSEQUAL,$3); } + | STRING GREATEREQUALS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_GREATEREQUAL,$3); } + ; + +where_list: + where_clause {set_logic(icalss_yy_gauge,ICALGAUGELOGIC_NONE);} + | where_list AND where_clause {set_logic(icalss_yy_gauge,ICALGAUGELOGIC_AND);} + | where_list OR where_clause {set_logic(icalss_yy_gauge,ICALGAUGELOGIC_OR);} + ; + + +%% + +void ssyacc_add_where(struct icalgauge_impl* impl, char* str1, + icalgaugecompare compare , char* value_str) +{ + + struct icalgauge_where *where; + char *compstr, *propstr, *c, *s,*l; + + if ( (where = malloc(sizeof(struct icalgauge_where))) ==0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return; + } + + memset(where,0,sizeof(struct icalgauge_where)); + where->logic = ICALGAUGELOGIC_NONE; + where->compare = ICALGAUGECOMPARE_NONE; + where->comp = ICAL_NO_COMPONENT; + where->prop = ICAL_NO_PROPERTY; + + /* remove enclosing quotes */ + s = value_str; + if(*s == '\''){ + s++; + } + l = s+strlen(s)-1; + if(*l == '\''){ + *l=0; + } + + where->value = strdup(s); + + /* Is there a period in str1 ? If so, the string specified both a + component and a property*/ + if( (c = strrchr(str1,'.')) != 0){ + compstr = str1; + propstr = c+1; + *c = '\0'; + } else { + compstr = 0; + propstr = str1; + } + + + /* Handle the case where a component was specified */ + if(compstr != 0){ + where->comp = icalenum_string_to_component_kind(compstr); + } else { + where->comp = ICAL_NO_COMPONENT; + } + + where->prop = icalenum_string_to_property_kind(propstr); + + where->compare = compare; + + if(where->value == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + free(where->value); + return; + } + + pvl_push(impl->where,where); +} + +void set_logic(struct icalgauge_impl* impl,icalgaugelogic l) +{ + pvl_elem e = pvl_tail(impl->where); + struct icalgauge_where *where = pvl_data(e); + + where->logic = l; + +} + + + +void ssyacc_add_select(struct icalgauge_impl* impl, char* str1) +{ + char *c, *compstr, *propstr; + struct icalgauge_where *where; + + /* Uses only the prop and comp fields of the where structure */ + if ( (where = malloc(sizeof(struct icalgauge_where))) ==0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return; + } + + memset(where,0,sizeof(struct icalgauge_where)); + where->logic = ICALGAUGELOGIC_NONE; + where->compare = ICALGAUGECOMPARE_NONE; + where->comp = ICAL_NO_COMPONENT; + where->prop = ICAL_NO_PROPERTY; + + /* Is there a period in str1 ? If so, the string specified both a + component and a property*/ + if( (c = strrchr(str1,'.')) != 0){ + compstr = str1; + propstr = c+1; + *c = '\0'; + } else { + compstr = 0; + propstr = str1; + } + + + /* Handle the case where a component was specified */ + if(compstr != 0){ + where->comp = icalenum_string_to_component_kind(compstr); + } else { + where->comp = ICAL_NO_COMPONENT; + } + + + /* If the property was '*', then accept all properties */ + if(strcmp("*",propstr) == 0) { + where->prop = ICAL_ANY_PROPERTY; + } else { + where->prop = icalenum_string_to_property_kind(propstr); + } + + + if(where->prop == ICAL_NO_PROPERTY){ + icalgauge_free(where); + icalerror_set_errno(ICAL_BADARG_ERROR); + return; + } + + pvl_push(impl->select,where); +} + +void ssyacc_add_from(struct icalgauge_impl* impl, char* str1) +{ + icalcomponent_kind ckind; + + ckind = icalenum_string_to_component_kind(str1); + + if(ckind == ICAL_NO_COMPONENT){ + assert(0); + } + + pvl_push(impl->from,(void*)ckind); + +} + + +void sserror(char *s){ + fprintf(stderr,"Parse error \'%s\'\n", s); +} diff --git a/libical/src/libicalss/libicalss.pro b/libical/src/libicalss/libicalss.pro new file mode 100644 index 0000000..a5cc80c --- a/dev/null +++ b/libical/src/libicalss/libicalss.pro @@ -0,0 +1,43 @@ +include(../../../variables.pri) + +TEMPLATE = lib + +TARGET = icalss +DESTDIR = ../../lib +CONFIG += staticlib +win32: DEFINES += _WIN32 _QTWIN_ +HEADERS = icalcalendar.h \ + icalclassify.h \ + icalcstp.h \ + icalcstpclient.h \ + icalcstpserver.h \ + icaldirset.h \ + icaldirsetimpl.h \ + icalfileset.h \ + icalfilesetimpl.h \ + icalgauge.h \ + icalgaugeimpl.h \ + icalmessage.h \ + icalset.h \ + icalspanlist.h \ + icalssyacc.h \ + config.h + +SOURCES = icalclassify.c \ + icalcstp.c \ + icalcstpclient.c \ + icalcstpserver.c \ + icaldirset.c \ + icalfileset.c \ + icalgauge.c \ + icalmessage.c \ + icalset.c \ + icalspanlist.c \ + icalsslexer.c \ + icalssyacc.c + +INTERFACES = + +INCLUDEPATH += ../libical + +DEFINES += HAVE_CONFIG_H diff --git a/libical/src/libicalss/libicalssE.pro b/libical/src/libicalss/libicalssE.pro new file mode 100644 index 0000000..57d60bd --- a/dev/null +++ b/libical/src/libicalss/libicalssE.pro @@ -0,0 +1,45 @@ +TEMPLATE = lib +CONFIG += warn_on staticlib +INCLUDEPATH += ../libical +INCLUDEPATH += . +DEFINES += HAVE_CONFIG_H +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR=../../lib/$(PLATFORM) +TARGET = icalss + +INTERFACES = \ + +HEADERS = \ + config.h \ + icalcalendar.h \ + icalclassify.h \ + icalcstp.h \ + icalcstpclient.h \ + icalcstpserver.h \ + icaldirset.h \ + icaldirsetimpl.h \ + icalfileset.h \ + icalfilesetimpl.h \ + icalgauge.h \ + icalgaugeimpl.h \ + icalmessage.h \ + icalset.h \ + icalspanlist.h \ + icalss.h \ + icalssyacc.h \ + +SOURCES = \ + icalclassify.c \ + icalcstp.c \ + icalcstpclient.c \ + icalcstpserver.c \ + icaldirset.c \ + icalfileset.c \ + icalgauge.c \ + icalmessage.c \ + icalset.c \ + icalspanlist.c \ + icalsslexer.c \ + icalssyacc.c \ + diff --git a/libical/src/src.pro b/libical/src/src.pro new file mode 100644 index 0000000..de8f0c4 --- a/dev/null +++ b/libical/src/src.pro @@ -0,0 +1,4 @@ + + +TEMPLATE = subdirs +SUBDIRS = libical libicalss diff --git a/libkabcwrap/README b/libkabcwrap/README new file mode 100644 index 0000000..366d58c --- a/dev/null +++ b/libkabcwrap/README @@ -0,0 +1,30 @@ +KAddressbook-Wrapper für Opie/Qtopia + +Bietet eine transparente Möglichkeit, auf die bekannten +Klassen StdAddressBook und AddresseeDialog zuzugreifen, +während im Hintergrund entsprechende Plugins durch Ansprechen +der Qtopia- bzw. Opie-PIM-API die Adressedaten aufbereiten +und laden. + +Einbinden in KO/Pi: + +In korganizerE.pro: + +- Die Definition KORG_NOKABC entfernen. +- In die INCLUDEPATH den Pfad zum Quellverzeichnis des Wrapper eintragen. +- -lkabc zu den LIBS hinzufügen + +In den Quelldateien incomingdialog.cpp, koeventviewer.cpp und publishdialog.cpp: +- Alle Aufrufe von addressList.size() durch addressList.count() ersetzen. + Beispielsweise durch + perl -i -p -e 's/addressList\.size/addressList.count/g' + +Der Pluginlader erwartet bislang zwei Plugins +libopiekabc.so und libqtopiakabc.so +im Verzeichnis /opt/Qtopia/plugins/korganizer. +Erst wird versucht, libopiekabc.so, dann libqtopiakabc.so zu laden. + +TODOs: +- Fixen Pfad "/opt/Qtopia" rausnehmen. +- AddresseeDialog::getAddressees wird momentan durch <plugin>::getAddressee + ersetzt, weshalb nur ein Adressat auswählbar ist. diff --git a/libkabcwrap/addresseedialog.cpp b/libkabcwrap/addresseedialog.cpp new file mode 100644 index 0000000..e0fe354 --- a/dev/null +++ b/libkabcwrap/addresseedialog.cpp @@ -0,0 +1,69 @@ +#include <qlistview.h> +#include <qmessagebox.h> +#include <qapplication.h> +#include "addresseedialog.h" +#include "select_addressee_base.h" + +using namespace KABC; + +Addressee AddresseeDialog::getAddressee( QWidget *parent ) { + + Addressee result; + if (!getInterface()) { + QMessageBox::warning(parent,"Plugin missing", "Plugins for Qtopia/Opie\naddressbook missing.\nPlease install\nlibqtopiakabc.so/libopiekabc.so\nunder $QPEDIR/plugins/korganizer.\nQtopia-plugin needs libqpepim.", 0L ); + } else { + + // qDebug("Start: AddresseeDialog::getAddressee"); + + Addressee::List list = getAddresseesFromPlugin(); + + SelectAddressee *selAddressee = new SelectAddressee(parent,"SelectAddressee", true); + QListView *contactList = selAddressee->contactList; + contactList->setSelectionMode(QListView::Single); + if (!contactList) { + Addressee emptyAddressee; + return emptyAddressee; + } + + for (uint i=0; i < list.count(); i++) { + Addressee a = list[i]; + QString fullName = a.formattedName(); + QString defaultEmail = a.preferredEmail(); + //qDebug("Adding " + fullName); + QListViewItem *item = new QListViewItem(contactList, fullName, defaultEmail); + } + if ( QApplication::desktop()->width() < 480 ) { + selAddressee->setMinimumWidth( 220 ); + } else { + selAddressee->setMinimumWidth( 440 ); + } + if (selAddressee->exec()) { + QListViewItem *selectedItem = contactList->selectedItem(); + if (selectedItem) { + uint i=0; + for (i=0; i < list.count() && (list[i].formattedName() != selectedItem->text(0)); i++); + if (i<list.count()) { + result = list[i]; + } + } + } + delete selAddressee; + //qDebug("End: AddresseeDialog::getAddressee"); +} + return result; + +} + +Addressee::List AddresseeDialog::getAddressees( QWidget *parent ) { + //qDebug("Start: AddresseeDialog::getAddressees"); + + KOAddressBookInterface *iface = getInterface(); + + Addressee::List results; + if (iface) { + Addressee a = getAddressee(parent); + results.append(a); + } + //qDebug("End: AddresseeDialog::getAddressees"); + return results; +} diff --git a/libkabcwrap/addresseedialog.h b/libkabcwrap/addresseedialog.h new file mode 100644 index 0000000..400214e --- a/dev/null +++ b/libkabcwrap/addresseedialog.h @@ -0,0 +1,17 @@ +#ifndef ADDRESSEE_DIALOG +#define ADDRESSEE_DIALOG + +#include "addressee.h" +#include "koaddressbookpluginloader.h" + +namespace KABC { + +class AddresseeDialog : public KOAddressBookPluginLoader { + + public: + static Addressee getAddressee( QWidget *parent ); + static Addressee::List getAddressees( QWidget *parent ); + +}; +} +#endif diff --git a/libkabcwrap/kabcaddressbookplugin.cpp b/libkabcwrap/kabcaddressbookplugin.cpp new file mode 100644 index 0000000..25f51d3 --- a/dev/null +++ b/libkabcwrap/kabcaddressbookplugin.cpp @@ -0,0 +1,84 @@ +/*US +#include <qwidget.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <opie/ocontact.h> +#include <opie/orecordlist.h> +#include "opieaddressee.h" +*/ +#include <stdio.h> +#include "kabcaddressbookplugin.h" + +KABCAddressBookPlugin::KABCAddressBookPlugin() : ref(0) { + +//US access = new OContactAccess("OpieAddressBookPlugin"); + +} + +KABC::Addressee::List KABCAddressBookPlugin::getAddressees() { + KABC::Addressee::List results; + + +/*US + OContactAccess access("OpieAddressBookPlugin"); + OContactAccess::List::Iterator it; + ORecordList<OContact> accessList = access.sorted(true,0,0,0); + for(it = accessList.begin(); it != accessList.end(); ++it ) { + OpieAddressee addressee( *it ); + results.append(addressee); + } +*/ + qDebug("KABCAddressBookPlugin::getAddressees has to be implemented"); + + return results; +} + +QString KABCAddressBookPlugin::name() { + return QString::QString("KABCAddressBookPlugin"); +} + + +KABC::Addressee::List KABCAddressBookPlugin::findByEmail(const QString &email) { + +printf("KABCAddressBookPlugin::findByEmail: email=%s\n", email.ascii()); + KABC::Addressee::List results; +/*US + + ORecordList<OContact> accessList = access->sorted(true,0,0,0); + OContactAccess::List::Iterator it; + for(it = accessList.begin(); it != accessList.end(); ++it ) { + OContact contact = *it; + QStringList emailList = contact.emailList(); + QStringList foundEmails = emailList.grep(email,false); + if (foundEmails.count() >= 1) { + OpieAddressee a(contact); + printf("Found Contact %s\n", a.formattedName().ascii()); + results.append(a); + } + } +*/ + qDebug("KABCAddressBookPlugin::findByEmail has to be implemented"); + + return results; + +} + +QRESULT KABCAddressBookPlugin::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ +printf("Start: KABCAddressBookPlugin::queryInterface\n"); + *iface = 0; + if ( uuid == IID_QUnknown ) + *iface = this; + else if ( uuid == IID_KOAddressBookInterface ) + *iface = this; + if ( *iface ) + (*iface)->addRef(); + return QS_OK; +printf("End: KABCAddressBookPlugin::queryInterface\n"); +} + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( KABCAddressBookPlugin ) +} + diff --git a/libkabcwrap/kabcaddressbookplugin.h b/libkabcwrap/kabcaddressbookplugin.h new file mode 100644 index 0000000..0f82744 --- a/dev/null +++ b/libkabcwrap/kabcaddressbookplugin.h @@ -0,0 +1,18 @@ +#include <qwidget.h> +#include <koaddressbookinterface.h> +#include <addressee.h> + +struct KABCAddressBookPlugin : public KOAddressBookInterface { + + public: + + KABCAddressBookPlugin::KABCAddressBookPlugin(); + QString name(); + KABC::Addressee::List getAddressees(); + KABC::Addressee::List findByEmail(const QString &email); + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + protected: +// OContactAccess *access; + ulong ref; +}; diff --git a/libkabcwrap/koaddressbookinterface.h b/libkabcwrap/koaddressbookinterface.h new file mode 100644 index 0000000..3889d2a --- a/dev/null +++ b/libkabcwrap/koaddressbookinterface.h @@ -0,0 +1,21 @@ +#ifndef KO_ADDRESS_BOOK_INTERFACE_H +#define KO_ADDRESS_BOOK_INTERFACE_H + +#include <qwidget.h> +#include <qpe/qcom.h> +#include "addressee.h" + +#ifndef QT_NO_COMPONENT +#ifndef IID_KOAddressBookInterface +#define IID_KOAddressBookInterface QUuid( 0x7505e192, 0x4977, 0x465a, 0xb7, 0x2f, 0x0a, 0x8d, 0xd4, 0x91, 0xcf, 0x43) +#endif +#endif + +struct KOAddressBookInterface : public QUnknownInterface { + + virtual QString name() = 0; + virtual KABC::Addressee::List getAddressees() = 0; + +}; +#endif + diff --git a/libkabcwrap/koaddressbookpluginloader.h b/libkabcwrap/koaddressbookpluginloader.h new file mode 100644 index 0000000..0182b29 --- a/dev/null +++ b/libkabcwrap/koaddressbookpluginloader.h @@ -0,0 +1,18 @@ +#ifndef KO_ADDRESS_BOOK_PLUGIN_LOADER_H +#define KO_ADDRESS_BOOK_PLUGIN_LOADER_H + +#include "addressee.h" +#include "koaddressbookinterface.h" + +class KOAddressBookPluginLoader { + + public: + static KOAddressBookInterface *getInterface(); + static KABC::Addressee::List getAddresseesFromPlugin(); + + private: + static KOAddressBookInterface *iface; + static KABC::Addressee::List addresseeList; +}; + +#endif diff --git a/libkabcwrap/koaddresspluginloader.cpp b/libkabcwrap/koaddresspluginloader.cpp new file mode 100644 index 0000000..d329262 --- a/dev/null +++ b/libkabcwrap/koaddresspluginloader.cpp @@ -0,0 +1,56 @@ +#include <stdio.h> +#include <qtopia/qlibrary.h> +#include <qpe/qpeapplication.h> +#include "koaddressbookpluginloader.h" +#include "kabcaddressbookplugin.h" + +KOAddressBookInterface *KOAddressBookPluginLoader::iface = 0; +KABC::Addressee::List KOAddressBookPluginLoader::addresseeList; + +KOAddressBookInterface *KOAddressBookPluginLoader::getInterface() { + + qDebug("Start: KOAddressBookPluginLoader::getInterface"); + + if (!iface) { + + const QString & qpeDir = QPEApplication::qpeDir(); + QLibrary *lib = new QLibrary( qpeDir + "/plugins/korganizer/libopiekabc.so", QLibrary::Immediately ); + QRESULT q = lib->queryInterface( IID_QUnknown, (QUnknownInterface**)&iface ); + if ( q != QS_OK ) { + lib = new QLibrary( qpeDir + "/plugins/korganizer/libqtopiakabc.so", QLibrary::Immediately ); + QRESULT q = lib->queryInterface( IID_QUnknown, (QUnknownInterface**)&iface ); + // we checked now for all known external interfaces. If no were found, use the default KABC interface + if ( q != QS_OK ) { + iface = new KABCAddressBookPlugin(); + } + } + } + + qDebug("End: KOAddressBookPluginLoader::getInterface"); + return iface; + +} + +KABC::Addressee::List KOAddressBookPluginLoader::getAddresseesFromPlugin() { + + qDebug("Start: KOAddressBookPluginLoader::getAddresseesFromPlugin"); + addresseeList.clear(); + if (!(addresseeList.count() > 0)) { + qDebug("KOAddressBookPluginLoader::getAddresseesFromPlugin: no addresses loaded. Loading..."); + if (!iface) { + qDebug("KOAddressBookPluginLoader::getAddresseesFromPlugin: no interface loaded. Loading..."); + iface = getInterface(); + } + if (iface) { + qDebug("KOAddressBookPluginLoader::getAddresseesFromPlugin: interface is " + iface->name()); + addresseeList = iface->getAddressees(); + } else { + qDebug("KOAddressBookPluginLoader::getAddresseesFromPlugin: No interface found!"); + } + } + + + qDebug("End: KOAddressBookPluginLoader::getAddresseesFromPlugin"); + return addresseeList; + +} diff --git a/libkabcwrap/libkabcwrapE.pro b/libkabcwrap/libkabcwrapE.pro new file mode 100644 index 0000000..c0f1fe5 --- a/dev/null +++ b/libkabcwrap/libkabcwrapE.pro @@ -0,0 +1,31 @@ +TEMPLATE = lib +CONFIG += qt warn_on release + +TARGET = microkabcwrap +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc +DESTDIR=$(QPEDIR)/lib +INCLUDEPATH += . $(QPEDIR)/include ../kabc ../microkde ../microkde/kdecore +DEFINES += +LIBS += -lmicrokabc +LIBS += -L$(QPEDIR)/lib +#US LIBS += -lqpe +#US LIBS += -lqte + +INTERFACES += select_addressee_base.ui + +HEADERS = \ + addresseedialog.h \ + koaddressbookinterface.h \ + kabcaddressbookplugin.h + +# kabc/addressee.h \ +# kabc/addressbook.h \ +# kabc/stdaddressbook.h \ + +SOURCES = \ + addresseedialog.cpp \ + koaddresspluginloader.cpp \ + kabcaddressbookplugin.cpp +# addressee.cpp \ +# stdaddressbook.cpp \ diff --git a/libkabcwrap/select_addressee_base.cpp b/libkabcwrap/select_addressee_base.cpp new file mode 100644 index 0000000..1b846e2 --- a/dev/null +++ b/libkabcwrap/select_addressee_base.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** Form implementation generated from reading ui file 'select_addressee_base.ui' +** +** Created: Fri Feb 6 04:58:15 2004 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#include "select_addressee_base.h" + +#include <qheader.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qvariant.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a SelectAddressee which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +SelectAddressee::SelectAddressee( QWidget* parent, const char* name, bool modal, WFlags fl ) + : QDialog( parent, name, modal, fl ) +{ + if ( !name ) + setName( "SelectAddressee" ); + resize( 208, 267 ); + setCaption( tr( "Select adressee" ) ); + SelectAddresseeLayout = new QVBoxLayout( this ); + SelectAddresseeLayout->setSpacing( 6 ); + SelectAddresseeLayout->setMargin( 11 ); + + contactList = new QListView( this, "contactList" ); + contactList->addColumn( tr( "Name" ) ); + contactList->addColumn( tr( "Email" ) ); + SelectAddresseeLayout->addWidget( contactList ); +} + +/* + * Destroys the object and frees any allocated resources + */ +SelectAddressee::~SelectAddressee() +{ + // no need to delete child widgets, Qt does it all for us +} + diff --git a/libkabcwrap/select_addressee_base.h b/libkabcwrap/select_addressee_base.h new file mode 100644 index 0000000..d77b44e --- a/dev/null +++ b/libkabcwrap/select_addressee_base.h @@ -0,0 +1,34 @@ +/**************************************************************************** +** Form interface generated from reading ui file 'select_addressee_base.ui' +** +** Created: Fri Feb 6 04:58:14 2004 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#ifndef SELECTADDRESSEE_H +#define SELECTADDRESSEE_H + +#include <qvariant.h> +#include <qdialog.h> +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QListView; +class QListViewItem; + +class SelectAddressee : public QDialog +{ + Q_OBJECT + +public: + SelectAddressee( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~SelectAddressee(); + + QListView* contactList; + +protected: + QVBoxLayout* SelectAddresseeLayout; +}; + +#endif // SELECTADDRESSEE_H diff --git a/libkabcwrap/select_addressee_base.ui b/libkabcwrap/select_addressee_base.ui new file mode 100644 index 0000000..d145b0d --- a/dev/null +++ b/libkabcwrap/select_addressee_base.ui @@ -0,0 +1,68 @@ +<!DOCTYPE UI><UI> +<class>SelectAddressee</class> +<widget> + <class>QDialog</class> + <property stdset="1"> + <name>name</name> + <cstring>SelectAddressee</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>208</width> + <height>267</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Select adressee</string> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>11</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QListView</class> + <column> + <property> + <name>text</name> + <string>Name</string> + </property> + <property> + <name>clickable</name> + <bool>true</bool> + </property> + <property> + <name>resizeable</name> + <bool>true</bool> + </property> + </column> + <column> + <property> + <name>text</name> + <string>Email</string> + </property> + <property> + <name>clickable</name> + <bool>true</bool> + </property> + <property> + <name>resizeable</name> + <bool>true</bool> + </property> + </column> + <property stdset="1"> + <name>name</name> + <cstring>contactList</cstring> + </property> + </widget> + </vbox> +</widget> +</UI> diff --git a/libkcal/alarm.cpp b/libkcal/alarm.cpp new file mode 100644 index 0000000..07812c2 --- a/dev/null +++ b/libkcal/alarm.cpp @@ -0,0 +1,407 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> + +#include "incidence.h" +#include "todo.h" + +#include "alarm.h" + +using namespace KCal; +#include <qwidget.h> +Alarm::Alarm(Incidence *parent) + : mParent(parent), + mType(Audio), + mDescription(""), // to make operator==() not fail + mFile(""), // to make operator==() not fail + mMailSubject(""), // to make operator==() not fail + mAlarmSnoozeTime(5), + mAlarmRepeatCount(0), + mEndOffset(false), + mHasTime(false), + mAlarmEnabled(false) +{ + +} + +Alarm::~Alarm() +{ +} + +bool Alarm::operator==( const Alarm& rhs ) const +{ + if ( mType != rhs.mType || + mAlarmSnoozeTime != rhs.mAlarmSnoozeTime || + mAlarmRepeatCount != rhs.mAlarmRepeatCount || + mAlarmEnabled != rhs.mAlarmEnabled || + mHasTime != rhs.mHasTime) + return false; + + if (mHasTime) { + if (mAlarmTime != rhs.mAlarmTime) + return false; + } else { + if (mOffset != rhs.mOffset || + mEndOffset != rhs.mEndOffset) + return false; + } + + switch (mType) { + case Display: + return mDescription == rhs.mDescription; + + case Email: + return mDescription == rhs.mDescription && + mMailAttachFiles == rhs.mMailAttachFiles && + mMailAddresses == rhs.mMailAddresses && + mMailSubject == rhs.mMailSubject; + + case Procedure: + return mFile == rhs.mFile && + mDescription == rhs.mDescription; + + case Audio: + return mFile == rhs.mFile; + + case Invalid: + break; + } + return false; +} + +void Alarm::setType(Alarm::Type type) +{ + if (type == mType) + return; + + switch (type) { + case Display: + mDescription = ""; + break; + case Procedure: + mFile = mDescription = ""; + break; + case Audio: + mFile = ""; + break; + case Email: + mMailSubject = mDescription = ""; + mMailAddresses.clear(); + mMailAttachFiles.clear(); + break; + case Invalid: + break; + default: + return; + } + mType = type; + mParent->updated(); +} + +Alarm::Type Alarm::type() const +{ + return mType; +} + +void Alarm::setAudioAlarm(const QString &audioFile) +{ + mType = Audio; + mFile = audioFile; + mParent->updated(); +} + +void Alarm::setAudioFile(const QString &audioFile) +{ + if (mType == Audio) { + mFile = audioFile; + mParent->updated(); + } +} + +QString Alarm::audioFile() const +{ + return (mType == Audio) ? mFile : QString::null; +} + +void Alarm::setProcedureAlarm(const QString &programFile, const QString &arguments) +{ + mType = Procedure; + mFile = programFile; + mDescription = arguments; + mParent->updated(); +} + +void Alarm::setProgramFile(const QString &programFile) +{ + if (mType == Procedure) { + mFile = programFile; + mParent->updated(); + } +} + +QString Alarm::programFile() const +{ + return (mType == Procedure) ? mFile : QString::null; +} + +void Alarm::setProgramArguments(const QString &arguments) +{ + if (mType == Procedure) { + mDescription = arguments; + mParent->updated(); + } +} + +QString Alarm::programArguments() const +{ + return (mType == Procedure) ? mDescription : QString::null; +} + +void Alarm::setEmailAlarm(const QString &subject, const QString &text, + const QValueList<Person> &addressees, const QStringList &attachments) +{ + mType = Email; + mMailSubject = subject; + mDescription = text; + mMailAddresses = addressees; + mMailAttachFiles = attachments; + mParent->updated(); +} + +void Alarm::setMailAddress(const Person &mailAddress) +{ + if (mType == Email) { + mMailAddresses.clear(); + mMailAddresses += mailAddress; + mParent->updated(); + } +} + +void Alarm::setMailAddresses(const QValueList<Person> &mailAddresses) +{ + if (mType == Email) { + mMailAddresses = mailAddresses; + mParent->updated(); + } +} + +void Alarm::addMailAddress(const Person &mailAddress) +{ + if (mType == Email) { + mMailAddresses += mailAddress; + mParent->updated(); + } +} + +QValueList<Person> Alarm::mailAddresses() const +{ + return (mType == Email) ? mMailAddresses : QValueList<Person>(); +} + +void Alarm::setMailSubject(const QString &mailAlarmSubject) +{ + if (mType == Email) { + mMailSubject = mailAlarmSubject; + mParent->updated(); + } +} + +QString Alarm::mailSubject() const +{ + return (mType == Email) ? mMailSubject : QString::null; +} + +void Alarm::setMailAttachment(const QString &mailAttachFile) +{ + if (mType == Email) { + mMailAttachFiles.clear(); + mMailAttachFiles += mailAttachFile; + mParent->updated(); + } +} + +void Alarm::setMailAttachments(const QStringList &mailAttachFiles) +{ + if (mType == Email) { + mMailAttachFiles = mailAttachFiles; + mParent->updated(); + } +} + +void Alarm::addMailAttachment(const QString &mailAttachFile) +{ + if (mType == Email) { + mMailAttachFiles += mailAttachFile; + mParent->updated(); + } +} + +QStringList Alarm::mailAttachments() const +{ + return (mType == Email) ? mMailAttachFiles : QStringList(); +} + +void Alarm::setMailText(const QString &text) +{ + if (mType == Email) { + mDescription = text; + mParent->updated(); + } +} + +QString Alarm::mailText() const +{ + return (mType == Email) ? mDescription : QString::null; +} + +void Alarm::setDisplayAlarm(const QString &text) +{ + mType = Display; + mDescription = text; + mParent->updated(); +} + +void Alarm::setText(const QString &text) +{ + if (mType == Display) { + mDescription = text; + mParent->updated(); + } +} + +QString Alarm::text() const +{ + return (mType == Display) ? mDescription : QString::null; +} + +void Alarm::setTime(const QDateTime &alarmTime) +{ + mAlarmTime = alarmTime; + mHasTime = true; + + mParent->updated(); +} + +QDateTime Alarm::time() const +{ + if ( hasTime() ) + return mAlarmTime; + else + { + if (mParent->type()=="Todo") { + Todo *t = static_cast<Todo*>(mParent); + return mOffset.end( t->dtDue() ); + } else if (mEndOffset) { + return mOffset.end( mParent->dtEnd() ); + } else { + return mOffset.end( mParent->dtStart() ); + } + } +} + +bool Alarm::hasTime() const +{ + return mHasTime; +} + +void Alarm::setSnoozeTime(int alarmSnoozeTime) +{ + mAlarmSnoozeTime = alarmSnoozeTime; + mParent->updated(); +} + +int Alarm::snoozeTime() const +{ + return mAlarmSnoozeTime; +} + +void Alarm::setRepeatCount(int alarmRepeatCount) +{ + kdDebug(5800) << "Alarm::setRepeatCount(): " << alarmRepeatCount << endl; + + mAlarmRepeatCount = alarmRepeatCount; + mParent->updated(); +} + +int Alarm::repeatCount() const +{ + kdDebug(5800) << "Alarm::repeatCount(): " << mAlarmRepeatCount << endl; + return mAlarmRepeatCount; +} + +void Alarm::toggleAlarm() +{ + mAlarmEnabled = !mAlarmEnabled; + mParent->updated(); +} + +void Alarm::setEnabled(bool enable) +{ + mAlarmEnabled = enable; + mParent->updated(); +} + +bool Alarm::enabled() const +{ + return mAlarmEnabled; +} + +void Alarm::setStartOffset( const Duration &offset ) +{ + mOffset = offset; + mEndOffset = false; + mHasTime = false; + mParent->updated(); +} + +Duration Alarm::startOffset() const +{ + return (mHasTime || mEndOffset) ? 0 : mOffset; +} + +bool Alarm::hasStartOffset() const +{ + return !mHasTime && !mEndOffset; +} + +bool Alarm::hasEndOffset() const +{ + return !mHasTime && mEndOffset; +} + +void Alarm::setEndOffset( const Duration &offset ) +{ + mOffset = offset; + mEndOffset = true; + mHasTime = false; + mParent->updated(); +} + +Duration Alarm::endOffset() const +{ + return (mHasTime || !mEndOffset) ? 0 : mOffset; +} + +void Alarm::setParent( Incidence *parent ) +{ + mParent = parent; +} diff --git a/libkcal/alarm.h b/libkcal/alarm.h new file mode 100644 index 0000000..ae2eca3 --- a/dev/null +++ b/libkcal/alarm.h @@ -0,0 +1,245 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KCAL_ALARM_H +#define KCAL_ALARM_H + +#include <qstring.h> +#include <qvaluelist.h> + +#include "customproperties.h" +#include "duration.h" +#include "person.h" + +namespace KCal { + +class Incidence; + +/** + This class represents an alarm notification. +*/ +class Alarm : public CustomProperties +{ + public: + enum Type { Invalid, Display, Procedure, Email, Audio }; + typedef QValueList<Alarm *> List; + + /** Construct a new alarm with variables initialized to "sane" values. */ + explicit Alarm(Incidence *parent); + /** Destruct Alarm object. */ + ~Alarm(); + + /** Compare this alarm with another one. */ + bool operator==(const Alarm &) const; + bool operator!=(const Alarm &a) const { return !operator==(a); } + + /** Set the type of the alarm. + If the specified type is different from the current type of the alarm, + the alarm's type-specific properties are initialised to null. + @param type type of alarm. + */ + void setType(Type type); + /** Return the type of the alarm */ + Type type() const; + + /** Set the alarm to be a display alarm. + @param text text to display when the alarm is triggered. + */ + void setDisplayAlarm(const QString &text); + /** Set the text to be displayed when the alarm is triggered. + Ignored if the alarm is not a display alarm. + */ + void setText(const QString &text); + /** Return the text string that displays when the alarm is triggered. */ + QString text() const; + + /** Set the alarm to be an audio alarm. + @param audioFile optional file to play when the alarm is triggered. + */ + void setAudioAlarm(const QString &audioFile = QString::null); + /** Set the file to play when the audio alarm is triggered. + Ignored if the alarm is not an audio alarm. + */ + void setAudioFile(const QString &audioFile); + /** Return the name of the audio file for the alarm. + @return The audio file for the alarm, or QString::null if not an audio alarm. + */ + QString audioFile() const; + + /** Set the alarm to be a procedure alarm. + @param programFile program to execute when the alarm is triggered. + @param arguments arguments to supply to programFile. + */ + void setProcedureAlarm(const QString &programFile, const QString &arguments = QString::null); + /** Set the program file to execute when the alarm is triggered. + Ignored if the alarm is not a procedure alarm. + */ + void setProgramFile(const QString &programFile); + /** Return the name of the program file to execute when the alarm is triggered. + @return the program file name, or QString::null if not a procedure alarm. + */ + QString programFile() const; + /** Set the arguments to the program to execute when the alarm is triggered. + Ignored if the alarm is not a procedure alarm. + */ + void setProgramArguments(const QString &arguments); + /** Return the arguments to the program to run when the alarm is triggered. + @return the program arguments, or QString::null if not a procedure alarm. + */ + QString programArguments() const; + + /** Set the alarm to be an email alarm. + @param subject subject line of email. + @param text body of email. + @param addressees email addresses of recipient(s). + @param attachments optional names of files to attach to the email. + */ + void setEmailAlarm(const QString &subject, const QString &text, const QValueList<Person> &addressees, + const QStringList &attachments = QStringList()); + + /** Send mail to this address when the alarm is triggered. + Ignored if the alarm is not an email alarm. + */ + void setMailAddress(const Person &mailAlarmAddress); + /** Send mail to these addresses when the alarm is triggered. + Ignored if the alarm is not an email alarm. + */ + void setMailAddresses(const QValueList<Person> &mailAlarmAddresses); + /** Add this address to the list of addresses to send mail to when the alarm is triggered. + Ignored if the alarm is not an email alarm. + */ + void addMailAddress(const Person &mailAlarmAddress); + /** return the addresses to send mail to when an alarm goes off */ + QValueList<Person> mailAddresses() const; + + /** Set the subject line of the mail. + Ignored if the alarm is not an email alarm. + */ + void setMailSubject(const QString &mailAlarmSubject); + /** return the subject line of the mail */ + QString mailSubject() const; + + /** Attach this filename to the email. + Ignored if the alarm is not an email alarm. + */ + void setMailAttachment(const QString &mailAttachFile); + /** Attach these filenames to the email. + Ignored if the alarm is not an email alarm. + */ + void setMailAttachments(const QStringList &mailAttachFiles); + /** Add this filename to the list of files to attach to the email. + Ignored if the alarm is not an email alarm. + */ + void addMailAttachment(const QString &mailAttachFile); + /** return the filenames to attach to the email */ + QStringList mailAttachments() const; + + /** Set the email body text. + Ignored if the alarm is not an email alarm. + */ + void setMailText(const QString &text); + /** Return the email body text. + @return the body text, or QString::null if not an email alarm. + */ + QString mailText() const; + + /** set the time to trigger an alarm */ + void setTime(const QDateTime &alarmTime); + /** return the date/time when an alarm goes off */ + QDateTime time() const; + /** Return true, if the alarm has an explicit date/time. */ + bool hasTime() const; + + /** Set offset of alarm in time relative to the start of the event. */ + void setStartOffset(const Duration &); + /** Return offset of alarm in time relative to the start of the event. + * If the alarm's time is not defined in terms of an offset relative + * to the start of the event, returns zero. + */ + Duration startOffset() const; + /** Return whether the alarm is defined in terms of an offset relative + * to the start of the event. + */ + bool hasStartOffset() const; + + /** Set offset of alarm in time relative to the end of the event. */ + void setEndOffset(const Duration &); + /** Return offset of alarm in time relative to the end of the event. + * If the alarm's time is not defined in terms of an offset relative + * to the end of the event, returns zero. + */ + Duration endOffset() const; + /** Return whether the alarm is defined in terms of an offset relative + * to the end of the event. + */ + bool hasEndOffset() const; + + /** Set the interval between snoozes for the alarm. + @param snoozeTime the time in minutes between snoozes. + */ + void setSnoozeTime(int alarmSnoozeTime); + /** Get how long the alarm snooze interval is. + @return the number of minutes between snoozes. + */ + int snoozeTime() const; + + /** set how many times an alarm is to repeat itself (w/snoozes) */ + void setRepeatCount(int alarmRepeatCount); + /** get how many times an alarm repeats */ + int repeatCount() const; + + /** toggles the value of alarm to be either on or off. + set's the alarm time to be x minutes before dtStart time. */ + void toggleAlarm(); + + /** set the alarm enabled status */ + void setEnabled(bool enable); + /** get the alarm enabled status */ + bool enabled() const; + + /** Set the alarm's parent incidence */ + void setParent( Incidence * ); + /** get the alarm's parent incidence */ + Incidence *parent() const { return mParent; } + + private: + Incidence *mParent; // the incidence which this alarm belongs to + Type mType; // type of alarm + QString mDescription; // text to display/email body/procedure arguments + QString mFile; // procedure program to run/optional audio file to play + QStringList mMailAttachFiles; // filenames to attach to email + QValueList<Person> mMailAddresses; // who to mail for reminder + QString mMailSubject; // subject of email + + int mAlarmSnoozeTime; // number of minutes after alarm to + // snooze before ringing again + int mAlarmRepeatCount; // number of times for alarm to repeat + // after the initial time + + QDateTime mAlarmTime; // time at which to trigger the alarm + Duration mOffset; // time relative to incidence DTSTART to trigger the alarm + bool mEndOffset; // if true, mOffset relates to DTEND, not DTSTART + bool mHasTime; // use mAlarmTime, not mOffset + bool mAlarmEnabled; +}; + +} + +#endif diff --git a/libkcal/attachment.cpp b/libkcal/attachment.cpp new file mode 100644 index 0000000..1ead923 --- a/dev/null +++ b/libkcal/attachment.cpp @@ -0,0 +1,86 @@ +/* + This file is part of libkcal. + Copyright (c) 2002 Michael Brade <brade@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "attachment.h" + +using namespace KCal; + +Attachment::Attachment(const QString& uri, const QString& mime) +{ + mMimeType = mime; + mData = uri; + mBinary = false; +} + +Attachment::Attachment(const char *base64, const QString& mime) +{ + mMimeType = mime; + mData = QString::fromUtf8(base64); + mBinary = true; +} + +bool Attachment::isURI() const +{ + return !mBinary; +} + +QString Attachment::uri() const +{ + if (!mBinary) + return mData; + else + return QString::null; +} + +void Attachment::setURI(const QString& uri) +{ + mData = uri; + mBinary = false; +} + +bool Attachment::isBinary() const +{ + return mBinary; +} + +char *Attachment::data() const +{ + if (mBinary) + return mData.utf8().data(); + else + return 0; +} + +void Attachment::setData(const char *base64) +{ + mData = QString::fromUtf8(base64); + mBinary = true; +} + +QString Attachment::mimeType() const +{ + return mMimeType; +} + +void Attachment::setMimeType(const QString& mime) +{ + mMimeType = mime; +} + diff --git a/libkcal/attachment.h b/libkcal/attachment.h new file mode 100644 index 0000000..cdf2458 --- a/dev/null +++ b/libkcal/attachment.h @@ -0,0 +1,69 @@ +/* + This file is part of libkcal. + Copyright (c) 2002 Michael Brade <brade@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _ATTACHMENT_H +#define _ATTACHMENT_H + +#include <qstring.h> + + +namespace KCal { + +/** + * This class represents information related to an attachment. + */ +class Attachment +{ +public: + /** + * Create a Reference to some URI. + * @param uri the uri this attachment refers to + * @param mime the mime type of the resource being linked to + */ + Attachment(const QString& uri, const QString& mime = QString::null); + + /** + * Create a binary attachment. + * @param base64 the attachment in base64 format + * @param mime the mime type of the attachment + */ + Attachment(const char *base64, const QString& mime = QString::null); + + /* The VALUE parameter in Cal */ + bool isURI() const; + QString uri() const; + void setURI(const QString& uri); + + bool isBinary() const; + char *data() const; + void setData(const char *base64); + + /* The optional FMTTYPE parameter in iCal */ + QString mimeType() const; + void setMimeType(const QString& mime); +private: + QString mMimeType; + QString mData; + bool mBinary; +}; + +} + +#endif diff --git a/libkcal/attendee.cpp b/libkcal/attendee.cpp new file mode 100644 index 0000000..41c6fcd --- a/dev/null +++ b/libkcal/attendee.cpp @@ -0,0 +1,167 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qstringlist.h> + +#include <kdebug.h> +#include <klocale.h> + +#include "attendee.h" + +using namespace KCal; + +Attendee::Attendee(const QString &name, const QString &email, bool _rsvp, Attendee::PartStat s, + Attendee::Role r,const QString &u) : + Person(name,email) +{ + mFlag = TRUE; + mRSVP = _rsvp; + mStatus = s; + mRole = r; + mUid = u; +} + +Attendee::~Attendee() +{ +} + + +bool KCal::operator==( const Attendee& a1, const Attendee& a2 ) +{ + return ( operator==( (const Person&)a1, (const Person&) a2 ) && + a1.RSVP() == a2.RSVP() && + a1.role() == a2.role() && + a1.status() == a2.status() && + a1.uid() == a2.uid() ); +} + + +void Attendee::setStatus(Attendee::PartStat s) +{ + mStatus = s; +} + +Attendee::PartStat Attendee::status() const +{ + return mStatus; +} + +QString Attendee::statusStr() const +{ + return statusName(mStatus); +} + +QString Attendee::statusName( Attendee::PartStat s ) +{ + switch (s) { + default: + case NeedsAction: + return i18n("Needs Action"); + break; + case Accepted: + return i18n("Accepted"); + break; + case Declined: + return i18n("Declined"); + break; + case Tentative: + return i18n("Tentative"); + break; + case Delegated: + return i18n("Delegated"); + break; + case Completed: + return i18n("Completed"); + break; + case InProcess: + return i18n("In Process"); + break; + } +} + +QStringList Attendee::statusList() +{ + QStringList list; + list << statusName(NeedsAction); + list << statusName(Accepted); + list << statusName(Declined); + list << statusName(Tentative); + list << statusName(Delegated); + list << statusName(Completed); + list << statusName(InProcess); + + return list; +} + + +void Attendee::setRole(Attendee::Role r) +{ + mRole = r; +} + +Attendee::Role Attendee::role() const +{ + return mRole; +} + +QString Attendee::roleStr() const +{ + return roleName(mRole); +} + +void Attendee::setUid(QString uid) +{ + mUid = uid; +} + +QString Attendee::uid() const +{ + return mUid; +} + +QString Attendee::roleName( Attendee::Role r ) +{ + switch (r) { + case Chair: + return i18n("Chair"); + break; + default: + case ReqParticipant: + return i18n("Participant"); + break; + case OptParticipant: + return i18n("Optional Participant"); + break; + case NonParticipant: + return i18n("Observer"); + break; + } +} + +QStringList Attendee::roleList() +{ + QStringList list; + list << roleName(ReqParticipant); + list << roleName(OptParticipant); + list << roleName(NonParticipant); + list << roleName(Chair); + + return list; +} diff --git a/libkcal/attendee.h b/libkcal/attendee.h new file mode 100644 index 0000000..1bd2ff3 --- a/dev/null +++ b/libkcal/attendee.h @@ -0,0 +1,96 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _ATTENDEE_H +#define _ATTENDEE_H + +#include <qstring.h> + +#include "person.h" + +namespace KCal { + +/** + This class represents information related to an attendee of an event. +*/ +class Attendee : public Person +{ + public: + enum PartStat { NeedsAction, Accepted, Declined, Tentative, + Delegated, Completed, InProcess }; + enum Role { ReqParticipant, OptParticipant, NonParticipant, Chair }; + + /** + Create Attendee. + + @param name Name + @param email Email address + @param rsvp Request for reply + @param status Status (see enum for list) + @param role Role + */ + Attendee(const QString& name, const QString &email, + bool rsvp=false, PartStat status=NeedsAction, + Role role=ReqParticipant,const QString& u=QString::null); + /** Destruct Attendee */ + virtual ~Attendee(); + + /** Set role of Attendee. List of roles still has to be documented. */ + void setRole( Role ); + /** Return role of Attendee. */ + Role role() const; + /** Return role as clear text string */ + QString roleStr() const; + static QString roleName( Role ); + static QStringList roleList(); + + /** Holds the uid of the attendee, if applicable **/ + QString uid() const; + void setUid (QString); + + /** Set status. See enum for definitions of possible values */ + void setStatus(PartStat s); + /** Return status. */ + PartStat status() const; + /** Return status as human-readable string. */ + QString statusStr() const; + static QString statusName( PartStat ); + static QStringList statusList(); + + /** Set if Attendee is asked to reply. */ + void setRSVP(bool r) { mRSVP = r; } + /** Return, if Attendee is asked to reply. */ + bool RSVP() const { return mRSVP; } + + private: + bool mRSVP; + Role mRole; + PartStat mStatus; + QString mUid; + + // used to tell whether we have need to mail this person or not. + bool mFlag; +}; + + bool operator==( const Attendee& a1, const Attendee& a2 ); + +} + +#endif diff --git a/libkcal/calendar.cpp b/libkcal/calendar.cpp new file mode 100644 index 0000000..dc198bd --- a/dev/null +++ b/libkcal/calendar.cpp @@ -0,0 +1,426 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <stdlib.h> +#include <time.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> + +#include "exceptions.h" +#include "calfilter.h" + +#include "calendar.h" + +using namespace KCal; + +Calendar::Calendar() +{ + + init(); + setTimeZoneId( i18n (" 00:00 Europe/London(UTC)") ); +} + +Calendar::Calendar( const QString &timeZoneId ) +{ + + init(); + setTimeZoneId(timeZoneId); +} + +void Calendar::init() +{ + mObserver = 0; + mNewObserver = false; + + mModified = false; + + // Setup default filter, which does nothing + mDefaultFilter = new CalFilter; + mFilter = mDefaultFilter; + mFilter->setEnabled(false); + + // initialize random numbers. This is a hack, and not + // even that good of one at that. +// srandom(time(0)); + + // user information... + setOwner(i18n("Unknown Name")); + setEmail(i18n("unknown@nowhere")); + +#if 0 + tmpStr = KOPrefs::instance()->mTimeZone; +// kdDebug(5800) << "Calendar::Calendar(): TimeZone: " << tmpStr << endl; + int dstSetting = KOPrefs::instance()->mDaylightSavings; + extern long int timezone; + struct tm *now; + time_t curtime; + curtime = time(0); + now = localtime(&curtime); + int hourOff = - ((timezone / 60) / 60); + if (now->tm_isdst) + hourOff += 1; + QString tzStr; + tzStr.sprintf("%.2d%.2d", + hourOff, + abs((timezone / 60) % 60)); + + // if no time zone was in the config file, write what we just discovered. + if (tmpStr.isEmpty()) { +// KOPrefs::instance()->mTimeZone = tzStr; + } else { + tzStr = tmpStr; + } + + // if daylight savings has changed since last load time, we need + // to rewrite these settings to the config file. + if ((now->tm_isdst && !dstSetting) || + (!now->tm_isdst && dstSetting)) { + KOPrefs::instance()->mTimeZone = tzStr; + KOPrefs::instance()->mDaylightSavings = now->tm_isdst; + } + + setTimeZone(tzStr); +#endif + +// KOPrefs::instance()->writeConfig(); +} + +Calendar::~Calendar() +{ + delete mDefaultFilter; +} + +const QString &Calendar::getOwner() const +{ + return mOwner; +} + +void Calendar::setOwner(const QString &os) +{ + int i; + mOwner = os; + i = mOwner.find(','); + if (i != -1) + mOwner = mOwner.left(i); + + setModified( true ); +} + +void Calendar::setTimeZone(const QString & tz) +{ + bool neg = FALSE; + int hours, minutes; + QString tmpStr(tz); + + if (tmpStr.left(1) == "-") + neg = TRUE; + if (tmpStr.left(1) == "-" || tmpStr.left(1) == "+") + tmpStr.remove(0, 1); + hours = tmpStr.left(2).toInt(); + if (tmpStr.length() > 2) + minutes = tmpStr.right(2).toInt(); + else + minutes = 0; + mTimeZone = (60*hours+minutes); + if (neg) + mTimeZone = -mTimeZone; + mLocalTime = false; + + setModified( true ); +} + +QString Calendar::getTimeZoneStr() const +{ + if (mLocalTime) + return ""; + QString tmpStr; + int hours = abs(mTimeZone / 60); + int minutes = abs(mTimeZone % 60); + bool neg = mTimeZone < 0; + + tmpStr.sprintf("%c%.2d%.2d", + (neg ? '-' : '+'), + hours, minutes); + return tmpStr; +} + +void Calendar::setTimeZone(int tz) +{ + mTimeZone = tz; + mLocalTime = false; + + setModified( true ); +} + +int Calendar::getTimeZone() const +{ + return mTimeZone; +} + +void Calendar::setTimeZoneId(const QString &id) +{ + mTimeZoneId = id; + mLocalTime = false; + mTimeZone = KGlobal::locale()->timezoneOffset(mTimeZoneId); + if ( mTimeZone > 1000) + setLocalTime(); + //qDebug("Calendar::setTimeZoneOffset %s %d ",mTimeZoneId.latin1(), mTimeZone); + setModified( true ); +} + +QString Calendar::timeZoneId() const +{ + return mTimeZoneId; +} + +void Calendar::setLocalTime() +{ + //qDebug("Calendar::setLocalTime() "); + mLocalTime = true; + mTimeZone = 0; + mTimeZoneId = ""; + + setModified( true ); +} + +bool Calendar::isLocalTime() const +{ + return mLocalTime; +} + +const QString &Calendar::getEmail() +{ + return mOwnerEmail; +} + +void Calendar::setEmail(const QString &e) +{ + mOwnerEmail = e; + + setModified( true ); +} + +void Calendar::setFilter(CalFilter *filter) +{ + mFilter = filter; +} + +CalFilter *Calendar::filter() +{ + return mFilter; +} + +QPtrList<Incidence> Calendar::incidences() +{ + QPtrList<Incidence> incidences; + + Incidence *i; + + QPtrList<Event> e = events(); + for( i = e.first(); i; i = e.next() ) incidences.append( i ); + + QPtrList<Todo> t = todos(); + for( i = t.first(); i; i = t.next() ) incidences.append( i ); + + QPtrList<Journal> j = journals(); + for( i = j.first(); i; i = j.next() ) incidences.append( i ); + + return incidences; +} + +QPtrList<Incidence> Calendar::rawIncidences() +{ + QPtrList<Incidence> incidences; + + Incidence *i; + + QPtrList<Event> e = rawEvents(); + for( i = e.first(); i; i = e.next() ) incidences.append( i ); + + QPtrList<Todo> t = rawTodos(); + for( i = t.first(); i; i = t.next() ) incidences.append( i ); + + QPtrList<Journal> j = journals(); + for( i = j.first(); i; i = j.next() ) incidences.append( i ); + + return incidences; +} + +QPtrList<Event> Calendar::events( const QDate &date, bool sorted ) +{ + QPtrList<Event> el = rawEventsForDate(date,sorted); + mFilter->apply(&el); + return el; +} + +QPtrList<Event> Calendar::events( const QDateTime &qdt ) +{ + QPtrList<Event> el = rawEventsForDate(qdt); + mFilter->apply(&el); + return el; +} + +QPtrList<Event> Calendar::events( const QDate &start, const QDate &end, + bool inclusive) +{ + QPtrList<Event> el = rawEvents(start,end,inclusive); + mFilter->apply(&el); + return el; +} + +QPtrList<Event> Calendar::events() +{ + QPtrList<Event> el = rawEvents(); + mFilter->apply(&el); + return el; +} + + +bool Calendar::addIncidence(Incidence *i) +{ + Incidence::AddVisitor<Calendar> v(this); + + return i->accept(v); +} +void Calendar::deleteIncidence(Incidence *in) +{ + if ( in->type() == "Event" ) + deleteEvent( (Event*) in ); + else if ( in->type() =="Todo" ) + deleteTodo( (Todo*) in); + else if ( in->type() =="Journal" ) + deleteJournal( (Journal*) in ); +} + +Incidence* Calendar::incidence( const QString& uid ) +{ + Incidence* i; + + if( (i = todo( uid )) != 0 ) + return i; + if( (i = event( uid )) != 0 ) + return i; + if( (i = journal( uid )) != 0 ) + return i; + + return 0; +} + +QPtrList<Todo> Calendar::todos() +{ + QPtrList<Todo> tl = rawTodos(); + mFilter->apply( &tl ); + return tl; +} + +// When this is called, the todo have already been added to the calendar. +// This method is only about linking related todos +void Calendar::setupRelations( Incidence *incidence ) +{ + QString uid = incidence->uid(); + //qDebug("Calendar::setupRelations "); + // First, go over the list of orphans and see if this is their parent + while( Incidence* i = mOrphans[ uid ] ) { + mOrphans.remove( uid ); + i->setRelatedTo( incidence ); + incidence->addRelation( i ); + mOrphanUids.remove( i->uid() ); + } + + // Now see about this incidences parent + if( !incidence->relatedTo() && !incidence->relatedToUid().isEmpty() ) { + // This incidence has a uid it is related to, but is not registered to it yet + // Try to find it + Incidence* parent = this->incidence( incidence->relatedToUid() ); + if( parent ) { + // Found it + incidence->setRelatedTo( parent ); + parent->addRelation( incidence ); + } else { + // Not found, put this in the mOrphans list + mOrphans.insert( incidence->relatedToUid(), incidence ); + mOrphanUids.insert( incidence->uid(), incidence ); + } + } +} + +// If a task with subtasks is deleted, move it's subtasks to the orphans list +void Calendar::removeRelations( Incidence *incidence ) +{ + // qDebug("Calendar::removeRelations "); + QString uid = incidence->uid(); + + QPtrList<Incidence> relations = incidence->relations(); + for( Incidence* i = relations.first(); i; i = relations.next() ) + if( !mOrphanUids.find( i->uid() ) ) { + mOrphans.insert( uid, i ); + mOrphanUids.insert( i->uid(), i ); + i->setRelatedTo( 0 ); + i->setRelatedToUid( uid ); + } + + // If this incidence is related to something else, tell that about it + if( incidence->relatedTo() ) + incidence->relatedTo()->removeRelation( incidence ); + + // Remove this one from the orphans list + if( mOrphanUids.remove( uid ) ) + // This incidence is located in the orphans list - it should be removed + if( !( incidence->relatedTo() != 0 && mOrphans.remove( incidence->relatedTo()->uid() ) ) ) { + // Removing wasn't that easy + for( QDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) { + if( it.current()->uid() == uid ) { + mOrphans.remove( it.currentKey() ); + break; + } + } + } +} + +void Calendar::registerObserver( Observer *observer ) +{ + mObserver = observer; + mNewObserver = true; +} + +void Calendar::setModified( bool modified ) +{ + if ( mObserver ) mObserver->calendarModified( modified, this ); + if ( modified != mModified || mNewObserver ) { + mNewObserver = false; + // if ( mObserver ) mObserver->calendarModified( modified, this ); + mModified = modified; + } +} + +void Calendar::setLoadedProductId( const QString &id ) +{ + mLoadedProductId = id; +} + +QString Calendar::loadedProductId() +{ + return mLoadedProductId; +} + +#include "calendar.moc" diff --git a/libkcal/calendar.h b/libkcal/calendar.h new file mode 100644 index 0000000..7a85e74 --- a/dev/null +++ b/libkcal/calendar.h @@ -0,0 +1,349 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef CALENDAR_H +#define CALENDAR_H + +#include <qobject.h> +#include <qstring.h> +#include <qdatetime.h> +#include <qptrlist.h> +#include <qdict.h> + +#include "customproperties.h" +#include "event.h" +#include "todo.h" +#include "journal.h" + +#define _TIME_ZONE "-0500" /* hardcoded, overridden in config file. */ + +class KConfig; + +namespace KCal { + +class CalFilter; + +/** + This is the main "calendar" object class for KOrganizer. It holds + information like all appointments/events, user information, etc. etc. + one calendar is associated with each CalendarView (@see calendarview.h). + This is an abstract base class defining the interface to a calendar. It is + implemented by subclasses like @see CalendarLocal, which use different + methods to store and access the data. + + Ownership of events etc. is handled by the following policy: As soon as an + event (or any other subclass of IncidenceBase) object is added to the + Calendar by addEvent() it is owned by the Calendar object. The Calendar takes + care of deleting it. All Events returned by the query functions are returned + as pointers, that means all changes to the returned events are immediately + visible in the Calendar. You shouldn't delete any Event object you get from + Calendar. +*/ +class Calendar : public QObject, public CustomProperties, + public IncidenceBase::Observer +{ + Q_OBJECT +public: + Calendar(); + Calendar(const QString &timeZoneId); + virtual ~Calendar(); + void deleteIncidence(Incidence *in); + /** + Clears out the current calendar, freeing all used memory etc. + */ + virtual void close() = 0; + + /** + Sync changes in memory to persistant storage. + */ + virtual void save() = 0; + + virtual bool isSaving() { return false; } + + /** + Return the owner of the calendar's full name. + */ + const QString &getOwner() const; + /** + Set the owner of the calendar. Should be owner's full name. + */ + void setOwner( const QString &os ); + /** + Return the email address of the calendar owner. + */ + const QString &getEmail(); + /** + Set the email address of the calendar owner. + */ + void setEmail( const QString & ); + + /** + Set time zone from a timezone string (e.g. -2:00) + */ + void setTimeZone( const QString &tz ); + /** + Set time zone from a minutes value (e.g. -60) + */ + void setTimeZone( int tz ); + /** + Return time zone as offest in minutes. + */ + int getTimeZone() const; + /** + Compute an ISO 8601 format string from the time zone. + */ + QString getTimeZoneStr() const; + /** + Set time zone id (see /usr/share/zoneinfo/zone.tab for list of legal + values). + */ + void setTimeZoneId( const QString & ); + /** + Return time zone id. + */ + QString timeZoneId() const; + /** + Use local time, not UTC or a time zone. + */ + void setLocalTime(); + /** + Return whether local time is being used. + */ + bool isLocalTime() const; + + /** + Add an incidence to calendar. + + @return true on success, false on error. + */ + virtual bool addIncidence( Incidence * ); + /** + Return filtered list of all incidences of this calendar. + */ + virtual QPtrList<Incidence> incidences(); + + /** + Return unfiltered list of all incidences of this calendar. + */ + virtual QPtrList<Incidence> rawIncidences(); + + /** + Adds a Event to this calendar object. + @param anEvent a pointer to the event to add + + @return true on success, false on error. + */ + virtual bool addEventNoDup( Event *event ) = 0; + virtual bool addEvent( Event *anEvent ) = 0; + /** + Delete event from calendar. + */ + virtual void deleteEvent( Event * ) = 0; + /** + Retrieves an event on the basis of the unique string ID. + */ + virtual Event *event( const QString &UniqueStr ) = 0; + virtual Event *event( int ) = 0; + /** + Builds and then returns a list of all events that match for the + date specified. useful for dayView, etc. etc. + The calendar filter is applied. + */ + QPtrList<Event> events( const QDate &date, bool sorted = false); + /** + Get events, which occur on the given date. + The calendar filter is applied. + */ + QPtrList<Event> events( const QDateTime &qdt ); + /** + Get events in a range of dates. If inclusive is set to true, only events + are returned, which are completely included in the range. + The calendar filter is applied. + */ + QPtrList<Event> events( const QDate &start, const QDate &end, + bool inclusive = false); + /** + Return filtered list of all events in calendar. + */ + virtual QPtrList<Event> events(); + /** + Return unfiltered list of all events in calendar. + */ + virtual QPtrList<Event> rawEvents() = 0; + + /** + Add a todo to the todolist. + + @return true on success, false on error. + */ + virtual bool addTodo( Todo *todo ) = 0; + virtual bool addTodoNoDup( Todo *todo ) = 0; + /** + Remove a todo from the todolist. + */ + virtual void deleteTodo( Todo * ) = 0; + virtual void deleteJournal( Journal * ) = 0; + /** + Return filterd list of todos. + */ + virtual QPtrList<Todo> todos(); + /** + Searches todolist for an event with this unique string identifier, + returns a pointer or null. + */ + virtual Todo *todo( const QString &uid ) = 0; + virtual Todo *todo( int ) = 0; + /** + Returns list of todos due on the specified date. + */ + virtual QPtrList<Todo> todos( const QDate &date ) = 0; + /** + Return unfiltered list of todos. + */ + virtual QPtrList<Todo> rawTodos() = 0; + + /** + Add a Journal entry to calendar. + + @return true on success, false on error. + */ + virtual bool addJournal( Journal * ) = 0; + /** + Return Journal for given date. + */ + virtual Journal *journal( const QDate & ) = 0; + /** + Return Journal with given UID. + */ + virtual Journal *journal( const QString &UID ) = 0; + /** + Return list of all Journal entries. + */ + virtual QPtrList<Journal> journals() = 0; + + /** + Searches all incidence types for an incidence with this unique + string identifier, returns a pointer or null. + */ + Incidence* incidence( const QString&UID ); + + /** + Setup relations for an incidence. + */ + virtual void setupRelations( Incidence * ); + /** + Remove all relations to an incidence + */ + virtual void removeRelations( Incidence * ); + + /** + Set calendar filter, which filters events for the events() functions. + The Filter object is owned by the caller. + */ + void setFilter( CalFilter * ); + /** + Return calendar filter. + */ + CalFilter *filter(); + virtual QDateTime nextAlarm( int daysTo ) = 0; + virtual QString nextSummary( ) const = 0; + virtual void reInitAlarmSettings() = 0; + virtual QDateTime nextAlarmEventDateTime() const = 0; + virtual void checkAlarmForIncidence( Incidence *, bool ) = 0; + /** + Return all alarms, which ocur in the given time interval. + */ + virtual Alarm::List alarms( const QDateTime &from, + const QDateTime &to ) = 0; + + class Observer { + public: + virtual void calendarModified( bool, Calendar * ) = 0; + }; + + void registerObserver( Observer * ); + + void setModified( bool ); + + /** + Set product id returned by loadedProductId(). This function is only + useful for the calendar loading code. + */ + void setLoadedProductId( const QString & ); + /** + Return product id taken from file that has been loaded. Returns + QString::null, if no calendar has been loaded. + */ + QString loadedProductId(); + + signals: + void calendarChanged(); + void calendarSaved(); + void calendarLoaded(); + void addAlarm(const QDateTime &qdt, const QString ¬i ); + void removeAlarm(const QDateTime &qdt, const QString ¬i ); + + protected: + /** + Get unfiltered events, which occur on the given date. + */ + virtual QPtrList<Event> rawEventsForDate( const QDateTime &qdt ) = 0; + /** + Get unfiltered events, which occur on the given date. + */ + virtual QPtrList<Event> rawEventsForDate( const QDate &date, + bool sorted = false ) = 0; + /** + Get events in a range of dates. If inclusive is set to true, only events + are returned, which are completely included in the range. + */ + virtual QPtrList<Event> rawEvents( const QDate &start, const QDate &end, + bool inclusive = false ) = 0; + Incidence *mNextAlarmIncidence; + +private: + void init(); + + QString mOwner; // who the calendar belongs to + QString mOwnerEmail; // email address of the owner + int mTimeZone; // timezone OFFSET from GMT (MINUTES) + bool mLocalTime; // use local time, not UTC or a time zone + + CalFilter *mFilter; + CalFilter *mDefaultFilter; + + QString mTimeZoneId; + + Observer *mObserver; + bool mNewObserver; + + bool mModified; + + QString mLoadedProductId; + + // This list is used to put together related todos + QDict<Incidence> mOrphans; + QDict<Incidence> mOrphanUids; +}; + +} + +#endif diff --git a/libkcal/calendar.moc b/libkcal/calendar.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libkcal/calendar.moc diff --git a/libkcal/calendarlocal.cpp b/libkcal/calendarlocal.cpp new file mode 100644 index 0000000..8ff8b14 --- a/dev/null +++ b/libkcal/calendarlocal.cpp @@ -0,0 +1,655 @@ +/* + This file is part of libkcal. + + Copyright (c) 1998 Preston Brown + Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdatetime.h> +#include <qstring.h> +#include <qptrlist.h> + +#include <kdebug.h> +#include <kconfig.h> +#include <kglobal.h> +#include <klocale.h> + +#include "vcaldrag.h" +#include "vcalformat.h" +#include "icalformat.h" +#include "exceptions.h" +#include "incidence.h" +#include "journal.h" +#include "filestorage.h" +#include "calfilter.h" + +#include "calendarlocal.h" + +// #ifndef DESKTOP_VERSION +// #include <qtopia/alarmserver.h> +// #endif +using namespace KCal; + +CalendarLocal::CalendarLocal() + : Calendar() +{ + init(); +} + +CalendarLocal::CalendarLocal(const QString &timeZoneId) + : Calendar(timeZoneId) +{ + init(); +} + +void CalendarLocal::init() +{ + mNextAlarmIncidence = 0; +} + + +CalendarLocal::~CalendarLocal() +{ + close(); +} + +bool CalendarLocal::load( const QString &fileName ) +{ + FileStorage storage( this, fileName ); + return storage.load(); +} + +bool CalendarLocal::save( const QString &fileName, CalFormat *format ) +{ + FileStorage storage( this, fileName, format ); + return storage.save(); +} + +void CalendarLocal::close() +{ + mEventList.setAutoDelete( true ); + mTodoList.setAutoDelete( true ); + mJournalList.setAutoDelete( false ); + + mEventList.clear(); + mTodoList.clear(); + mJournalList.clear(); + + mEventList.setAutoDelete( false ); + mTodoList.setAutoDelete( false ); + mJournalList.setAutoDelete( false ); + + setModified( false ); +} +bool CalendarLocal::addEventNoDup( Event *event ) +{ + Event * eve; + for ( eve = mEventList.first(); eve ; eve = mEventList.next() ) { + if ( *eve == *event ) { + //qDebug("CalendarLocal::Duplicate event found! Not inserted! "); + return false; + } + } + return addEvent( event ); +} + +bool CalendarLocal::addEvent( Event *event ) +{ + insertEvent( event ); + + event->registerObserver( this ); + + setModified( true ); + + return true; +} + +void CalendarLocal::deleteEvent( Event *event ) +{ + + + if ( mEventList.removeRef( event ) ) { + setModified( true ); + } +} + + +Event *CalendarLocal::event( const QString &uid ) +{ + + Event *event; + + for ( event = mEventList.first(); event; event = mEventList.next() ) { + if ( event->uid() == uid ) { + return event; + } + } + + return 0; +} +bool CalendarLocal::addTodoNoDup( Todo *todo ) +{ + Todo * eve; + for ( eve = mTodoList.first(); eve ; eve = mTodoList.next() ) { + if ( *eve == *todo ) { + //qDebug("duplicate todo found! not inserted! "); + return false; + } + } + return addTodo( todo ); +} +bool CalendarLocal::addTodo( Todo *todo ) +{ + mTodoList.append( todo ); + + todo->registerObserver( this ); + + // Set up subtask relations + setupRelations( todo ); + + setModified( true ); + + return true; +} + +void CalendarLocal::deleteTodo( Todo *todo ) +{ + // Handle orphaned children + removeRelations( todo ); + + if ( mTodoList.removeRef( todo ) ) { + setModified( true ); + } +} + +QPtrList<Todo> CalendarLocal::rawTodos() +{ + return mTodoList; +} +Todo *CalendarLocal::todo( int id ) +{ + Todo *todo; + for ( todo = mTodoList.first(); todo; todo = mTodoList.next() ) { + if ( todo->zaurusId() == id ) return todo; + } + + return 0; +} + +Event *CalendarLocal::event( int id ) +{ + Event *todo; + for ( todo = mEventList.first(); todo; todo = mEventList.next() ) { + if ( todo->zaurusId() == id ) return todo; + } + + return 0; +} +Todo *CalendarLocal::todo( const QString &uid ) +{ + Todo *todo; + for ( todo = mTodoList.first(); todo; todo = mTodoList.next() ) { + if ( todo->uid() == uid ) return todo; + } + + return 0; +} +QString CalendarLocal::nextSummary() const +{ + return mNextSummary; +} +QDateTime CalendarLocal::nextAlarmEventDateTime() const +{ + return mNextAlarmEventDateTime; +} +void CalendarLocal::checkAlarmForIncidence( Incidence * incidence, bool deleted) +{ + //mNextAlarmIncidence + //mNextAlarmDateTime + //return mNextSummary; + //return mNextAlarmEventDateTime; + bool newNextAlarm = false; + bool computeNextAlarm = false; + bool ok; + int offset; + QDateTime nextA; + // QString nextSum; + //QDateTime nextEvent; + if ( mNextAlarmIncidence == 0 || incidence == 0 ) { + computeNextAlarm = true; + } else { + if ( ! deleted ) { + nextA = incidence->getNextAlarmDateTime(& ok, &offset ) ; + if ( ok ) { + if ( nextA < mNextAlarmDateTime ) { + deRegisterAlarm(); + mNextAlarmDateTime = nextA; + mNextSummary = incidence->summary(); + mNextAlarmEventDateTime = nextA.addSecs(offset ) ; + mNextAlarmEventDateTimeString = KGlobal::locale()->formatDateTime(mNextAlarmEventDateTime); + newNextAlarm = true; + mNextAlarmIncidence = incidence; + } else { + if ( incidence == mNextAlarmIncidence ) { + computeNextAlarm = true; + } + } + } else { + if ( mNextAlarmIncidence == incidence ) { + computeNextAlarm = true; + } + } + } else { // deleted + if ( incidence == mNextAlarmIncidence ) { + computeNextAlarm = true; + } + } + } + if ( computeNextAlarm ) { + deRegisterAlarm(); + nextA = nextAlarm( 1000 ); + if (! mNextAlarmIncidence ) { + return; + } + newNextAlarm = true; + } + if ( newNextAlarm ) + registerAlarm(); +} +QString CalendarLocal:: getAlarmNotification() +{ + QString ret; + // this should not happen + if (! mNextAlarmIncidence ) + return "cal_alarm"+ mNextSummary.left( 25 )+"\n"+mNextAlarmEventDateTimeString; + Alarm* alarm = mNextAlarmIncidence->alarms().first(); + if ( alarm->type() == Alarm::Procedure ) { + ret = "proc_alarm" + alarm->programFile()+"+++"; + } else { + ret = "audio_alarm" +alarm->audioFile() +"+++"; + } + ret += "cal_alarm"+ mNextSummary.left( 25 ); + if ( mNextSummary.length() > 25 ) + ret += "\n" + mNextSummary.mid(25, 25 ); + ret+= "\n"+mNextAlarmEventDateTimeString; + return ret; +} + +void CalendarLocal::registerAlarm() +{ + mLastAlarmNotificationString = getAlarmNotification(); + // qDebug("++ register Alarm %s %s",mNextAlarmDateTime.toString().latin1(), mLastAlarmNotificationString.latin1() ); + emit addAlarm ( mNextAlarmDateTime, mLastAlarmNotificationString ); +// #ifndef DESKTOP_VERSION +// AlarmServer::addAlarm ( mNextAlarmDateTime,"koalarm", mLastAlarmNotificationString.latin1() ); +// #endif +} +void CalendarLocal::deRegisterAlarm() +{ + if ( mLastAlarmNotificationString.isNull() ) + return; + //qDebug("-- deregister Alarm %s ", mLastAlarmNotificationString.latin1() ); + + emit removeAlarm ( mNextAlarmDateTime, mLastAlarmNotificationString ); +// #ifndef DESKTOP_VERSION +// AlarmServer::deleteAlarm (mNextAlarmDateTime ,"koalarm" ,mLastAlarmNotificationString.latin1() ); +// #endif +} + +QPtrList<Todo> CalendarLocal::todos( const QDate &date ) +{ + QPtrList<Todo> todos; + + Todo *todo; + for ( todo = mTodoList.first(); todo; todo = mTodoList.next() ) { + if ( todo->hasDueDate() && todo->dtDue().date() == date ) { + todos.append( todo ); + } + } + + filter()->apply( &todos ); + return todos; +} +void CalendarLocal::reInitAlarmSettings() +{ + if ( !mNextAlarmIncidence ) { + nextAlarm( 1000 ); + } + deRegisterAlarm(); + mNextAlarmIncidence = 0; + checkAlarmForIncidence( 0, false ); + +} + + + +QDateTime CalendarLocal::nextAlarm( int daysTo ) +{ + QDateTime nextA = QDateTime::currentDateTime().addDays( daysTo ); + QDateTime start = QDateTime::currentDateTime().addSecs( 30 ); + QDateTime next; + Event *e; + bool ok; + bool found = false; + int offset; + mNextAlarmIncidence = 0; + for( e = mEventList.first(); e; e = mEventList.next() ) { + next = e->getNextAlarmDateTime(& ok, &offset ) ; + if ( ok ) { + if ( next < nextA ) { + nextA = next; + found = true; + mNextSummary = e->summary(); + mNextAlarmEventDateTime = next.addSecs(offset ) ; + mNextAlarmIncidence = (Incidence *) e; + } + } + } + Todo *t; + for( t = mTodoList.first(); t; t = mTodoList.next() ) { + next = t->getNextAlarmDateTime(& ok, &offset ) ; + if ( ok ) { + if ( next < nextA ) { + nextA = next; + found = true; + mNextSummary = t->summary(); + mNextAlarmEventDateTime = next.addSecs(offset ); + mNextAlarmIncidence = (Incidence *) t; + } + } + } + if ( mNextAlarmIncidence ) { + mNextAlarmEventDateTimeString = KGlobal::locale()->formatDateTime(mNextAlarmEventDateTime); + mNextAlarmDateTime = nextA; + } + return nextA; +} +Alarm::List CalendarLocal::alarmsTo( const QDateTime &to ) +{ + return alarms( QDateTime( QDate( 1900, 1, 1 ) ), to ); +} + +Alarm::List CalendarLocal::alarms( const QDateTime &from, const QDateTime &to ) +{ + kdDebug(5800) << "CalendarLocal::alarms(" << from.toString() << " - " + << to.toString() << ")\n"; + + Alarm::List alarms; + + Event *e; + + for( e = mEventList.first(); e; e = mEventList.next() ) { + if ( e->doesRecur() ) appendRecurringAlarms( alarms, e, from, to ); + else appendAlarms( alarms, e, from, to ); + } + + Todo *t; + for( t = mTodoList.first(); t; t = mTodoList.next() ) { + appendAlarms( alarms, t, from, to ); + } + + return alarms; +} + +void CalendarLocal::appendAlarms( Alarm::List &alarms, Incidence *incidence, + const QDateTime &from, const QDateTime &to ) +{ + QPtrList<Alarm> alarmList = incidence->alarms(); + Alarm *alarm; + for( alarm = alarmList.first(); alarm; alarm = alarmList.next() ) { +// kdDebug(5800) << "CalendarLocal::appendAlarms() '" << alarm->text() +// << "': " << alarm->time().toString() << " - " << alarm->enabled() << endl; + if ( alarm->enabled() ) { + if ( alarm->time() >= from && alarm->time() <= to ) { + kdDebug(5800) << "CalendarLocal::appendAlarms() '" << incidence->summary() + << "': " << alarm->time().toString() << endl; + alarms.append( alarm ); + } + } + } +} + +void CalendarLocal::appendRecurringAlarms( Alarm::List &alarms, + Incidence *incidence, + const QDateTime &from, + const QDateTime &to ) +{ + + QPtrList<Alarm> alarmList = incidence->alarms(); + Alarm *alarm; + QDateTime qdt; + for( alarm = alarmList.first(); alarm; alarm = alarmList.next() ) { + if (incidence->recursOn(from.date())) { + qdt.setTime(alarm->time().time()); + qdt.setDate(from.date()); + } + else qdt = alarm->time(); + // qDebug("1 %s %s %s", qdt.toString().latin1(), from.toString().latin1(), to.toString().latin1()); + if ( alarm->enabled() ) { + if ( qdt >= from && qdt <= to ) { + alarms.append( alarm ); + } + } + } +} + + +/****************************** PROTECTED METHODS ****************************/ + +// after changes are made to an event, this should be called. +void CalendarLocal::update( IncidenceBase *incidence ) +{ + incidence->setSyncStatus( Event::SYNCMOD ); + incidence->setLastModified( QDateTime::currentDateTime() ); + // we should probably update the revision number here, + // or internally in the Event itself when certain things change. + // need to verify with ical documentation. + + setModified( true ); +} + +void CalendarLocal::insertEvent( Event *event ) +{ + if ( mEventList.findRef( event ) < 0 ) mEventList.append( event ); +} + + +QPtrList<Event> CalendarLocal::rawEventsForDate( const QDate &qd, bool sorted ) +{ + QPtrList<Event> eventList; + + Event *event; + for( event = mEventList.first(); event; event = mEventList.next() ) { + if ( event->doesRecur() ) { + if ( event->isMultiDay() ) { + int extraDays = event->dtStart().date().daysTo( event->dtEnd().date() ); + int i; + for ( i = 0; i <= extraDays; i++ ) { + if ( event->recursOn( qd.addDays( -i ) ) ) { + eventList.append( event ); + break; + } + } + } else { + if ( event->recursOn( qd ) ) + eventList.append( event ); + } + } else { + if ( event->dtStart().date() <= qd && event->dtEnd().date() >= qd ) { + eventList.append( event ); + } + } + } + + if ( !sorted ) { + return eventList; + } + + // kdDebug(5800) << "Sorting events for date\n" << endl; + // now, we have to sort it based on dtStart.time() + QPtrList<Event> eventListSorted; + Event *sortEvent; + for ( event = eventList.first(); event; event = eventList.next() ) { + sortEvent = eventListSorted.first(); + int i = 0; + while ( sortEvent && event->dtStart().time()>=sortEvent->dtStart().time() ) + { + i++; + sortEvent = eventListSorted.next(); + } + eventListSorted.insert( i, event ); + } + return eventListSorted; +} + + +QPtrList<Event> CalendarLocal::rawEvents( const QDate &start, const QDate &end, + bool inclusive ) +{ + Event *event = 0; + + QPtrList<Event> eventList; + + // Get non-recurring events + for( event = mEventList.first(); event; event = mEventList.next() ) { + if ( event->doesRecur() ) { + QDate rStart = event->dtStart().date(); + bool found = false; + if ( inclusive ) { + if ( rStart >= start && rStart <= end ) { + // Start date of event is in range. Now check for end date. + // if duration is negative, event recurs forever, so do not include it. + if ( event->recurrence()->duration() == 0 ) { // End date set + QDate rEnd = event->recurrence()->endDate(); + if ( rEnd >= start && rEnd <= end ) { // End date within range + found = true; + } + } else if ( event->recurrence()->duration() > 0 ) { // Duration set + // TODO: Calculate end date from duration. Should be done in Event + // For now exclude all events with a duration. + } + } + } else { + bool founOne; + QDate next = event->getNextOccurence( start, &founOne ).date(); + if ( founOne ) { + if ( next <= end ) { + found = true; + } + } + + /* + // crap !!! + if ( rStart <= end ) { // Start date not after range + if ( rStart >= start ) { // Start date within range + found = true; + } else if ( event->recurrence()->duration() == -1 ) { // Recurs forever + found = true; + } else if ( event->recurrence()->duration() == 0 ) { // End date set + QDate rEnd = event->recurrence()->endDate(); + if ( rEnd >= start && rEnd <= end ) { // End date within range + found = true; + } + } else { // Duration set + // TODO: Calculate end date from duration. Should be done in Event + // For now include all events with a duration. + found = true; + } + } + */ + + } + + if ( found ) eventList.append( event ); + } else { + QDate s = event->dtStart().date(); + QDate e = event->dtEnd().date(); + + if ( inclusive ) { + if ( s >= start && e <= end ) { + eventList.append( event ); + } + } else { + if ( ( s >= start && s <= end ) || ( e >= start && e <= end ) ) { + eventList.append( event ); + } + } + } + } + + return eventList; +} + +QPtrList<Event> CalendarLocal::rawEventsForDate( const QDateTime &qdt ) +{ + return rawEventsForDate( qdt.date() ); +} + +QPtrList<Event> CalendarLocal::rawEvents() +{ + return mEventList; +} + +bool CalendarLocal::addJournal(Journal *journal) +{ + if ( journal->dtStart().isValid()) + kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl; + else + kdDebug(5800) << "Adding Journal without a DTSTART" << endl; + + mJournalList.append(journal); + + journal->registerObserver( this ); + + setModified( true ); + + return true; +} + +void CalendarLocal::deleteJournal( Journal *journal ) +{ + if ( mJournalList.removeRef(journal) ) { + setModified( true ); + } +} + +Journal *CalendarLocal::journal( const QDate &date ) +{ +// kdDebug(5800) << "CalendarLocal::journal() " << date.toString() << endl; + + for ( Journal *it = mJournalList.first(); it; it = mJournalList.next() ) + if ( it->dtStart().date() == date ) + return it; + + return 0; +} + +Journal *CalendarLocal::journal( const QString &uid ) +{ + for ( Journal *it = mJournalList.first(); it; it = mJournalList.next() ) + if ( it->uid() == uid ) + return it; + + return 0; +} + +QPtrList<Journal> CalendarLocal::journals() +{ + return mJournalList; +} + diff --git a/libkcal/calendarlocal.h b/libkcal/calendarlocal.h new file mode 100644 index 0000000..a17cf11 --- a/dev/null +++ b/libkcal/calendarlocal.h @@ -0,0 +1,216 @@ +/* + This file is part of libkcal. + + Copyright (c) 1998 Preston Brown + Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_CALENDARLOCAL_H +#define KCAL_CALENDARLOCAL_H + +#include "calendar.h" + +namespace KCal { + +class CalFormat; + +/** + This class provides a calendar stored as a local file. +*/ +class CalendarLocal : public Calendar +{ + public: + /** + Constructs a new calendar, with variables initialized to sane values. + */ + CalendarLocal(); + /** + Constructs a new calendar, with variables initialized to sane values. + */ + CalendarLocal( const QString &timeZoneId ); + ~CalendarLocal(); + + /** + Loads a calendar on disk in vCalendar or iCalendar format into the current + calendar. Any information already present is lost. + @return true, if successfull, false on error. + @param fileName the name of the calendar on disk. + */ + bool load( const QString &fileName ); + /** + Writes out the calendar to disk in the specified \a format. + CalendarLocal takes ownership of the CalFormat object. + @return true, if successfull, false on error. + @param fileName the name of the file + */ + bool save( const QString &fileName, CalFormat *format = 0 ); + + /** + Clears out the current calendar, freeing all used memory etc. etc. + */ + void close(); + + void save() {} + + /** + Add Event to calendar. + */ + bool addEventNoDup( Event *event ); + bool addEvent( Event *event ); + /** + Deletes an event from this calendar. + */ + void deleteEvent( Event *event ); + + /** + Retrieves an event on the basis of the unique string ID. + */ + Event *event( const QString &uid ); + /** + Return unfiltered list of all events in calendar. + */ + QPtrList<Event> rawEvents(); + + /** + Add a todo to the todolist. + */ + bool addTodo( Todo *todo ); + bool addTodoNoDup( Todo *todo ); + /** + Remove a todo from the todolist. + */ + void deleteTodo( Todo * ); + /** + Searches todolist for an event with this unique string identifier, + returns a pointer or null. + */ + Todo *todo( const QString &uid ); + /** + Return list of all todos. + */ + QPtrList<Todo> rawTodos(); + /** + Returns list of todos due on the specified date. + */ + QPtrList<Todo> todos( const QDate &date ); + /** + Return list of all todos. + + Workaround because compiler does not recognize function of base class. + */ + QPtrList<Todo> todos() { return Calendar::todos(); } + + /** + Add a Journal entry to calendar. + */ + bool addJournal( Journal * ); + /** + Remove a Journal from the calendar. + */ + void deleteJournal( Journal * ); + /** + Return Journal for given date. + */ + Journal *journal( const QDate & ); + /** + Return Journal with given UID. + */ + Journal *journal( const QString &uid ); + /** + Return list of all Journals stored in calendar. + */ + QPtrList<Journal> journals(); + + /** + Return all alarms, which ocur in the given time interval. + */ + Alarm::List alarms( const QDateTime &from, const QDateTime &to ); + + /** + Return all alarms, which ocur before given date. + */ + Alarm::List alarmsTo( const QDateTime &to ); + + QDateTime nextAlarm( int daysTo ) ; + QDateTime nextAlarmEventDateTime() const; + void checkAlarmForIncidence( Incidence *, bool deleted ) ; + void registerAlarm(); + void deRegisterAlarm(); + QString getAlarmNotification(); + QString nextSummary() const ; + /** + This method should be called whenever a Event is modified directly + via it's pointer. It makes sure that the calendar is internally + consistent. + */ + void update( IncidenceBase *incidence ); + + /** + Builds and then returns a list of all events that match for the + date specified. useful for dayView, etc. etc. + */ + QPtrList<Event> rawEventsForDate( const QDate &date, bool sorted = false ); + /** + Get unfiltered events for date \a qdt. + */ + QPtrList<Event> rawEventsForDate( const QDateTime &qdt ); + /** + Get unfiltered events in a range of dates. If inclusive is set to true, + only events are returned, which are completely included in the range. + */ + QPtrList<Event> rawEvents( const QDate &start, const QDate &end, + bool inclusive = false ); + Todo *CalendarLocal::todo( int uid ); + Event *CalendarLocal::event( int uid ); + + + + protected: + + // Event* mNextAlarmEvent; + QString mNextSummary; + QString mNextAlarmEventDateTimeString; + QString mLastAlarmNotificationString; + QDateTime mNextAlarmEventDateTime; + QDateTime mNextAlarmDateTime; + void reInitAlarmSettings(); + + /** Notification function of IncidenceBase::Observer. */ + void incidenceUpdated( IncidenceBase *i ) { update( i ); } + + /** inserts an event into its "proper place" in the calendar. */ + void insertEvent( Event *event ); + + /** Append alarms of incidence in interval to list of alarms. */ + void appendAlarms( Alarm::List &alarms, Incidence *incidence, + const QDateTime &from, const QDateTime &to ); + + /** Append alarms of recurring events in interval to list of alarms. */ + void appendRecurringAlarms( Alarm::List &alarms, Incidence *incidence, + const QDateTime &from, const QDateTime &to ); + + private: + void init(); + + QPtrList<Event> mEventList; + QPtrList<Todo> mTodoList; + QPtrList<Journal> mJournalList; +}; + +} + +#endif diff --git a/libkcal/calendarresources.h b/libkcal/calendarresources.h new file mode 100644 index 0000000..a218dd7 --- a/dev/null +++ b/libkcal/calendarresources.h @@ -0,0 +1,17 @@ +#ifndef MICRO_KCAL_CALENDARRESOURCES_H +#define MICRO_KCAL_CALENDARRESOURCES_H + +#include "calendar.h" +#include "resourcecalendar.h" + +namespace KCal { + +class CalendarResources : public Calendar +{ + public: + CalendarResourceManager *resourceManager() { return 0; } +}; + +} + +#endif diff --git a/libkcal/calfilter.cpp b/libkcal/calfilter.cpp new file mode 100644 index 0000000..c182db5 --- a/dev/null +++ b/libkcal/calfilter.cpp @@ -0,0 +1,201 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> + +#include "calfilter.h" + +using namespace KCal; + +CalFilter::CalFilter() +{ + mEnabled = true; + mCriteria = ShowPublic | ShowPrivate| ShowConfidential ; +} + +CalFilter::CalFilter(const QString &name) +{ + mName = name; + mEnabled = true; + mCriteria = ShowPublic | ShowPrivate| ShowConfidential ; +} + +CalFilter::~CalFilter() +{ +} + +void CalFilter::apply(QPtrList<Event> *eventlist) +{ + if (!mEnabled) return; + +// kdDebug(5800) << "CalFilter::apply()" << endl; + + Event *event = eventlist->first(); + while(event) { + if (!filterEvent(event)) { + eventlist->remove(); + event = eventlist->current(); + } else { + event = eventlist->next(); + } + } + +// kdDebug(5800) << "CalFilter::apply() done" << endl; +} + +// TODO: avoid duplicating apply() code +void CalFilter::apply(QPtrList<Todo> *eventlist) +{ + if (!mEnabled) return; + +// kdDebug(5800) << "CalFilter::apply()" << endl; + + Todo *event = eventlist->first(); + while(event) { + if (!filterTodo(event)) { + eventlist->remove(); + event = eventlist->current(); + } else { + event = eventlist->next(); + } + } + +// kdDebug(5800) << "CalFilter::apply() done" << endl; +} + +bool CalFilter::filterEvent(Event *event) +{ +// kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl; + + if (mCriteria & HideRecurring) { + if (event->recurrence()->doesRecur()) return false; + } + + return filterIncidence(event); +} + +bool CalFilter::filterTodo(Todo *todo) +{ +// kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl; + + if (mCriteria & HideCompleted) { + if (todo->isCompleted()) return false; + } + + return filterIncidence(todo); +} +bool CalFilter::showCategories() +{ + return mCriteria & ShowCategories; +} +int CalFilter::getSecrecy() +{ + if ( (mCriteria & ShowPublic )) + return Incidence::SecrecyPublic; + if ( (mCriteria & ShowPrivate )) + return Incidence::SecrecyPrivate; + if ( (mCriteria & ShowConfidential )) + return Incidence::SecrecyConfidential; + return Incidence::SecrecyPublic; +} +bool CalFilter::filterIncidence(Incidence *incidence) +{ + if ( mCriteria > 7 ) { + switch (incidence->secrecy()) { + case Incidence::SecrecyPublic: + if (! (mCriteria & ShowPublic )) + return false; + break; + case Incidence::SecrecyPrivate: + if (! (mCriteria & ShowPrivate )) + return false; + break; + case Incidence::SecrecyConfidential: + if (! (mCriteria & ShowConfidential )) + return false; + break; + default: + return false; + break; + } + } + + // kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl; + + if (mCriteria & ShowCategories) { + for (QStringList::Iterator it = mCategoryList.begin(); + it != mCategoryList.end(); ++it ) { + QStringList incidenceCategories = incidence->categories(); + for (QStringList::Iterator it2 = incidenceCategories.begin(); + it2 != incidenceCategories.end(); ++it2 ) { + if ((*it) == (*it2)) { + return true; + } + } + } + return false; + } else { + for (QStringList::Iterator it = mCategoryList.begin(); + it != mCategoryList.end(); ++it ) { + QStringList incidenceCategories = incidence->categories(); + for (QStringList::Iterator it2 = incidenceCategories.begin(); + it2 != incidenceCategories.end(); ++it2 ) { + if ((*it) == (*it2)) { + return false; + } + } + } + return true; + } + +// kdDebug(5800) << "CalFilter::filterEvent(): passed" << endl; + + return true; +} + +void CalFilter::setEnabled(bool enabled) +{ + mEnabled = enabled; +} + +bool CalFilter::isEnabled() +{ + return mEnabled; +} + +void CalFilter::setCriteria(int criteria) +{ + mCriteria = criteria; +} + +int CalFilter::criteria() +{ + return mCriteria; +} + +void CalFilter::setCategoryList(const QStringList &categoryList) +{ + mCategoryList = categoryList; +} + +QStringList CalFilter::categoryList() +{ + return mCategoryList; +} diff --git a/libkcal/calfilter.h b/libkcal/calfilter.h new file mode 100644 index 0000000..d6d4717 --- a/dev/null +++ b/libkcal/calfilter.h @@ -0,0 +1,128 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _CALFILTER_H +#define _CALFILTER_H + +#include <qstring.h> +#include <qptrlist.h> + +#include "event.h" +#include "todo.h" + +namespace KCal { + +/** + Filter for calendar objects. +*/ +class CalFilter { + public: + /** Construct filter. */ + CalFilter(); + /** Construct filter with name */ + CalFilter(const QString &name); + /** Destruct filter. */ + ~CalFilter(); + + /** + Set name of filter. + */ + void setName(const QString &name) { mName = name; } + /** + Return name of filter. + */ + QString name() const { return mName; } + + /** + Apply filter to eventlist, all events not matching filter criterias are + removed from the list. + */ + void apply(QPtrList<Event> *eventlist); + + /** + Apply filter to todolist, all todos not matching filter criterias are + removed from the list. + */ + void apply(QPtrList<Todo> *todolist); + + /** + Apply filter criteria on the specified event. Return true, if event passes + criteria, otherwise return false. + */ + bool filterEvent(Event *); + + /** + Apply filter criteria on the specified todo. Return true, if event passes + criteria, otherwise return false. + */ + bool filterTodo(Todo *); + + /** + Apply filter criteria on the specified incidence. Return true, if event passes + criteria, otherwise return false. + */ + bool filterIncidence(Incidence *); + + /** + Enable or disable filter. + */ + void setEnabled(bool); + /** + Return wheter the filter is enabled or not. + */ + bool isEnabled(); + bool showCategories(); + int getSecrecy(); + /** + Set list of categories, which is used for showing/hiding categories of + events. + See related functions. + */ + void setCategoryList(const QStringList &); + /** + Return category list, used for showing/hiding categories of events. + See related functions. + */ + QStringList categoryList(); + + enum { HideRecurring = 1, HideCompleted = 2, ShowCategories = 4 ,ShowPublic = 8, ShowPrivate = 16, ShowConfidential = 32 }; + + /** + Set criteria, which have to be fulfilled by events passing the filter. + */ + void setCriteria(int); + /** + Get inclusive filter criteria. + */ + int criteria(); + + private: + QString mName; + + int mCriteria; + + bool mEnabled; + + QStringList mCategoryList; +}; + +} + +#endif /* _CALFILTER_H */ diff --git a/libkcal/calformat.cpp b/libkcal/calformat.cpp new file mode 100644 index 0000000..8a3d069 --- a/dev/null +++ b/libkcal/calformat.cpp @@ -0,0 +1,98 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <klocale.h> +#include <kdebug.h> +#include <kapplication.h> + +#include "calformat.h" + +using namespace KCal; + +QString CalFormat::mApplication = QString::fromLatin1("libkcal"); +QString CalFormat::mProductId = QString::fromLatin1("-//K Desktop Environment//NONSGML libkcal 3.1//EN"); + +// An array containing the PRODID strings indexed against the calendar file format version used. +// Every time the calendar file format is changed, add an entry/entries to this list. +struct CalVersion { + int version; + QString prodId; +}; +static CalVersion prodIds[] = { + { 220, QString::fromLatin1("-//K Desktop Environment//NONSGML KOrganizer 2.2//EN") }, + { 300, QString::fromLatin1("-//K Desktop Environment//NONSGML KOrganizer 3.0//EN") }, + { 310, QString::fromLatin1("-//K Desktop Environment//NONSGML KOrganizer 3.1//EN") }, + { 0 , QString() } +}; + + +CalFormat::CalFormat() +{ + mException = 0; +} + +CalFormat::~CalFormat() +{ + delete mException; +} + +void CalFormat::clearException() +{ + delete mException; + mException = 0; +} + +void CalFormat::setException(ErrorFormat *exception) +{ + delete mException; + mException = exception; +} + +ErrorFormat *CalFormat::exception() +{ + return mException; +} + +void CalFormat::setApplication(const QString& application, const QString& productID) +{ + mApplication = application; + mProductId = productID; +} + +QString CalFormat::createUniqueId() +{ + int hashTime = QTime::currentTime().hour() + + QTime::currentTime().minute() + QTime::currentTime().second() + + QTime::currentTime().msec(); + QString uidStr = QString("%1-%2.%3") + .arg(mApplication) + .arg(KApplication::random()) + .arg(hashTime); + return uidStr; +} + +int CalFormat::calendarVersion(const char* prodId) +{ + for (const CalVersion* cv = prodIds; cv->version; ++cv) { + if (!strcmp(prodId, cv->prodId.local8Bit())) + return cv->version; + } + return 0; +} diff --git a/libkcal/calformat.h b/libkcal/calformat.h new file mode 100644 index 0000000..0c7ee7e --- a/dev/null +++ b/libkcal/calformat.h @@ -0,0 +1,111 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef _CALFORMAT_H +#define _CALFORMAT_H + +#include <qstring.h> +#include <qdatetime.h> +#include <qevent.h> + +#include "exceptions.h" +#include "event.h" + +namespace KCal { + +class VCalDrag; +class Calendar; + +/** + This is the base class for calendar formats. It provides an interface for the + generation/interpretation of a textual representation of a calendar. + + @short Class providing in interface to a calendar format +*/ +class CalFormat { + public: + /** Constructs a new format. */ + CalFormat(); + /** Destruct calendar format. */ + virtual ~CalFormat(); + + /** + loads a calendar on disk into the calendar associated with this format. + Returns TRUE if successful,else returns FALSE. + @param fileName the name of the calendar on disk. + */ + virtual bool load(Calendar *, const QString &fileName) = 0; + /** writes out the calendar to disk. Returns true if + * successful and false on error. + * @param fileName the name of the file + */ + virtual bool save(Calendar *, const QString &fileName) = 0; + + /** + Parse string and populate calendar with that information. + */ + virtual bool fromString(Calendar *, const QString & ) = 0; + /** + Return calendar information as string. + */ + virtual QString toString(Calendar *) = 0; + + /** Clear exception status of this format object */ + void clearException(); + /** + Return exception, if there is any, containing information about the last + error that occured. + */ + ErrorFormat *exception(); + + /** Set the application name for use in unique IDs and error messages, + * and product ID for incidence PRODID property + */ + static void setApplication(const QString& app, const QString& productID); + /** Return the application name used in unique IDs and error messages */ + static const QString& application() { return mApplication; } + /** Return the PRODID string to write into calendar files */ + static const QString& productId() { return mProductId; } + /** Return the KDE calendar format version indicated by a PRODID property */ + static int calendarVersion(const char* prodId); + /** Return the PRODID string loaded from calendar file */ + const QString &loadedProductId() { return mLoadedProductId; } + + /** Create a unique id string. */ + static QString createUniqueId(); + + /** + Set exception for this object. This is used by the functions of this + class to report errors. + */ + void setException(ErrorFormat *error); + + protected: + QString mLoadedProductId; // PRODID string loaded from calendar file + + private: + ErrorFormat *mException; + + static QString mApplication; // name of application for unique ID strings + static QString mProductId; // PRODID string to write to calendar files +}; + +} + +#endif diff --git a/libkcal/calstorage.h b/libkcal/calstorage.h new file mode 100644 index 0000000..72972ea --- a/dev/null +++ b/libkcal/calstorage.h @@ -0,0 +1,52 @@ +/* + This file is part of libkcal. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_CALSTORAGE_H +#define KCAL_CALSTORAGE_H + +namespace KCal { + +class Calendar; + +/** + This class provides the interface to the storage of a calendar. +*/ +class CalStorage +{ + public: + CalStorage( Calendar *calendar ) + { + mCalendar = calendar; + } + virtual ~CalStorage() {} + + Calendar *calendar() const { return mCalendar; } + + virtual bool open() = 0; + virtual bool load(bool = false ) = 0; + virtual bool save() = 0; + virtual bool close() = 0; + + private: + Calendar *mCalendar; +}; + +} + +#endif diff --git a/libkcal/compat.cpp b/libkcal/compat.cpp new file mode 100644 index 0000000..070e082 --- a/dev/null +++ b/libkcal/compat.cpp @@ -0,0 +1,37 @@ +/* + This file is part of libkcal. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "compat.h" + +#include <kdebug.h> + +#include <qregexp.h> + +using namespace KCal; + +Compat *CompatFactory::createCompat( const QString & ) +{ + return new Compat; +} + +void CompatPre31::fixFloatingEnd( QDate &endDate ) +{ + endDate = endDate.addDays( 1 ); +} diff --git a/libkcal/compat.h b/libkcal/compat.h new file mode 100644 index 0000000..42d44fa --- a/dev/null +++ b/libkcal/compat.h @@ -0,0 +1,53 @@ +/* + This file is part of libkcal. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_COMPAT_H +#define KCAL_COMPAT_H + +#include <qstring.h> +#include <qdatetime.h> + +namespace KCal { + +class Compat; + +class CompatFactory +{ + public: + static Compat *createCompat( const QString &productId ); +}; + +class Compat +{ + public: + Compat() {}; + virtual ~Compat() {}; + + virtual void fixFloatingEnd( QDate & ) {} +}; + +class CompatPre31 : public Compat +{ + public: + void fixFloatingEnd( QDate & ); +}; + +} + +#endif diff --git a/libkcal/customproperties.cpp b/libkcal/customproperties.cpp new file mode 100644 index 0000000..adc1710 --- a/dev/null +++ b/libkcal/customproperties.cpp @@ -0,0 +1,114 @@ +/* + This file is part of libkcal. + Copyright (c) 2002 David Jarvie <software@astrojar.org.uk> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "customproperties.h" + +using namespace KCal; + +CustomProperties::CustomProperties() +{ +} + +CustomProperties::CustomProperties(const CustomProperties &cp) + : mProperties(cp.mProperties) +{ +} + +CustomProperties::~CustomProperties() +{ +} + +void CustomProperties::setCustomProperty(const QCString &app, const QCString &key, + const QString &value) +{ + if (value.isNull() || key.isEmpty() || app.isEmpty()) + return; + QCString property = "X-KDE-" + app + "-" + key; + if (!checkName(property)) + return; + mProperties[property] = value; +} + +void CustomProperties::removeCustomProperty(const QCString &app, const QCString &key) +{ + removeNonKDECustomProperty(QCString("X-KDE-" + app + "-" + key)); +} + +QString CustomProperties::customProperty(const QCString &app, const QCString &key) const +{ + return nonKDECustomProperty(QCString("X-KDE-" + app + "-" + key)); +} + +void CustomProperties::setNonKDECustomProperty(const QCString &name, const QString &value) +{ + if (value.isNull() || !checkName(name)) + return; + mProperties[name] = value; +} + +void CustomProperties::removeNonKDECustomProperty(const QCString &name) +{ + QMap<QCString, QString>::Iterator it = mProperties.find(name); + if (it != mProperties.end()) + mProperties.remove(it); +} + +QString CustomProperties::nonKDECustomProperty(const QCString &name) const +{ + QMap<QCString, QString>::ConstIterator it = mProperties.find(name); + if (it == mProperties.end()) + return QString::null; + return it.data(); +} + +void CustomProperties::setCustomProperties(const QMap<QCString, QString> &properties) +{ + for (QMap<QCString, QString>::ConstIterator it = properties.begin(); it != properties.end(); ++it) { + // Validate the property name and convert any null string to empty string + if (checkName(it.key())) { + mProperties[it.key()] = it.data().isNull() ? QString("") : it.data(); + } + } +} + +QMap<QCString, QString> CustomProperties::customProperties() const +{ + return mProperties; +} + +bool CustomProperties::checkName(const QCString &name) +{ + // Check that the property name starts with 'X-' and contains + // only the permitted characters + const char* n = name; + int len = name.length(); + if (len < 2 || n[0] != 'X' || n[1] != '-') + return false; + for (int i = 2; i < len; ++i) { + char ch = n[i]; + if (ch >= 'A' && ch <= 'Z' + || ch >= 'a' && ch <= 'z' + || ch >= '0' && ch <= '9' + || ch == '-') + continue; + return false; // invalid character found + } + return true; +} diff --git a/libkcal/customproperties.h b/libkcal/customproperties.h new file mode 100644 index 0000000..0cbfdcd --- a/dev/null +++ b/libkcal/customproperties.h @@ -0,0 +1,97 @@ +/* + This file is part of libkcal. + Copyright (c) 2002 David Jarvie <software@astrojar.org.uk> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KCAL_CUSTOM_PROPERTIES_H +#define KCAL_CUSTOM_PROPERTIES_H + +#include <qstring.h> +#include <qmap.h> + +namespace KCal { + +/** + This class represents custom calendar properties. + It is used as a base class for classes which represent calendar components. + A custom property name written by libkcal has the form X-KDE-APP-KEY where + APP represents the application name, and KEY distinguishes individual + properties for the application. + In keeping with RFC2445, property names must be composed only of the + characters A-Z, a-z, 0-9 and '-'. +*/ +class CustomProperties +{ + public: + /** Construct a new empty custom properties instance */ + CustomProperties(); + CustomProperties(const CustomProperties &); + ~CustomProperties(); + + /** Create or modify a custom calendar property. + @param app Application name as it appears in the custom property name. + @param key Property identifier specific to the application. + @param value The property's value. A call with a value of QString::null + will be ignored. + */ + void setCustomProperty(const QCString &app, const QCString &key, + const QString &value); + /** Delete a custom calendar property. + @param app Application name as it appears in the custom property name. + @param key Property identifier specific to the application. + */ + void removeCustomProperty(const QCString &app, const QCString &key); + /** Return the value of a custom calendar property. + @param app Application name as it appears in the custom property name. + @param key Property identifier specific to the application. + @return Property value, or QString::null if (and only if) the property does not exist. + */ + QString customProperty(const QCString &app, const QCString &key) const; + + /** Create or modify a non-KDE or non-standard custom calendar property. + @param name Full property name + @param value The property's value. A call with a value of QString::null + will be ignored. + */ + void setNonKDECustomProperty(const QCString &name, const QString &value); + /** Delete a non-KDE or non-standard custom calendar property. + @param name Full property name + */ + void removeNonKDECustomProperty(const QCString &name); + /** Return the value of a non-KDE or non-standard custom calendar property. + @param name Full property name + @return Property value, or QString::null if (and only if) the property does not exist. + */ + QString nonKDECustomProperty(const QCString& name) const; + + /** Initialise the alarm's custom calendar properties to the specified + key/value pairs. + */ + void setCustomProperties(const QMap<QCString, QString> &properties); + /** Return all custom calendar property key/value pairs. */ + QMap<QCString, QString> customProperties() const; + + private: + static bool checkName(const QCString& name); + + QMap<QCString, QString> mProperties; // custom calendar properties +}; + +} + +#endif diff --git a/libkcal/dndfactory.h b/libkcal/dndfactory.h new file mode 100644 index 0000000..6b73f34 --- a/dev/null +++ b/libkcal/dndfactory.h @@ -0,0 +1,62 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001,2002 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// $Id$ + +#ifndef KCAL_DNDFACTORY_H +#define KCAL_DNDFACTORY_H + +#include "vcalformat.h" + +class QDropEvent; + +namespace KCal { + +/** + This class implements functions to create Drag and Drop objects used for + Drag-and-Drop and Copy-and-Paste. + + @short vCalendar Drag-and-Drop object factory. +*/ +class DndFactory { + public: + DndFactory( Calendar * ) {} + + /** create an object to be used with the Xdnd Drag And Drop protocol. */ + ICalDrag *createDrag(Event *, QWidget *) { return 0; } + /** create an object to be used with the Xdnd Drag And Drop protocol. */ + ICalDrag *createDragTodo(Todo *, QWidget *) { return 0; } + /** Create Todo object from drop event */ + Todo *createDropTodo(QDropEvent *) { return 0; } + /** Create Event object from drop event */ + Event *createDrop(QDropEvent *) { return 0; } + + /** cut event to clipboard */ + void cutEvent(Event *) {} + /** cut, copy, and paste operations follow. */ + bool copyEvent(Event *) { return false; } + /** pastes the event and returns a pointer to the new event pasted. */ + Event *pasteEvent(const QDate &, const QTime *newTime = 0) { return 0; } +}; + +} + +#endif diff --git a/libkcal/dummyscheduler.cpp b/libkcal/dummyscheduler.cpp new file mode 100644 index 0000000..ae40e6d --- a/dev/null +++ b/libkcal/dummyscheduler.cpp @@ -0,0 +1,119 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// +// DummyScheduler - iMIP implementation of iTIP methods +// + +#include <qfile.h> +#include <qtextstream.h> + +#include <kdebug.h> + +#include "event.h" +#include "icalformat.h" + +#include "dummyscheduler.h" + +using namespace KCal; + +DummyScheduler::DummyScheduler(Calendar *calendar) + : Scheduler(calendar) +{ +} + +DummyScheduler::~DummyScheduler() +{ +} + +bool DummyScheduler::publish (IncidenceBase *incidence,const QString &recipients) +{ + QString messageText = mFormat->createScheduleMessage(incidence, + Scheduler::Publish); + + return saveMessage(messageText); +} + +bool DummyScheduler::performTransaction(IncidenceBase *incidence,Method method,const QString &recipients) +{ + QString messageText = mFormat->createScheduleMessage(incidence,method); + + return saveMessage(messageText); +} + +bool DummyScheduler::performTransaction(IncidenceBase *incidence,Method method) +{ + QString messageText = mFormat->createScheduleMessage(incidence,method); + + return saveMessage(messageText); +} + +bool DummyScheduler::saveMessage(const QString &message) +{ + QFile f("dummyscheduler.store"); + if (f.open(IO_WriteOnly | IO_Append)) { + QTextStream t(&f); + t << message << endl; + f.close(); + return true; + } else { + return false; + } +} + +QPtrList<ScheduleMessage> DummyScheduler::retrieveTransactions() +{ + QPtrList<ScheduleMessage> messageList; + + QFile f("dummyscheduler.store"); + if (!f.open(IO_ReadOnly)) { + kdDebug(5800) << "DummyScheduler::retrieveTransactions(): Can't open file" + << endl; + } else { + QTextStream t(&f); + QString messageString; + QString messageLine = t.readLine(); + while (!messageLine.isNull()) { +// kdDebug(5800) << "++++++++" << messageLine << endl; + messageString += messageLine + "\n"; + if (messageLine.find("END:VCALENDAR") >= 0) { + kdDebug(5800) << "---------------" << messageString << endl; + ScheduleMessage *message = mFormat->parseScheduleMessage(mCalendar, + messageString); + kdDebug(5800) << "--Parsed" << endl; + if (message) { + messageList.append(message); + } else { + QString errorMessage; + if (mFormat->exception()) { + errorMessage = mFormat->exception()->message(); + } + kdDebug(5800) << "DummyScheduler::retrieveTransactions() Error parsing " + "message: " << errorMessage << endl; + } + messageString=""; + } + messageLine = t.readLine(); + } + f.close(); + } + + return messageList; +} diff --git a/libkcal/dummyscheduler.h b/libkcal/dummyscheduler.h new file mode 100644 index 0000000..df42153 --- a/dev/null +++ b/libkcal/dummyscheduler.h @@ -0,0 +1,51 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef DUMMYSCHEDULER_H +#define DUMMYSCHEDULER_H +// +// Dummy implementation of iTIP methods +// + +#include "scheduler.h" + +namespace KCal { + +/** + This class implements the iTIP interface as a primitive local version for + testing. It uses a file dummyscheduler.store as inbox/outbox. +*/ +class DummyScheduler : public Scheduler { + public: + DummyScheduler(Calendar *); + virtual ~DummyScheduler(); + + bool publish (IncidenceBase *incidence,const QString &recipients); + bool performTransaction(IncidenceBase *incidence,Method method); + bool performTransaction(IncidenceBase *incidence,Method method,const QString &recipients); + QPtrList<ScheduleMessage> retrieveTransactions(); + + protected: + bool saveMessage(const QString &); +}; + +} + +#endif // DUMMYSCHEDULER_H + diff --git a/libkcal/duration.cpp b/libkcal/duration.cpp new file mode 100644 index 0000000..3d57136 --- a/dev/null +++ b/libkcal/duration.cpp @@ -0,0 +1,59 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> +#include <klocale.h> + +#include "duration.h" + +using namespace KCal; + +Duration::Duration() +{ + mSeconds = 0; +} + +Duration::Duration( const QDateTime &start, const QDateTime &end ) +{ + mSeconds = start.secsTo( end ); +} + +Duration::Duration( int seconds ) +{ + mSeconds = seconds; +} + + +bool KCal::operator==( const Duration& d1, const Duration& d2 ) +{ + return ( d1.asSeconds() == d2.asSeconds() ); +} + + + +QDateTime Duration::end( const QDateTime &start ) const +{ + return start.addSecs( mSeconds ); +} + +int Duration::asSeconds() const +{ + return mSeconds; +} diff --git a/libkcal/duration.h b/libkcal/duration.h new file mode 100644 index 0000000..81274dd --- a/dev/null +++ b/libkcal/duration.h @@ -0,0 +1,48 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_DURATION_H +#define KCAL_DURATION_H + +#include <qdatetime.h> + +namespace KCal { + +class Duration +{ + public: + Duration(); + Duration( const QDateTime &start, const QDateTime &end ); + Duration( int seconds ); + + QDateTime end( const QDateTime &start ) const; + + int asSeconds() const; + + private: + int mSeconds; +}; + + bool operator==( const Duration&, const Duration& ); + inline bool operator!=( const Duration &d1, const Duration &d2 ) + { return !operator==( d1, d2 ); } + +} + +#endif diff --git a/libkcal/event.cpp b/libkcal/event.cpp new file mode 100644 index 0000000..dd67252 --- a/dev/null +++ b/libkcal/event.cpp @@ -0,0 +1,178 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +#include "event.h" + +using namespace KCal; + +Event::Event() : + mHasEndDate( false ), mTransparency( Opaque ) +{ +} + +Event::Event(const Event &e) : Incidence(e) +{ + mDtEnd = e.mDtEnd; + mHasEndDate = e.mHasEndDate; + mTransparency = e.mTransparency; +} + +Event::~Event() +{ +} + +Incidence *Event::clone() +{ + kdDebug(5800) << "Event::clone()" << endl; + return new Event(*this); +} + +bool KCal::operator==( const Event& e1, const Event& e2 ) +{ + return operator==( (const Incidence&)e1, (const Incidence&)e2 ) && + e1.dtEnd() == e2.dtEnd() && + e1.hasEndDate() == e2.hasEndDate() && + e1.transparency() == e2.transparency(); +} + + + +void Event::setDtEnd(const QDateTime &dtEnd) +{ + if (mReadOnly) return; + + mDtEnd = getEvenTime( dtEnd ); + + setHasEndDate(true); + setHasDuration(false); + + updated(); +} + +QDateTime Event::dtEnd() const +{ + if (hasEndDate()) return mDtEnd; + if (hasDuration()) return dtStart().addSecs(duration()); + + kdDebug(5800) << "Warning! Event '" << summary() + << "' does have neither end date nor duration." << endl; + return dtStart(); +} + +QString Event::dtEndTimeStr() const +{ + return KGlobal::locale()->formatTime(mDtEnd.time()); +} + +QString Event::dtEndDateStr(bool shortfmt) const +{ + return KGlobal::locale()->formatDate(mDtEnd.date(),shortfmt); +} + +QString Event::dtEndStr(bool shortfmt) const +{ + return KGlobal::locale()->formatDateTime(mDtEnd, shortfmt); +} + +void Event::setHasEndDate(bool b) +{ + mHasEndDate = b; +} + +bool Event::hasEndDate() const +{ + return mHasEndDate; +} + +bool Event::isMultiDay() const +{ + bool multi = !(dtStart().date() == dtEnd().date()); + return multi; +} + +void Event::setTransparency(Event::Transparency transparency) +{ + if (mReadOnly) return; + mTransparency = transparency; + updated(); +} + +Event::Transparency Event::transparency() const +{ + return mTransparency; +} + +void Event::setDuration(int seconds) +{ + setHasEndDate(false); + Incidence::setDuration(seconds); +} +QDateTime Event::getNextAlarmDateTime( bool * ok, int * offset ) const +{ + + bool yes; + QDateTime incidenceStart = getNextOccurence( QDateTime::currentDateTime(), &yes ); + if ( ! yes || cancelled() ) { + *ok = false; + return QDateTime (); + } + + bool enabled = false; + Alarm* alarm; + int off; + QDateTime alarmStart = QDateTime::currentDateTime().addDays( 3650 );; + // if ( QDateTime::currentDateTime() > incidenceStart ){ +// *ok = false; +// return incidenceStart; +// } + for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) { + if (alarm->enabled()) { + if ( alarm->hasTime () ) { + if ( alarm->time() < alarmStart ) { + alarmStart = alarm->time(); + enabled = true; + off = alarmStart.secsTo( incidenceStart ); + } + + } else { + int secs = alarm->startOffset().asSeconds(); + if ( incidenceStart.addSecs( secs ) < alarmStart ) { + alarmStart = incidenceStart.addSecs( secs ); + enabled = true; + off = -secs; + } + } + } + } + if ( enabled ) { + if ( alarmStart > QDateTime::currentDateTime() ) { + *ok = true; + * offset = off; + return alarmStart; + } + } + *ok = false; + return QDateTime (); + +} diff --git a/libkcal/event.h b/libkcal/event.h new file mode 100644 index 0000000..2a8bd95 --- a/dev/null +++ b/libkcal/event.h @@ -0,0 +1,88 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef EVENT_H +#define EVENT_H +// +// Event component, representing a VEVENT object +// + +#include "incidence.h" +namespace KCal { + +/** + This class provides an Event in the sense of RFC2445. +*/ +class Event : public Incidence +{ + public: + enum Transparency { Opaque, Transparent }; + typedef ListBase<Event> List; + Event(); + Event(const Event &); + ~Event(); + + QCString type() const { return "Event"; } + + Incidence *clone(); + QDateTime getNextAlarmDateTime( bool * ok, int * offset ) const; + + /** for setting an event's ending date/time with a QDateTime. */ + void setDtEnd(const QDateTime &dtEnd); + /** Return the event's ending date/time as a QDateTime. */ + virtual QDateTime dtEnd() const; + /** returns an event's end time as a string formatted according to the + users locale settings */ + QString dtEndTimeStr() const; + /** returns an event's end date as a string formatted according to the + users locale settings */ + QString dtEndDateStr(bool shortfmt=true) const; + /** returns an event's end date and time as a string formatted according + to the users locale settings */ + QString dtEndStr(bool shortfmt=true) const; + void setHasEndDate(bool); + /** Return whether the event has an end date/time. */ + bool hasEndDate() const; + + /** Return true if the event spans multiple days, otherwise return false. */ + bool isMultiDay() const; + + /** set the event's time transparency level. */ + void setTransparency(Transparency transparency); + /** get the event's time transparency level. */ + Transparency transparency() const; + + void setDuration(int seconds); + + private: + bool accept(Visitor &v) { return v.visit(this); } + + QDateTime mDtEnd; + bool mHasEndDate; + Transparency mTransparency; +}; + +bool operator==( const Event&, const Event& ); + + +} + + +#endif diff --git a/libkcal/exceptions.cpp b/libkcal/exceptions.cpp new file mode 100644 index 0000000..bc298f9 --- a/dev/null +++ b/libkcal/exceptions.cpp @@ -0,0 +1,90 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <klocale.h> + +#include "calformat.h" +#include "exceptions.h" + +using namespace KCal; + +Exception::Exception(const QString &message) +{ + mMessage = message; +} + +Exception::~Exception() +{ +} + +QString Exception::message() +{ + if (mMessage.isEmpty()) return i18n("%1 Error").arg(CalFormat::application()); + else return mMessage; +} + + +ErrorFormat::ErrorFormat(ErrorCodeFormat code,const QString &message) : + Exception(message) +{ + mCode = code; +} + +QString ErrorFormat::message() +{ + QString message = ""; + + switch (mCode) { + case LoadError: + message = i18n("Load Error"); + break; + case SaveError: + message = i18n("Save Error"); + break; + case ParseErrorIcal: + message = i18n("Parse Error in libical"); + break; + case ParseErrorKcal: + message = i18n("Parse Error in libkcal"); + break; + case NoCalendar: + message = i18n("No calendar component found."); + break; + case CalVersion1: + message = i18n("vCalendar Version 1.0 detected."); + break; + case CalVersion2: + message = i18n("iCalendar Version 2.0 detected."); + break; + case Restriction: + message = i18n("Restriction violation"); + default: + break; + } + + if (!mMessage.isEmpty()) message += ": " + mMessage; + + return message; +} + +ErrorFormat::ErrorCodeFormat ErrorFormat::errorCode() +{ + return mCode; +} diff --git a/libkcal/exceptions.h b/libkcal/exceptions.h new file mode 100644 index 0000000..4b75df8 --- a/dev/null +++ b/libkcal/exceptions.h @@ -0,0 +1,75 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KCAL_EXCEPTIONS_H +#define KCAL_EXCEPTIONS_H +// +// Exception classes of libkcal. +// +// We don't use actual C++ exceptions right now. These classes are currently +// returned by an error function, but we can build upon them, when we start +// to use C++ exceptions. + +#include <qstring.h> + +namespace KCal { + +/** + KOrganizer exceptions base class. This is currently used as a fancy kind of error code not as an + C++ exception. +*/ +class Exception { + public: + /** Construct exception with descriptive message \a message. */ + Exception(const QString &message=QString::null); + virtual ~Exception(); + + /** Return descriptive message of exception. */ + virtual QString message(); + + protected: + QString mMessage; +}; + +/** Calendar format related error class */ +class ErrorFormat : public Exception { + public: + enum ErrorCodeFormat { LoadError, SaveError, + ParseErrorIcal, ParseErrorKcal, + NoCalendar, + CalVersion1,CalVersion2, + CalVersionUnknown, + Restriction }; + + /** Create format error exception. */ + ErrorFormat(ErrorCodeFormat code,const QString &message = QString::null); + + /** Return format error message. */ + QString message(); + /** Return format error code. */ + ErrorCodeFormat errorCode(); + + private: + ErrorCodeFormat mCode; +}; + +} + +#endif diff --git a/libkcal/filestorage.cpp b/libkcal/filestorage.cpp new file mode 100644 index 0000000..00c15d9 --- a/dev/null +++ b/libkcal/filestorage.cpp @@ -0,0 +1,140 @@ +/* + This file is part of libkcal. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <stdlib.h> + +#include <qdatetime.h> +#include <qstring.h> +#include <qptrlist.h> + +#include <kdebug.h> + +#include "calendar.h" +#include "vcaldrag.h" +#include "vcalformat.h" +#include "icalformat.h" + +#include "filestorage.h" + +using namespace KCal; + +FileStorage::FileStorage( Calendar *cal, const QString &fileName, + CalFormat *format ) + : CalStorage( cal ), + mFileName( fileName ), + mSaveFormat( format ) +{ +} + +FileStorage::~FileStorage() +{ + delete mSaveFormat; +} + +void FileStorage::setFileName( const QString &fileName ) +{ + mFileName = fileName; +} + +QString FileStorage::fileName()const +{ + return mFileName; +} + + +void FileStorage::setSaveFormat( CalFormat *format ) +{ + delete mSaveFormat; + mSaveFormat = format; +} + +CalFormat *FileStorage::saveFormat()const +{ + return mSaveFormat; +} + + +bool FileStorage::open() +{ + return true; +} + +bool FileStorage::load( bool quick ) +{ + kdDebug(5800) << "FileStorage::load(): '" << mFileName << "'" << endl; + + // do we want to silently accept this, or make some noise? Dunno... + // it is a semantical thing vs. a practical thing. + if (mFileName.isEmpty()) return false; + + // Always try to load with iCalendar. It will detect, if it is actually a + // vCalendar file. + ICalFormat iCal (quick ); + + bool success = iCal.load( calendar(), mFileName); + + if ( !success ) { + if ( iCal.exception() ) { +// kdDebug(5800) << "---Error: " << mFormat->exception()->errorCode() << endl; + if ( iCal.exception()->errorCode() == ErrorFormat::CalVersion1 ) { + // Expected non vCalendar file, but detected vCalendar + kdDebug(5800) << "FileStorage::load() Fallback to VCalFormat" << endl; + VCalFormat vCal; + success = vCal.load( calendar(), mFileName ); + calendar()->setLoadedProductId( vCal.productId() ); + } else { + return false; + } + } else { + kdDebug(5800) << "Warning! There should be set an exception." << endl; + return false; + } + } else { +// kdDebug(5800) << "---Success" << endl; + calendar()->setLoadedProductId( iCal.loadedProductId() ); + } + + calendar()->setModified( false ); + + return true; +} + +bool FileStorage::save() +{ + if ( mFileName.isEmpty() ) return false; + + bool success; + + if ( mSaveFormat ) { + success = mSaveFormat->save( calendar(), mFileName); + } else { + ICalFormat iCal; + success = iCal.save( calendar(), mFileName); + } + + if ( success ) calendar()->setModified( false ); + + return success; +} + +bool FileStorage::close() +{ + return true; +} diff --git a/libkcal/filestorage.h b/libkcal/filestorage.h new file mode 100644 index 0000000..e9dc15e --- a/dev/null +++ b/libkcal/filestorage.h @@ -0,0 +1,58 @@ +/* + This file is part of libkcal. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_FILESTORAGE_H +#define KCAL_FILESTORAGE_H + +#include "calstorage.h" + +namespace KCal { + +/** + This class provides a calendar storage as a local file. +*/ +class FileStorage : public CalStorage +{ + public: + FileStorage( Calendar *, const QString &fileName = QString::null, + CalFormat *format = 0 ); + virtual ~FileStorage(); + + void setFileName( const QString &mFileName ); + QString fileName()const; + + /** + FileStorage takes ownership of format object. + */ + void setSaveFormat( CalFormat * ); + CalFormat *saveFormat()const; + + bool open(); + bool load(bool quick = false ); + bool save(); + bool close(); + + private: + QString mFileName; + CalFormat *mSaveFormat; +}; + +} + +#endif diff --git a/libkcal/freebusy.cpp b/libkcal/freebusy.cpp new file mode 100644 index 0000000..ba15d6d --- a/dev/null +++ b/libkcal/freebusy.cpp @@ -0,0 +1,184 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> + +#include "freebusy.h" + +using namespace KCal; + +FreeBusy::FreeBusy() +{ +} + +FreeBusy::FreeBusy(const QDateTime &start, const QDateTime &end) +{ + setDtStart(start); + setDtEnd(end); +} + +FreeBusy::FreeBusy( Calendar *calendar, const QDateTime &start, const QDateTime &end ) +{ + kdDebug() << "FreeBusy::FreeBusy" << endl; + mCalendar = calendar; + + setDtStart(start); + setDtEnd(end); + + //Gets all the events in the calendar + QPtrList<Event> eventList = mCalendar->events(); + Event *event; + + int extraDays, i, x, duration; + duration = start.daysTo(end); + QDate day; + QDateTime tmpStart; + QDateTime tmpEnd; + //Loops through every event in the calendar + for( event = eventList.first(); event; event = eventList.next() ) { + //This whole for loop is for recurring events, it loops through + //each of the days of the freebusy request + + //First check if this is transparent. If it is, it shouldn't be in the + //freebusy list + if ( event->transparency() == Event::Transparent ) + // Transparent + continue; + + for(i=0; i<=duration; i++) { + day=(start.addDays(i).date()); + tmpStart.setDate(day); + tmpEnd.setDate(day); + + if( (*(event->recurrence())).doesRecur() ) { + if ( event->isMultiDay() ) { + extraDays = event->dtStart().date().daysTo(event->dtEnd().date()); + for (x=0; x<=extraDays; x++) { + if ( event->recursOn(day.addDays(-x))) { + tmpStart.setDate(day.addDays(-x)); + tmpStart.setTime(event->dtStart().time()); + tmpEnd=tmpStart.addSecs( (event->duration()) ); + + addLocalPeriod( tmpStart, tmpEnd ); + break; + } + } + } else { + if (event->recursOn(day)) { + tmpStart.setTime(event->dtStart().time()); + tmpEnd.setTime(event->dtEnd().time()); + + addLocalPeriod (tmpStart, tmpEnd); + } + } + } + + } + //Non-reocurring events + addLocalPeriod(event->dtStart(), event->dtEnd()); + } + + sortList(); +} + +FreeBusy::~FreeBusy() +{ +} + +bool FreeBusy::setDtEnd( const QDateTime &end ) +{ + mDtEnd = end; + return true; +} + +QDateTime FreeBusy::dtEnd() const +{ + return mDtEnd; +} + +QValueList<Period> FreeBusy::busyPeriods() const +{ + return mBusyPeriods; +} + +bool FreeBusy::addLocalPeriod(const QDateTime &eventStart, const QDateTime &eventEnd ) { + QDateTime tmpStart; + QDateTime tmpEnd; + + //Check to see if the start *or* end of the event is + //between the start and end of the freebusy dates. + if (!((((this->dtStart()).secsTo(eventStart)>=0)&&(eventStart.secsTo(this->dtEnd())>=0)) + ||(((this->dtStart()).secsTo(eventEnd) >= 0)&&(eventEnd.secsTo(this->dtEnd()) >= 0)))) + return false; + + if ( eventStart.secsTo(this->dtStart())>=0) { + tmpStart = this->dtStart(); + } else { + tmpStart = eventStart; + } + + if ( eventEnd.secsTo(this->dtEnd())<=0 ) { + tmpEnd = this->dtEnd(); + } else { + tmpEnd = eventEnd; + } + + Period p(tmpStart, tmpEnd); + mBusyPeriods.append( p ); + + return true; +} + +FreeBusy::FreeBusy(QValueList<Period> busyPeriods) +{ + mBusyPeriods = busyPeriods; +} + +void FreeBusy::sortList() +{ + typedef QValueList<Period> PeriodList; + + PeriodList::Iterator tmpPeriod, earlyPeriod; + PeriodList sortedList; + QDateTime earlyTime; + + while( mBusyPeriods.count() > 0 ) { + earlyTime=(*mBusyPeriods.begin()).start(); + for (tmpPeriod=mBusyPeriods.begin(); tmpPeriod!=mBusyPeriods.end(); tmpPeriod++) { + if (earlyTime.secsTo((*tmpPeriod).start()) <= 0) { + earlyTime=(*tmpPeriod).start(); + earlyPeriod=tmpPeriod; + } + } + //Move tmpPeriod to sortedList + Period tmpPeriod( (*earlyPeriod).start(), (*earlyPeriod).end() ); + sortedList.append( tmpPeriod ); + mBusyPeriods.remove( earlyPeriod ); + } + mBusyPeriods=sortedList; +} + +void FreeBusy::addPeriod(const QDateTime &start, const QDateTime &end) +{ + Period p(start, end); + mBusyPeriods.append( p ); + + sortList(); +} diff --git a/libkcal/freebusy.h b/libkcal/freebusy.h new file mode 100644 index 0000000..054feda --- a/dev/null +++ b/libkcal/freebusy.h @@ -0,0 +1,72 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_FREEBUSY_H +#define KCAL_FREEBUSY_H +// +// FreeBusy - information about free/busy times +// + +#include <qdatetime.h> +#include <qvaluelist.h> +#include <qptrlist.h> + +#include "period.h" +#include "calendar.h" + +#include "incidencebase.h" + +namespace KCal { + +/** + This class provides information about free/busy time of a calendar user. +*/ +class FreeBusy : public IncidenceBase +{ + public: + FreeBusy(); + FreeBusy(const QDateTime &start, const QDateTime &end); + FreeBusy(Calendar *calendar, const QDateTime &start, const QDateTime &end); + FreeBusy(QValueList<Period> busyPeriods); + + ~FreeBusy(); + + QCString type() const { return "FreeBusy"; } + + virtual QDateTime dtEnd() const; + bool setDtEnd( const QDateTime &end ); + + QValueList<Period> busyPeriods() const; + + void addPeriod(const QDateTime &start, const QDateTime &end); + void sortList(); + + private: + + //This is used for creating a freebusy object for the current user + bool addLocalPeriod(const QDateTime &start, const QDateTime &end); + + QDateTime mDtEnd; + QValueList<Period> mBusyPeriods; + Calendar *mCalendar; +}; + +} + +#endif diff --git a/libkcal/icaldrag.cpp b/libkcal/icaldrag.cpp new file mode 100644 index 0000000..446a115 --- a/dev/null +++ b/libkcal/icaldrag.cpp @@ -0,0 +1,58 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "icaldrag.h" + +#include "icalformat.h" + +#include <kdebug.h> + +using namespace KCal; + +ICalDrag::ICalDrag( Calendar *cal, QWidget *parent, const char *name ) + : QStoredDrag( "text/calendar", parent, name ) +{ + ICalFormat icf; + QString scal = icf.toString( cal ); + + setEncodedData( scal.utf8() ); +} + +bool ICalDrag::canDecode( QMimeSource *me ) +{ + return me->provides( "text/calendar" ); +} + +bool ICalDrag::decode( QMimeSource *de, Calendar *cal ) +{ + bool success = false; + + QByteArray payload = de->encodedData( "text/calendar" ); + if ( payload.size() ) { + QString txt = QString::fromUtf8( payload.data() ); + + ICalFormat icf; + success = icf.fromString( cal, txt ); + } + + return success; +} + diff --git a/libkcal/icaldrag.h b/libkcal/icaldrag.h new file mode 100644 index 0000000..fdf32b7 --- a/dev/null +++ b/libkcal/icaldrag.h @@ -0,0 +1,46 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef ICALDRAG_H +#define ICALDRAG_H + +#include <qdragobject.h> +#include "calendar.h" + +namespace KCal { + +/** iCalendar drag&drop class. */ +class ICalDrag : public QStoredDrag +{ + public: + /** Create a drag&drop object for iCalendar component \a ical. */ + ICalDrag( Calendar *cal, QWidget *parent = 0, const char *name = 0 ); + ~ICalDrag() {}; + + /** Return, if drag&drop object can be decode to iCalendar. */ + static bool canDecode( QMimeSource * ); + /** Decode drag&drop object to iCalendar component \a cal. */ + static bool decode( QMimeSource *e, Calendar *cal ); +}; + +} + +#endif diff --git a/libkcal/icalformat.cpp b/libkcal/icalformat.cpp new file mode 100644 index 0000000..5893db5 --- a/dev/null +++ b/libkcal/icalformat.cpp @@ -0,0 +1,478 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdatetime.h> +#include <qstring.h> +#include <qptrlist.h> +#include <qregexp.h> +#include <qclipboard.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qtextcodec.h> +#include <stdlib.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> + +extern "C" { + #include <ical.h> + #include <icalss.h> + #include <icalparser.h> + #include <icalrestriction.h> +} + +#include "calendar.h" +#include "calendarlocal.h" +#include "journal.h" + +#include "icalformat.h" +#include "icalformatimpl.h" + +#define _ICAL_VERSION "2.0" + +using namespace KCal; + +ICalFormat::ICalFormat(bool quick ) +{ + mQuicksave = false; //quick; + mImpl = new ICalFormatImpl( this ); + tzOffsetMin = 0; + //qDebug("new ICalFormat() "); +} + +ICalFormat::~ICalFormat() +{ + delete mImpl; + //qDebug("delete ICalFormat "); +} + +bool ICalFormat::load( Calendar *calendar, const QString &fileName) +{ + + clearException(); + + QFile file( fileName ); + if (!file.open( IO_ReadOnly ) ) { + setException(new ErrorFormat(ErrorFormat::LoadError)); + return false; + } + QTextStream ts( &file ); + QString text; +#if 0 + if ( !mQuicksave ) { + qDebug("KO: No quickload!"); + ts.setEncoding( QTextStream::Latin1 ); + text = ts.read(); + } else { + ts.setCodec( QTextCodec::codecForName("utf8") ); + text = ts.read(); + } +#endif + ts.setEncoding( QTextStream::Latin1 ); + text = ts.read(); + file.close(); + + return fromString( calendar, text ); +} + +//#include <qdatetime.h> +bool ICalFormat::save( Calendar *calendar, const QString &fileName ) +{ + //kdDebug(5800) << "ICalFormat::save(): " << fileName << endl; + //qDebug("ICalFormat::save "); + clearException(); + QString text = toString( calendar ); + //return false; + // qDebug("to string takes ms: %d ",is.elapsed() ); + if ( text.isNull() ) return false; + + // TODO: write backup file + //is.restart(); + QFile file( fileName ); + if (!file.open( IO_WriteOnly ) ) { + setException(new ErrorFormat(ErrorFormat::SaveError, + i18n("Could not open file '%1'").arg(fileName))); + return false; + } + QTextStream ts( &file ); + +// #ifdef DESKTOP_VERSION +// mQuicksave = false; +// #endif +// if ( mQuicksave ) { +// ts << text.utf8(); +// } else { +// ts.setEncoding( QTextStream::Latin1 ); +// ts << text; +// //ts << text.latin1(); +// } + ts.setEncoding( QTextStream::Latin1 ); + ts << text; + file.close(); + //qDebug("saving file takes ms: %d ", is.elapsed() ); + return true; +} + +bool ICalFormat::fromString( Calendar *cal, const QString &text ) +{ + setTimeZone( cal->timeZoneId(), !cal->isLocalTime() ); + // qDebug("ICalFormat::fromString tz: %s ", cal->timeZoneId().latin1()); + // Get first VCALENDAR component. + // TODO: Handle more than one VCALENDAR or non-VCALENDAR top components + icalcomponent *calendar; + + //calendar = icalcomponent_new_from_string( text.local8Bit().data()); + // good calendar = icalcomponent_new_from_string( text.utf8().data()); + calendar = icalcomponent_new_from_string( (char*)text.latin1()); + if (!calendar) { + setException(new ErrorFormat(ErrorFormat::ParseErrorIcal)); + return false; + } + + bool success = true; + + if (icalcomponent_isa(calendar) != ICAL_VCALENDAR_COMPONENT) { + setException(new ErrorFormat(ErrorFormat::NoCalendar)); + success = false; + } else { + // put all objects into their proper places + if ( !mImpl->populate( cal, calendar ) ) { + if ( !exception() ) { + setException(new ErrorFormat(ErrorFormat::ParseErrorKcal)); + } + success = false; + } else + mLoadedProductId = mImpl->loadedProductId(); + } + + icalcomponent_free( calendar ); + + return success; +} + +Incidence *ICalFormat::fromString( const QString &text ) +{ + CalendarLocal cal( mTimeZoneId ); + fromString(&cal, text); + + Incidence *ical = 0; + QPtrList<Event> elist = cal.events(); + if ( elist.count() > 0 ) { + ical = elist.first(); + } else { + QPtrList<Todo> tlist = cal.todos(); + if ( tlist.count() > 0 ) { + ical = tlist.first(); + } else { + QPtrList<Journal> jlist = cal.journals(); + if ( jlist.count() > 0 ) { + ical = jlist.first(); + } + } + } + return ical; +} +#include <qapp.h> + +QString ICalFormat::toString( Calendar *cal ) +{ + + setTimeZone( cal->timeZoneId(), !cal->isLocalTime() ); + + icalcomponent *calendar = mImpl->createCalendarComponent(cal); + + icalcomponent *component; + + // todos + QPtrList<Todo> todoList = cal->rawTodos(); + QPtrListIterator<Todo> qlt(todoList); + for (; qlt.current(); ++qlt) { + component = mImpl->writeTodo(qlt.current()); + icalcomponent_add_component(calendar,component); + //qDebug(" todos "); + qApp->processEvents(); + } + // events + QPtrList<Event> events = cal->rawEvents(); + Event *ev; + for(ev=events.first();ev;ev=events.next()) { + component = mImpl->writeEvent(ev); + icalcomponent_add_component(calendar,component); + //qDebug("events "); + qApp->processEvents(); + } + + // journals + QPtrList<Journal> journals = cal->journals(); + Journal *j; + for(j=journals.first();j;j=journals.next()) { + component = mImpl->writeJournal(j); + icalcomponent_add_component(calendar,component); + //qDebug("journals "); + qApp->processEvents(); + } + const char *text; + QString ret =""; + text = icalcomponent_as_ical_string( calendar ); + qApp->processEvents(); + + // text = "BEGIN:VCALENDAR\nPRODID\n :-//K Desktop Environment//NONSGML libkcal 3.1//EN\nVERSION\n :2.0\nBEGIN:VEVENT\nDTSTAMP\n :20031231T213514Z\nORGANIZER\n :MAILTO:lutz@putz.de\nCREATED\n :20031231T213513Z\nUID\n :libkcal-1295166342.120\nSEQUENCE\n :0\nLAST-MODIFIED\n :20031231T213513Z\nSUMMARY\n :test1\nCLASS\n :PUBLIC\nPRIORITY\n :3\nDTSTART\n :20040101T090000Z\nDTEND\n :20040101T110000Z\nTRANSP\n :OPAQUE\nEND:VEVENT\nEND:VCALENDAR\n"; + + + if ( text ) { + ret = QString ( text ); + } + icalcomponent_free( calendar ); + + if (!text) { + setException(new ErrorFormat(ErrorFormat::SaveError, + i18n("libical error"))); + return QString::null; + } + + return ret; +} + +QString ICalFormat::toICalString( Incidence *incidence ) +{ + CalendarLocal cal( mTimeZoneId ); + cal.addIncidence( incidence->clone() ); + return toString( &cal ); +} + +QString ICalFormat::toString( Incidence *incidence ) +{ + icalcomponent *component; + + component = mImpl->writeIncidence( incidence ); + + const char *text = icalcomponent_as_ical_string( component ); + + icalcomponent_free( component ); + + return QString::fromLocal8Bit( text ); +} + +QString ICalFormat::toString( Recurrence *recurrence ) +{ + icalproperty *property; + property = mImpl->writeRecurrenceRule( recurrence ); + const char *text = icalproperty_as_ical_string( property ); + icalproperty_free( property ); + return QString::fromLocal8Bit( text ); +} +/* +bool ICalFormat::fromString( Recurrence * recurrence, const QString& rrule ) +{ + bool success = true; + icalerror_clear_errno(); + struct icalrecurrencetype recur = icalrecurrencetype_from_string( rrule ); + if ( icalerrno != ICAL_NO_ERROR ) { + kdDebug() << "Recurrence parsing error: " << icalerror_strerror( icalerrno ) << endl; + success = false; + } + + if ( success ) { + mImpl->readRecurrence( recur, recurrence ); + } + + return success; +} +*/ + +QString ICalFormat::createScheduleMessage(IncidenceBase *incidence, + Scheduler::Method method) +{ + icalcomponent *message = mImpl->createScheduleComponent(incidence,method); + + QString messageText = icalcomponent_as_ical_string(message); + + + + return messageText; +} + +ScheduleMessage *ICalFormat::parseScheduleMessage( Calendar *cal, + const QString &messageText ) +{ + setTimeZone( cal->timeZoneId(), !cal->isLocalTime() ); + clearException(); + + if (messageText.isEmpty()) return 0; + + icalcomponent *message; + message = icalparser_parse_string(messageText.local8Bit()); + + if (!message) return 0; + + icalproperty *m = icalcomponent_get_first_property(message, + ICAL_METHOD_PROPERTY); + + if (!m) return 0; + + icalcomponent *c; + + IncidenceBase *incidence = 0; + c = icalcomponent_get_first_component(message,ICAL_VEVENT_COMPONENT); + if (c) { + incidence = mImpl->readEvent(c); + } + + if (!incidence) { + c = icalcomponent_get_first_component(message,ICAL_VTODO_COMPONENT); + if (c) { + incidence = mImpl->readTodo(c); + } + } + + if (!incidence) { + c = icalcomponent_get_first_component(message,ICAL_VFREEBUSY_COMPONENT); + if (c) { + incidence = mImpl->readFreeBusy(c); + } + } + + if (!incidence) { + kdDebug() << "ICalFormat:parseScheduleMessage: object is not a freebusy, event or todo" << endl; + return 0; + } + + kdDebug(5800) << "ICalFormat::parseScheduleMessage() getting method..." << endl; + + icalproperty_method icalmethod = icalproperty_get_method(m); + Scheduler::Method method; + + switch (icalmethod) { + case ICAL_METHOD_PUBLISH: + method = Scheduler::Publish; + break; + case ICAL_METHOD_REQUEST: + method = Scheduler::Request; + break; + case ICAL_METHOD_REFRESH: + method = Scheduler::Refresh; + break; + case ICAL_METHOD_CANCEL: + method = Scheduler::Cancel; + break; + case ICAL_METHOD_ADD: + method = Scheduler::Add; + break; + case ICAL_METHOD_REPLY: + method = Scheduler::Reply; + break; + case ICAL_METHOD_COUNTER: + method = Scheduler::Counter; + break; + case ICAL_METHOD_DECLINECOUNTER: + method = Scheduler::Declinecounter; + break; + default: + method = Scheduler::NoMethod; + kdDebug(5800) << "ICalFormat::parseScheduleMessage(): Unknow method" << endl; + break; + } + + + if (!icalrestriction_check(message)) { + setException(new ErrorFormat(ErrorFormat::Restriction, + Scheduler::translatedMethodName(method) + ": " + + mImpl->extractErrorProperty(c))); + return 0; + } + + icalcomponent *calendarComponent = mImpl->createCalendarComponent(cal); + + Incidence *existingIncidence = cal->event(incidence->uid()); + if (existingIncidence) { + // TODO: check, if cast is required, or if it can be done by virtual funcs. + if (existingIncidence->type() == "Todo") { + Todo *todo = static_cast<Todo *>(existingIncidence); + icalcomponent_add_component(calendarComponent, + mImpl->writeTodo(todo)); + } + if (existingIncidence->type() == "Event") { + Event *event = static_cast<Event *>(existingIncidence); + icalcomponent_add_component(calendarComponent, + mImpl->writeEvent(event)); + } + } else { + calendarComponent = 0; + } + + + icalclass result = icalclassify(message,calendarComponent,(char *)""); + + + ScheduleMessage::Status status; + + switch (result) { + case ICAL_PUBLISH_NEW_CLASS: + status = ScheduleMessage::PublishNew; + break; + case ICAL_OBSOLETE_CLASS: + status = ScheduleMessage::Obsolete; + break; + case ICAL_REQUEST_NEW_CLASS: + status = ScheduleMessage::RequestNew; + break; + case ICAL_REQUEST_UPDATE_CLASS: + status = ScheduleMessage::RequestUpdate; + break; + case ICAL_UNKNOWN_CLASS: + default: + status = ScheduleMessage::Unknown; + break; + } + + return new ScheduleMessage(incidence,method,status); +} + +void ICalFormat::setTimeZone( const QString &id, bool utc ) +{ + + + mTimeZoneId = id; + mUtc = utc; + + tzOffsetMin = KGlobal::locale()->timezoneOffset(mTimeZoneId); + + //qDebug("ICalFormat::setTimeZoneOffset %s %d ",mTimeZoneId.latin1(), tzOffsetMin); +} + +QString ICalFormat::timeZoneId() const +{ + return mTimeZoneId; +} + +bool ICalFormat::utc() const +{ + return mUtc; +} +int ICalFormat::timeOffset() +{ + return tzOffsetMin; +} +const char *ICalFormat::tzString() +{ + const char* ret = (const char* ) mTzString; + return ret; +} diff --git a/libkcal/icalformat.h b/libkcal/icalformat.h new file mode 100644 index 0000000..236efbf --- a/dev/null +++ b/libkcal/icalformat.h @@ -0,0 +1,116 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef ICALFORMAT_H +#define ICALFORMAT_H + +#include <qstring.h> + +#include "scheduler.h" + +#include "calformat.h" + +namespace KCal { + +class ICalFormatImpl; + +/** + This class implements the iCalendar format. It provides methods for + loading/saving/converting iCalendar format data into the internal KOrganizer + representation as Calendar and Events. + + @short iCalendar format implementation +*/ +class ICalFormat : public CalFormat { + public: + /** Create new iCalendar format. */ + ICalFormat( bool quick = false ); + virtual ~ICalFormat(); + + /** + Loads a calendar on disk in iCalendar format into calendar. + Returns true if successful, else returns false. Provides more error + information by exception(). + @param calendar Calendar object to be filled. + @param fileName The name of the calendar file on disk. + */ + bool load( Calendar *, const QString &fileName ); + /** + Writes out the calendar to disk in iCalendar format. Returns true if + successful and false on error. + + @param calendar The Calendar object to be written. + @param fileName The name of the calendar file on disk. + */ + bool save( Calendar *, const QString &fileName ); + + /** + Parse string and populate calendar with that information. + */ + bool fromString( Calendar *, const QString & ); + /** + Parse string and return first ical component. + */ + Incidence *fromString( const QString & ); + /** + Return calendar information as string. + */ + QString toString( Calendar * ); + /** + Return incidence as full iCalendar formatted text. + */ + QString toICalString( Incidence * ); + /** + Return incidence as iCalendar formatted text. + */ + QString toString( Incidence * ); + /** + Return recurrence as iCalendar formatted text. + */ + QString toString( Recurrence * ); + /** + Parse string and fill recurrence object with + that information + */ + //bool fromString ( Recurrence *, const QString& ); + + /** Create a scheduling message for event \a e using method \m */ + QString createScheduleMessage(IncidenceBase *e,Scheduler::Method m); + /** Parse scheduling message provided as string \s */ + ScheduleMessage *parseScheduleMessage( Calendar *, const QString &s); + + /** Set id of used time zone and whether this time zone is UTC or not. */ + void setTimeZone( const QString &id, bool utc ); + QString timeZoneId() const; + int timeOffset(); + const char * tzString(); + bool utc() const; + + private: + ICalFormatImpl *mImpl; + bool mQuicksave; + QString mTimeZoneId; + QCString mTzString; + int tzOffsetMin; + bool mUtc; +}; + +} + +#endif diff --git a/libkcal/icalformatimpl.cpp b/libkcal/icalformatimpl.cpp new file mode 100644 index 0000000..e5c27a0 --- a/dev/null +++ b/libkcal/icalformatimpl.cpp @@ -0,0 +1,2173 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdatetime.h> +#include <qstring.h> +#include <qptrlist.h> +#include <qfile.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> + +extern "C" { + #include <ical.h> + #include <icalss.h> + #include <icalparser.h> + #include <icalrestriction.h> +} + +#include "calendar.h" +#include "journal.h" +#include "icalformat.h" +#include "icalformatimpl.h" +#include "compat.h" + +#define _ICAL_VERSION "2.0" + +using namespace KCal; + +const int gSecondsPerMinute = 60; +const int gSecondsPerHour = gSecondsPerMinute * 60; +const int gSecondsPerDay = gSecondsPerHour * 24; +const int gSecondsPerWeek = gSecondsPerDay * 7; + +ICalFormatImpl::ICalFormatImpl( ICalFormat *parent ) : + mParent( parent ), mCalendarVersion( 0 ) +{ + mCompat = new Compat; +} + +ICalFormatImpl::~ICalFormatImpl() +{ + delete mCompat; +} + +class ToStringVisitor : public Incidence::Visitor +{ + public: + ToStringVisitor( ICalFormatImpl *impl ) : mImpl( impl ), mComponent( 0 ) {} + + bool visit( Event *e ) { mComponent = mImpl->writeEvent( e ); return true; } + bool visit( Todo *e ) { mComponent = mImpl->writeTodo( e ); return true; } + bool visit( Journal *e ) { mComponent = mImpl->writeJournal( e ); return true; } + + icalcomponent *component() { return mComponent; } + + private: + ICalFormatImpl *mImpl; + icalcomponent *mComponent; +}; + +icalcomponent *ICalFormatImpl::writeIncidence(Incidence *incidence) +{ + ToStringVisitor v( this ); + incidence->accept(v); + return v.component(); +} + +icalcomponent *ICalFormatImpl::writeTodo(Todo *todo) +{ + QString tmpStr; + QStringList tmpStrList; + + icalcomponent *vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT); + + writeIncidence(vtodo,todo); + + // due date + if (todo->hasDueDate()) { + icaltimetype due; + if (todo->doesFloat()) { + due = writeICalDate(todo->dtDue().date()); + } else { + due = writeICalDateTime(todo->dtDue()); + } + icalcomponent_add_property(vtodo,icalproperty_new_due(due)); + } + + // start time + if (todo->hasStartDate()) { + icaltimetype start; + if (todo->doesFloat()) { +// kdDebug(5800) << "§§ Incidence " << todo->summary() << " floats." << endl; + start = writeICalDate(todo->dtStart().date()); + } else { +// kdDebug(5800) << "§§ incidence " << todo->summary() << " has time." << endl; + start = writeICalDateTime(todo->dtStart()); + } + icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start)); + } + + // completion date + if (todo->isCompleted()) { + if (!todo->hasCompletedDate()) { + // If todo was created by KOrganizer <2.2 it has no correct completion + // date. Set it to now. + todo->setCompleted(QDateTime::currentDateTime()); + } + icaltimetype completed = writeICalDateTime(todo->completed()); + icalcomponent_add_property(vtodo,icalproperty_new_completed(completed)); + } + + icalcomponent_add_property(vtodo, + icalproperty_new_percentcomplete(todo->percentComplete())); + + return vtodo; +} + +icalcomponent *ICalFormatImpl::writeEvent(Event *event) +{ + kdDebug(5800) << "Write Event '" << event->summary() << "' (" << event->uid() + << ")" << endl; + + QString tmpStr; + QStringList tmpStrList; + + icalcomponent *vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT); + + writeIncidence(vevent,event); + + // start time + icaltimetype start; + if (event->doesFloat()) { +// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl; + start = writeICalDate(event->dtStart().date()); + } else { +// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl; + start = writeICalDateTime(event->dtStart()); + } + icalcomponent_add_property(vevent,icalproperty_new_dtstart(start)); + + if (event->hasEndDate()) { + // end time + icaltimetype end; + if (event->doesFloat()) { +// kdDebug(5800) << "§§ Event " << event->summary() << " floats." << endl; + // +1 day because end date is non-inclusive. + end = writeICalDate( event->dtEnd().date().addDays( 1 ) ); + } else { +// kdDebug(5800) << "§§ Event " << event->summary() << " has time." << endl; + end = writeICalDateTime(event->dtEnd()); + } + icalcomponent_add_property(vevent,icalproperty_new_dtend(end)); + } + +// TODO: attachments, resources +#if 0 + // attachments + tmpStrList = anEvent->attachments(); + for ( QStringList::Iterator it = tmpStrList.begin(); + it != tmpStrList.end(); + ++it ) + addPropValue(vevent, VCAttachProp, (*it).utf8()); + + // resources + tmpStrList = anEvent->resources(); + tmpStr = tmpStrList.join(";"); + if (!tmpStr.isEmpty()) + addPropValue(vevent, VCResourcesProp, tmpStr.utf8()); + +#endif + + // Transparency + switch( event->transparency() ) { + case Event::Transparent: + icalcomponent_add_property(vevent, icalproperty_new_transp("TRANSPARENT")); + break; + case Event::Opaque: + icalcomponent_add_property(vevent, icalproperty_new_transp("OPAQUE")); + break; + } + + return vevent; +} + +icalcomponent *ICalFormatImpl::writeFreeBusy(FreeBusy *freebusy, + Scheduler::Method method) +{ +#if QT_VERSION >= 300 + kdDebug(5800) << "icalformatimpl: writeFreeBusy: startDate: " + << freebusy->dtStart().toString("ddd MMMM d yyyy: h:m:s ap") << " End Date: " + << freebusy->dtEnd().toString("ddd MMMM d yyyy: h:m:s ap") << endl; +#endif + + icalcomponent *vfreebusy = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT); + + writeIncidenceBase(vfreebusy,freebusy); + + icalcomponent_add_property(vfreebusy, icalproperty_new_dtstart( + writeICalDateTime(freebusy->dtStart()))); + + icalcomponent_add_property(vfreebusy, icalproperty_new_dtend( + writeICalDateTime(freebusy->dtEnd()))); + + if (method == Scheduler::Request) { + icalcomponent_add_property(vfreebusy,icalproperty_new_uid( + freebusy->uid().utf8())); + } + + //Loops through all the periods in the freebusy object + QValueList<Period> list = freebusy->busyPeriods(); + QValueList<Period>::Iterator it; + icalperiodtype period; + for (it = list.begin(); it!= list.end(); ++it) { + period.start = writeICalDateTime((*it).start()); + period.end = writeICalDateTime((*it).end()); + icalcomponent_add_property(vfreebusy, icalproperty_new_freebusy(period) ); + } + + return vfreebusy; +} + +icalcomponent *ICalFormatImpl::writeJournal(Journal *journal) +{ + icalcomponent *vjournal = icalcomponent_new(ICAL_VJOURNAL_COMPONENT); + + writeIncidence(vjournal,journal); + + // start time + if (journal->dtStart().isValid()) { + icaltimetype start; + if (journal->doesFloat()) { +// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl; + start = writeICalDate(journal->dtStart().date()); + } else { +// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl; + start = writeICalDateTime(journal->dtStart()); + } + icalcomponent_add_property(vjournal,icalproperty_new_dtstart(start)); + } + + return vjournal; +} + +void ICalFormatImpl::writeIncidence(icalcomponent *parent,Incidence *incidence) +{ + // pilot sync stuff +// TODO: move this application-specific code to kpilot + if (incidence->pilotId()) { + incidence->setNonKDECustomProperty("X-PILOTID", QString::number(incidence->pilotId())); + incidence->setNonKDECustomProperty("X-PILOTSTAT", QString::number(incidence->syncStatus())); + } + if (incidence->zaurusId() >= 0) { + incidence->setNonKDECustomProperty("X-ZAURUSID", QString::number(incidence->zaurusId())); + } + + if (incidence->zaurusUid() > 0) { + incidence->setNonKDECustomProperty("X-ZAURUSUID", QString::number(incidence->zaurusUid())); + } + if (incidence->zaurusStat() > 0) { + incidence->setNonKDECustomProperty("X-ZAURUSSTAT", QString::number(incidence->zaurusStat())); + } + + writeIncidenceBase(parent,incidence); + if (incidence->cancelled()) { + icalcomponent_add_property(parent,icalproperty_new_status(ICAL_STATUS_CANCELLED)); + } + + // creation date + icalcomponent_add_property(parent,icalproperty_new_created( + writeICalDateTime(incidence->created()))); + + // unique id + icalcomponent_add_property(parent,icalproperty_new_uid( + incidence->uid().utf8())); + + // revision + icalcomponent_add_property(parent,icalproperty_new_sequence( + incidence->revision())); + + // last modification date + icalcomponent_add_property(parent,icalproperty_new_lastmodified( + writeICalDateTime(incidence->lastModified()))); + + // description + if (!incidence->description().isEmpty()) { + icalcomponent_add_property(parent,icalproperty_new_description( + incidence->description().utf8())); + } + + // summary + if (!incidence->summary().isEmpty()) { + icalcomponent_add_property(parent,icalproperty_new_summary( + incidence->summary().utf8())); + } + + // location + if (!incidence->location().isEmpty()) { + icalcomponent_add_property(parent,icalproperty_new_location( + incidence->location().utf8())); + } + +// TODO: + // status +// addPropValue(parent, VCStatusProp, incidence->getStatusStr().utf8()); + + // secrecy + const char *classStr; + switch (incidence->secrecy()) { + case Incidence::SecrecyPublic: + classStr = "PUBLIC"; + break; + case Incidence::SecrecyConfidential: + classStr = "CONFIDENTIAL"; + break; + case Incidence::SecrecyPrivate: + default: + classStr = "PRIVATE"; + break; + } + icalcomponent_add_property(parent,icalproperty_new_class(classStr)); + + // priority + icalcomponent_add_property(parent,icalproperty_new_priority( + incidence->priority())); + + // categories + QStringList categories = incidence->categories(); + QStringList::Iterator it; + for(it = categories.begin(); it != categories.end(); ++it ) { + icalcomponent_add_property(parent,icalproperty_new_categories((*it).utf8())); + } +// TODO: Ensure correct concatenation of categories properties. + +/* + // categories + tmpStrList = incidence->getCategories(); + tmpStr = ""; + QString catStr; + for ( QStringList::Iterator it = tmpStrList.begin(); + it != tmpStrList.end(); + ++it ) { + catStr = *it; + if (catStr[0] == ' ') + tmpStr += catStr.mid(1); + else + tmpStr += catStr; + // this must be a ';' character as the vCalendar specification requires! + // vcc.y has been hacked to translate the ';' to a ',' when the vcal is + // read in. + tmpStr += ";"; + } + if (!tmpStr.isEmpty()) { + tmpStr.truncate(tmpStr.length()-1); + icalcomponent_add_property(parent,icalproperty_new_categories( + writeText(incidence->getCategories().join(";")))); + } +*/ + + // related event + if (incidence->relatedTo()) { + icalcomponent_add_property(parent,icalproperty_new_relatedto( + incidence->relatedTo()->uid().utf8())); + } + + // recurrence rule stuff + Recurrence *recur = incidence->recurrence(); + if (recur->doesRecur()) { + + icalcomponent_add_property(parent,writeRecurrenceRule(recur)); + } + + // recurrence excpetion dates + DateList dateList = incidence->exDates(); + DateList::ConstIterator exIt; + for(exIt = dateList.begin(); exIt != dateList.end(); ++exIt) { + icalcomponent_add_property(parent,icalproperty_new_exdate( + writeICalDate(*exIt))); + } + + // attachments + QPtrList<Attachment> attachments = incidence->attachments(); + for (Attachment *at = attachments.first(); at; at = attachments.next()) + icalcomponent_add_property(parent,writeAttachment(at)); + + // alarms + QPtrList<Alarm> alarms = incidence->alarms(); + Alarm* alarm; + for (alarm = alarms.first(); alarm; alarm = alarms.next()) { + if (alarm->enabled()) { + kdDebug(5800) << "Write alarm for " << incidence->summary() << endl; + icalcomponent_add_component(parent,writeAlarm(alarm)); + } + } + + // duration + +// turned off as it always is set to PTS0 (and must not occur together with DTEND + +// if (incidence->hasDuration()) { +// icaldurationtype duration; +// duration = writeICalDuration(incidence->duration()); +// icalcomponent_add_property(parent,icalproperty_new_duration(duration)); +// } +} + +void ICalFormatImpl::writeIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase) +{ + icalcomponent_add_property(parent,icalproperty_new_dtstamp( + writeICalDateTime(QDateTime::currentDateTime()))); + + // organizer stuff + icalcomponent_add_property(parent,icalproperty_new_organizer( + ("MAILTO:" + incidenceBase->organizer()).utf8())); + + // attendees + if (incidenceBase->attendeeCount() != 0) { + QPtrList<Attendee> al = incidenceBase->attendees(); + QPtrListIterator<Attendee> ai(al); + for (; ai.current(); ++ai) { + icalcomponent_add_property(parent,writeAttendee(ai.current())); + } + } + + // custom properties + writeCustomProperties(parent, incidenceBase); +} + +void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties) +{ + QMap<QCString, QString> custom = properties->customProperties(); + for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) { + icalproperty *p = icalproperty_new_x(c.data().utf8()); + icalproperty_set_x_name(p,c.key()); + icalcomponent_add_property(parent,p); + } +} + +icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee) +{ + icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8()); + + if (!attendee->name().isEmpty()) { + icalproperty_add_parameter(p,icalparameter_new_cn(attendee->name().utf8())); + } + + + icalproperty_add_parameter(p,icalparameter_new_rsvp( + attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE )); + + icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION; + switch (attendee->status()) { + default: + case Attendee::NeedsAction: + status = ICAL_PARTSTAT_NEEDSACTION; + break; + case Attendee::Accepted: + status = ICAL_PARTSTAT_ACCEPTED; + break; + case Attendee::Declined: + status = ICAL_PARTSTAT_DECLINED; + break; + case Attendee::Tentative: + status = ICAL_PARTSTAT_TENTATIVE; + break; + case Attendee::Delegated: + status = ICAL_PARTSTAT_DELEGATED; + break; + case Attendee::Completed: + status = ICAL_PARTSTAT_COMPLETED; + break; + case Attendee::InProcess: + status = ICAL_PARTSTAT_INPROCESS; + break; + } + icalproperty_add_parameter(p,icalparameter_new_partstat(status)); + + icalparameter_role role = ICAL_ROLE_REQPARTICIPANT; + switch (attendee->role()) { + case Attendee::Chair: + role = ICAL_ROLE_CHAIR; + break; + default: + case Attendee::ReqParticipant: + role = ICAL_ROLE_REQPARTICIPANT; + break; + case Attendee::OptParticipant: + role = ICAL_ROLE_OPTPARTICIPANT; + break; + case Attendee::NonParticipant: + role = ICAL_ROLE_NONPARTICIPANT; + break; + } + icalproperty_add_parameter(p,icalparameter_new_role(role)); + + if (!attendee->uid().isEmpty()) { + icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8()); + icalparameter_set_xname(icalparameter_uid,"X-UID"); + icalproperty_add_parameter(p,icalparameter_uid); + } + + return p; +} + +icalproperty *ICalFormatImpl::writeAttachment(Attachment *att) +{ + icalattachtype* attach = icalattachtype_new(); + if (att->isURI()) + icalattachtype_set_url(attach, att->uri().utf8().data()); + else + icalattachtype_set_base64(attach, att->data(), 0); + + icalproperty *p = icalproperty_new_attach(attach); + + if (!att->mimeType().isEmpty()) + icalproperty_add_parameter(p,icalparameter_new_fmttype(att->mimeType().utf8().data())); + + if (att->isBinary()) { + icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY)); + icalproperty_add_parameter(p,icalparameter_new_encoding(ICAL_ENCODING_BASE64)); + } + return p; +} + +icalproperty *ICalFormatImpl::writeRecurrenceRule(Recurrence *recur) +{ +// kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl; + + icalrecurrencetype r; + + icalrecurrencetype_clear(&r); + + int index = 0; + int index2 = 0; + + QPtrList<Recurrence::rMonthPos> tmpPositions; + QPtrList<int> tmpDays; + int *tmpDay; + Recurrence::rMonthPos *tmpPos; + bool datetime = false; + int day; + int i; + + switch(recur->doesRecur()) { + case Recurrence::rMinutely: + r.freq = ICAL_MINUTELY_RECURRENCE; + datetime = true; + break; + case Recurrence::rHourly: + r.freq = ICAL_HOURLY_RECURRENCE; + datetime = true; + break; + case Recurrence::rDaily: + r.freq = ICAL_DAILY_RECURRENCE; + break; + case Recurrence::rWeekly: + r.freq = ICAL_WEEKLY_RECURRENCE; + r.week_start = static_cast<icalrecurrencetype_weekday>(recur->weekStart()%7 + 1); + for (i = 0; i < 7; i++) { + if (recur->days().testBit(i)) { + day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 + r.by_day[index++] = icalrecurrencetype_day_day_of_week(day); + } + } +// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; + break; + case Recurrence::rMonthlyPos: + r.freq = ICAL_MONTHLY_RECURRENCE; + + tmpPositions = recur->monthPositions(); + for (tmpPos = tmpPositions.first(); + tmpPos; + tmpPos = tmpPositions.next()) { + for (i = 0; i < 7; i++) { + if (tmpPos->rDays.testBit(i)) { + day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 + day += tmpPos->rPos*8; + if (tmpPos->negative) day = -day; + r.by_day[index++] = day; + } + } + } +// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; + break; + case Recurrence::rMonthlyDay: + r.freq = ICAL_MONTHLY_RECURRENCE; + + tmpDays = recur->monthDays(); + for (tmpDay = tmpDays.first(); + tmpDay; + tmpDay = tmpDays.next()) { + r.by_month_day[index++] = icalrecurrencetype_day_position(*tmpDay*8);//*tmpDay); + } +// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; + break; + case Recurrence::rYearlyMonth: + case Recurrence::rYearlyPos: + r.freq = ICAL_YEARLY_RECURRENCE; + + tmpDays = recur->yearNums(); + for (tmpDay = tmpDays.first(); + tmpDay; + tmpDay = tmpDays.next()) { + r.by_month[index++] = *tmpDay; + } +// r.by_set_pos[index] = ICAL_RECURRENCE_ARRAY_MAX; + if (recur->doesRecur() == Recurrence::rYearlyPos) { + tmpPositions = recur->monthPositions(); + for (tmpPos = tmpPositions.first(); + tmpPos; + tmpPos = tmpPositions.next()) { + for (i = 0; i < 7; i++) { + if (tmpPos->rDays.testBit(i)) { + day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 + day += tmpPos->rPos*8; + if (tmpPos->negative) day = -day; + r.by_day[index2++] = day; + } + } + } +// r.by_day[index2] = ICAL_RECURRENCE_ARRAY_MAX; + } + break; + case Recurrence::rYearlyDay: + r.freq = ICAL_YEARLY_RECURRENCE; + + tmpDays = recur->yearNums(); + for (tmpDay = tmpDays.first(); + tmpDay; + tmpDay = tmpDays.next()) { + r.by_year_day[index++] = *tmpDay; + } +// r.by_year_day[index] = ICAL_RECURRENCE_ARRAY_MAX; + break; + default: + r.freq = ICAL_NO_RECURRENCE; + kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl; + break; + } + + r.interval = recur->frequency(); + + if (recur->duration() > 0) { + r.count = recur->duration(); + } else if (recur->duration() == -1) { + r.count = 0; + } else { + if (datetime) + r.until = writeICalDateTime(recur->endDateTime()); + else + r.until = writeICalDate(recur->endDate()); + } + +// Debug output +#if 0 + const char *str = icalrecurrencetype_as_string(&r); + if (str) { + kdDebug(5800) << " String: " << str << endl; + } else { + kdDebug(5800) << " No String" << endl; + } +#endif + + return icalproperty_new_rrule(r); +} + +icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm) +{ + icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT); + + icalproperty_action action; + icalattachtype *attach = 0; + + switch (alarm->type()) { + case Alarm::Procedure: + action = ICAL_ACTION_PROCEDURE; + attach = icalattachtype_new(); + icalattachtype_set_url(attach,QFile::encodeName(alarm->programFile()).data()); + icalcomponent_add_property(a,icalproperty_new_attach(attach)); + icalattachtype_free(attach); + if (!alarm->programArguments().isEmpty()) { + icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8())); + } + break; + case Alarm::Audio: + action = ICAL_ACTION_AUDIO; + if (!alarm->audioFile().isEmpty()) { + attach = icalattachtype_new(); + icalattachtype_set_url(attach,QFile::encodeName( alarm->audioFile() ).data()); + icalcomponent_add_property(a,icalproperty_new_attach(attach)); + icalattachtype_free(attach); + } + break; + case Alarm::Email: { + action = ICAL_ACTION_EMAIL; + QValueList<Person> addresses = alarm->mailAddresses(); + for (QValueList<Person>::Iterator ad = addresses.begin(); ad != addresses.end(); ++ad) { + icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8()); + if (!(*ad).name().isEmpty()) { + icalproperty_add_parameter(p,icalparameter_new_cn((*ad).name().utf8())); + } + icalcomponent_add_property(a,p); + } + icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8())); + icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8())); + QStringList attachments = alarm->mailAttachments(); + if (attachments.count() > 0) { + for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) { + attach = icalattachtype_new(); + icalattachtype_set_url(attach,QFile::encodeName( *at ).data()); + icalcomponent_add_property(a,icalproperty_new_attach(attach)); + icalattachtype_free(attach); + } + } + break; + } + case Alarm::Display: + action = ICAL_ACTION_DISPLAY; + icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8())); + break; + case Alarm::Invalid: + default: + kdDebug(5800) << "Unknown type of alarm" << endl; + action = ICAL_ACTION_NONE; + break; + } + icalcomponent_add_property(a,icalproperty_new_action(action)); + + // Trigger time + icaltriggertype trigger; + if ( alarm->hasTime() ) { + trigger.time = writeICalDateTime(alarm->time()); + trigger.duration = icaldurationtype_null_duration(); + } else { + trigger.time = icaltime_null_time(); + Duration offset; + if ( alarm->hasStartOffset() ) + offset = alarm->startOffset(); + else + offset = alarm->endOffset(); + trigger.duration = icaldurationtype_from_int( offset.asSeconds() ); + } + icalproperty *p = icalproperty_new_trigger(trigger); + if ( alarm->hasEndOffset() ) + icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END)); + icalcomponent_add_property(a,p); + + // Repeat count and duration + if (alarm->repeatCount()) { + icalcomponent_add_property(a,icalproperty_new_repeat(alarm->repeatCount())); + icalcomponent_add_property(a,icalproperty_new_duration( + icaldurationtype_from_int(alarm->snoozeTime()*60))); + } + + // Custom properties + QMap<QCString, QString> custom = alarm->customProperties(); + for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) { + icalproperty *p = icalproperty_new_x(c.data().utf8()); + icalproperty_set_x_name(p,c.key()); + icalcomponent_add_property(a,p); + } + + return a; +} + +Todo *ICalFormatImpl::readTodo(icalcomponent *vtodo) +{ + Todo *todo = new Todo; + + readIncidence(vtodo,todo); + + icalproperty *p = icalcomponent_get_first_property(vtodo,ICAL_ANY_PROPERTY); + +// int intvalue; + icaltimetype icaltime; + + QStringList categories; + + while (p) { + icalproperty_kind kind = icalproperty_isa(p); + switch (kind) { + + case ICAL_DUE_PROPERTY: // due date + icaltime = icalproperty_get_due(p); + if (icaltime.is_date) { + todo->setDtDue(QDateTime(readICalDate(icaltime),QTime(0,0,0))); + todo->setFloats(true); + + } else { + todo->setDtDue(readICalDateTime(icaltime)); + todo->setFloats(false); + } + todo->setHasDueDate(true); + break; + + case ICAL_COMPLETED_PROPERTY: // completion date + icaltime = icalproperty_get_completed(p); + todo->setCompleted(readICalDateTime(icaltime)); + break; + + case ICAL_PERCENTCOMPLETE_PROPERTY: // Percent completed + todo->setPercentComplete(icalproperty_get_percentcomplete(p)); + break; + + case ICAL_RELATEDTO_PROPERTY: // related todo (parent) + todo->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p))); + mTodosRelate.append(todo); + break; + + case ICAL_DTSTART_PROPERTY: + // Flag that todo has start date. Value is read in by readIncidence(). + todo->setHasStartDate(true); + break; + + default: +// kdDebug(5800) << "ICALFormat::readTodo(): Unknown property: " << kind +// << endl; + break; + } + + p = icalcomponent_get_next_property(vtodo,ICAL_ANY_PROPERTY); + } + + return todo; +} + +Event *ICalFormatImpl::readEvent(icalcomponent *vevent) +{ + Event *event = new Event; + event->setFloats(false); + + readIncidence(vevent,event); + + icalproperty *p = icalcomponent_get_first_property(vevent,ICAL_ANY_PROPERTY); + +// int intvalue; + icaltimetype icaltime; + + QStringList categories; + QString transparency; + + while (p) { + icalproperty_kind kind = icalproperty_isa(p); + switch (kind) { + + case ICAL_DTEND_PROPERTY: // start date and time + icaltime = icalproperty_get_dtend(p); + if (icaltime.is_date) { + event->setFloats( true ); + // End date is non-inclusive + QDate endDate = readICalDate( icaltime ).addDays( -1 ); + mCompat->fixFloatingEnd( endDate ); + if ( endDate < event->dtStart().date() ) { + endDate = event->dtStart().date(); + } + event->setDtEnd( QDateTime( endDate, QTime( 0, 0, 0 ) ) ); + } else { + event->setDtEnd(readICalDateTime(icaltime)); + } + break; + +// TODO: + // at this point, there should be at least a start or end time. + // fix up for events that take up no time but have a time associated +#if 0 + if (!(vo = isAPropertyOf(vevent, VCDTstartProp))) + anEvent->setDtStart(anEvent->dtEnd()); + if (!(vo = isAPropertyOf(vevent, VCDTendProp))) + anEvent->setDtEnd(anEvent->dtStart()); +#endif + +// TODO: exdates +#if 0 + // recurrence exceptions + if ((vo = isAPropertyOf(vevent, VCExDateProp)) != 0) { + anEvent->setExDates(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + } +#endif + +#if 0 + // secrecy + if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) { + anEvent->setSecrecy(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + } + else + anEvent->setSecrecy("PUBLIC"); + + // attachments + tmpStrList.clear(); + initPropIterator(&voi, vevent); + while (moreIteration(&voi)) { + vo = nextVObject(&voi); + if (strcmp(vObjectName(vo), VCAttachProp) == 0) { + tmpStrList.append(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + } + } + anEvent->setAttachments(tmpStrList); + + // resources + if ((vo = isAPropertyOf(vevent, VCResourcesProp)) != 0) { + QString resources = (s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + tmpStrList.clear(); + index1 = 0; + index2 = 0; + QString resource; + while ((index2 = resources.find(';', index1)) != -1) { + resource = resources.mid(index1, (index2 - index1)); + tmpStrList.append(resource); + index1 = index2; + } + anEvent->setResources(tmpStrList); + } +#endif + + case ICAL_RELATEDTO_PROPERTY: // releated event (parent) + event->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p))); + mEventsRelate.append(event); + break; + + + case ICAL_TRANSP_PROPERTY: // Transparency + transparency = QString::fromUtf8(icalproperty_get_transp(p)); + if( transparency == "TRANSPARENT" ) + event->setTransparency( Event::Transparent ); + else + event->setTransparency( Event::Opaque ); + break; + + default: +// kdDebug(5800) << "ICALFormat::readEvent(): Unknown property: " << kind +// << endl; + break; + } + + p = icalcomponent_get_next_property(vevent,ICAL_ANY_PROPERTY); + } + + QString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT"); + if (!msade.isNull()) { + bool floats = (msade == QString::fromLatin1("TRUE")); + kdDebug(5800) << "ICALFormat::readEvent(): all day event: " << floats << endl; + event->setFloats(floats); + if (floats) { + QDateTime endDate = event->dtEnd(); + event->setDtEnd(endDate.addDays(-1)); + } + } + + // some stupid vCal exporters ignore the standard and use Description + // instead of Summary for the default field. Correct for this. + if (event->summary().isEmpty() && + !(event->description().isEmpty())) { + QString tmpStr = event->description().simplifyWhiteSpace(); + event->setDescription(""); + event->setSummary(tmpStr); + } + + return event; +} + +FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy) +{ + FreeBusy *freebusy = new FreeBusy; + + readIncidenceBase(vfreebusy,freebusy); + + icalproperty *p = icalcomponent_get_first_property(vfreebusy,ICAL_ANY_PROPERTY); + + icaltimetype icaltime; + icalperiodtype icalperiod; + QDateTime period_start, period_end; + + while (p) { + icalproperty_kind kind = icalproperty_isa(p); + switch (kind) { + + case ICAL_DTSTART_PROPERTY: // start date and time + icaltime = icalproperty_get_dtstart(p); + freebusy->setDtStart(readICalDateTime(icaltime)); + break; + + case ICAL_DTEND_PROPERTY: // start End Date and Time + icaltime = icalproperty_get_dtend(p); + freebusy->setDtEnd(readICalDateTime(icaltime)); + break; + + case ICAL_FREEBUSY_PROPERTY: //Any FreeBusy Times + icalperiod = icalproperty_get_freebusy(p); + period_start = readICalDateTime(icalperiod.start); + period_end = readICalDateTime(icalperiod.end); + freebusy->addPeriod(period_start, period_end); + break; + + default: + kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind + << endl; + break; + } + p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY); + } + + return freebusy; +} + +Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal) +{ + Journal *journal = new Journal; + + readIncidence(vjournal,journal); + + return journal; +} + +Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee) +{ + icalparameter *p = 0; + + QString email = QString::fromUtf8(icalproperty_get_attendee(attendee)); + + QString name; + QString uid = QString::null; + p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER); + if (p) { + name = QString::fromUtf8(icalparameter_get_cn(p)); + } else { + } + + bool rsvp=false; + p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER); + if (p) { + icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p); + if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true; + } + + Attendee::PartStat status = Attendee::NeedsAction; + p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER); + if (p) { + icalparameter_partstat partStatParameter = icalparameter_get_partstat(p); + switch(partStatParameter) { + default: + case ICAL_PARTSTAT_NEEDSACTION: + status = Attendee::NeedsAction; + break; + case ICAL_PARTSTAT_ACCEPTED: + status = Attendee::Accepted; + break; + case ICAL_PARTSTAT_DECLINED: + status = Attendee::Declined; + break; + case ICAL_PARTSTAT_TENTATIVE: + status = Attendee::Tentative; + break; + case ICAL_PARTSTAT_DELEGATED: + status = Attendee::Delegated; + break; + case ICAL_PARTSTAT_COMPLETED: + status = Attendee::Completed; + break; + case ICAL_PARTSTAT_INPROCESS: + status = Attendee::InProcess; + break; + } + } + + Attendee::Role role = Attendee::ReqParticipant; + p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER); + if (p) { + icalparameter_role roleParameter = icalparameter_get_role(p); + switch(roleParameter) { + case ICAL_ROLE_CHAIR: + role = Attendee::Chair; + break; + default: + case ICAL_ROLE_REQPARTICIPANT: + role = Attendee::ReqParticipant; + break; + case ICAL_ROLE_OPTPARTICIPANT: + role = Attendee::OptParticipant; + break; + case ICAL_ROLE_NONPARTICIPANT: + role = Attendee::NonParticipant; + break; + } + } + + p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER); + uid = icalparameter_get_xvalue(p); + // This should be added, but there seems to be a libical bug here. + /*while (p) { + // if (icalparameter_get_xname(p) == "X-UID") { + uid = icalparameter_get_xvalue(p); + p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER); + } */ + + return new Attendee( name, email, rsvp, status, role, uid ); +} + +Attachment *ICalFormatImpl::readAttachment(icalproperty *attach) +{ + icalattachtype *a = icalproperty_get_attach(attach); + icalparameter_value v = ICAL_VALUE_NONE; + icalparameter_encoding e = ICAL_ENCODING_NONE; + + Attachment *attachment = 0; + + icalparameter *vp = icalproperty_get_first_parameter(attach, ICAL_VALUE_PARAMETER); + if (vp) + v = icalparameter_get_value(vp); + + icalparameter *ep = icalproperty_get_first_parameter(attach, ICAL_ENCODING_PARAMETER); + if (ep) + e = icalparameter_get_encoding(ep); + + if (v == ICAL_VALUE_BINARY && e == ICAL_ENCODING_BASE64) + attachment = new Attachment(icalattachtype_get_base64(a)); + else if ((v == ICAL_VALUE_NONE || v == ICAL_VALUE_URI) && (e == ICAL_ENCODING_NONE || e == ICAL_ENCODING_8BIT)) { + attachment = new Attachment(QString(icalattachtype_get_url(a))); + } else { + kdWarning(5800) << "Unsupported attachment format, discarding it!" << endl; + return 0; + } + + icalparameter *p = icalproperty_get_first_parameter(attach, ICAL_FMTTYPE_PARAMETER); + if (p) + attachment->setMimeType(QString(icalparameter_get_fmttype(p))); + + return attachment; +} +#include <qtextcodec.h> +void ICalFormatImpl::readIncidence(icalcomponent *parent,Incidence *incidence) +{ + readIncidenceBase(parent,incidence); + + icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY); + bool readrec = false; + const char *text; + int intvalue; + icaltimetype icaltime; + icaldurationtype icalduration; + struct icalrecurrencetype rectype; + QStringList categories; + + while (p) { + icalproperty_kind kind = icalproperty_isa(p); + switch (kind) { + + case ICAL_CREATED_PROPERTY: + icaltime = icalproperty_get_created(p); + incidence->setCreated(readICalDateTime(icaltime)); + break; + + case ICAL_SEQUENCE_PROPERTY: // sequence + intvalue = icalproperty_get_sequence(p); + incidence->setRevision(intvalue); + break; + + case ICAL_LASTMODIFIED_PROPERTY: // last modification date + icaltime = icalproperty_get_lastmodified(p); + incidence->setLastModified(readICalDateTime(icaltime)); + break; + + case ICAL_DTSTART_PROPERTY: // start date and time + icaltime = icalproperty_get_dtstart(p); + if (icaltime.is_date) { + incidence->setDtStart(QDateTime(readICalDate(icaltime),QTime(0,0,0))); + incidence->setFloats(true); + } else { + incidence->setDtStart(readICalDateTime(icaltime)); + } + break; + + case ICAL_DURATION_PROPERTY: // start date and time + icalduration = icalproperty_get_duration(p); + incidence->setDuration(readICalDuration(icalduration)); + break; + + case ICAL_DESCRIPTION_PROPERTY: // description + text = icalproperty_get_description(p); + incidence->setDescription(QString::fromUtf8(text)); + break; + + case ICAL_SUMMARY_PROPERTY: // summary + { + text = icalproperty_get_summary(p); + incidence->setSummary(QString::fromUtf8(text)); + } + break; + case ICAL_STATUS_PROPERTY: // summary + { + if ( ICAL_STATUS_CANCELLED == icalproperty_get_status(p) ) + incidence->setCancelled( true ); + } + break; + + case ICAL_LOCATION_PROPERTY: // location + text = icalproperty_get_location(p); + incidence->setLocation(QString::fromUtf8(text)); + break; + +#if 0 + // status + if ((vo = isAPropertyOf(vincidence, VCStatusProp)) != 0) { + incidence->setStatus(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + } + else + incidence->setStatus("NEEDS ACTION"); +#endif + + case ICAL_PRIORITY_PROPERTY: // priority + intvalue = icalproperty_get_priority(p); + incidence->setPriority(intvalue); + break; + + case ICAL_CATEGORIES_PROPERTY: // categories + text = icalproperty_get_categories(p); + categories.append(QString::fromUtf8(text)); + break; + //******************************************* + case ICAL_RRULE_PROPERTY: + // we do need (maybe )start datetime of incidence for recurrence + // such that we can read recurrence only after we read incidence completely + readrec = true; + rectype = icalproperty_get_rrule(p); + break; + + case ICAL_EXDATE_PROPERTY: + icaltime = icalproperty_get_exdate(p); + incidence->addExDate(readICalDate(icaltime)); + break; + + case ICAL_CLASS_PROPERTY: + text = icalproperty_get_class(p); + if (strcmp(text,"PUBLIC") == 0) { + incidence->setSecrecy(Incidence::SecrecyPublic); + } else if (strcmp(text,"CONFIDENTIAL") == 0) { + incidence->setSecrecy(Incidence::SecrecyConfidential); + } else { + incidence->setSecrecy(Incidence::SecrecyPrivate); + } + break; + + case ICAL_ATTACH_PROPERTY: // attachments + incidence->addAttachment(readAttachment(p)); + break; + + default: +// kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind +// << endl; + break; + } + + p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY); + } + if ( readrec ) { + readRecurrenceRule(rectype,incidence); + } + // kpilot stuff +// TODO: move this application-specific code to kpilot + QString kp = incidence->nonKDECustomProperty("X-PILOTID"); + if (!kp.isNull()) { + incidence->setPilotId(kp.toInt()); + } + kp = incidence->nonKDECustomProperty("X-PILOTSTAT"); + if (!kp.isNull()) { + incidence->setSyncStatus(kp.toInt()); + } + kp = incidence->nonKDECustomProperty("X-ZAURUSID"); + if (!kp.isNull()) { + incidence->setZaurusId(kp.toInt()); + } + + kp = incidence->nonKDECustomProperty("X-ZAURUSUID"); + if (!kp.isNull()) { + incidence->setZaurusUid(kp.toInt()); + } + + kp = incidence->nonKDECustomProperty("X-ZAURUSSTAT"); + if (!kp.isNull()) { + incidence->setZaurusStat(kp.toInt()); + } + + // Cancel backwards compatibility mode for subsequent changes by the application + incidence->recurrence()->setCompatVersion(); + + // add categories + incidence->setCategories(categories); + + // iterate through all alarms + for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT); + alarm; + alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) { + readAlarm(alarm,incidence); + } +} + +void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase) +{ + icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY); + + while (p) { + icalproperty_kind kind = icalproperty_isa(p); + switch (kind) { + + case ICAL_UID_PROPERTY: // unique id + incidenceBase->setUid(QString::fromUtf8(icalproperty_get_uid(p))); + break; + + case ICAL_ORGANIZER_PROPERTY: // organizer + incidenceBase->setOrganizer(QString::fromUtf8(icalproperty_get_organizer(p))); + break; + + case ICAL_ATTENDEE_PROPERTY: // attendee + incidenceBase->addAttendee(readAttendee(p)); + break; + + default: + break; + } + + p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY); + } + + // custom properties + readCustomProperties(parent, incidenceBase); +} + +void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties) +{ + QMap<QCString, QString> customProperties; + + icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY); + + while (p) { + + QString value = QString::fromUtf8(icalproperty_get_x(p)); + customProperties[icalproperty_get_name(p)] = value; + + p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY); + } + + properties->setCustomProperties(customProperties); +} + +void ICalFormatImpl::readRecurrenceRule(struct icalrecurrencetype rrule,Incidence *incidence) +{ +// kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl; + + Recurrence *recur = incidence->recurrence(); + recur->setCompatVersion(mCalendarVersion); + recur->unsetRecurs(); + + struct icalrecurrencetype r = rrule; + + dumpIcalRecurrence(r); + readRecurrence( r, recur, incidence); +} + +void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur, Incidence *incidence) +{ + int wkst; + int index = 0; + short day = 0; + QBitArray qba(7); + int frequ = r.freq; + int interv = r.interval; + // preprocessing for odd recurrence definitions + + if ( r.freq == ICAL_MONTHLY_RECURRENCE ) { + if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { + interv = 12; + } + } + if ( r.freq == ICAL_YEARLY_RECURRENCE ) { + if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX && r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX ) { + frequ = ICAL_MONTHLY_RECURRENCE; + interv = 12; + } + } + + switch (frequ) { + case ICAL_MINUTELY_RECURRENCE: + if (!icaltime_is_null_time(r.until)) { + recur->setMinutely(interv,readICalDateTime(r.until)); + } else { + if (r.count == 0) + recur->setMinutely(interv,-1); + else + recur->setMinutely(interv,r.count); + } + break; + case ICAL_HOURLY_RECURRENCE: + if (!icaltime_is_null_time(r.until)) { + recur->setHourly(interv,readICalDateTime(r.until)); + } else { + if (r.count == 0) + recur->setHourly(interv,-1); + else + recur->setHourly(interv,r.count); + } + break; + case ICAL_DAILY_RECURRENCE: + if (!icaltime_is_null_time(r.until)) { + recur->setDaily(interv,readICalDate(r.until)); + } else { + if (r.count == 0) + recur->setDaily(interv,-1); + else + recur->setDaily(interv,r.count); + } + break; + case ICAL_WEEKLY_RECURRENCE: + // kdDebug(5800) << "WEEKLY_RECURRENCE" << endl; + wkst = (r.week_start + 5)%7 + 1; + if (!icaltime_is_null_time(r.until)) { + recur->setWeekly(interv,qba,readICalDate(r.until),wkst); + } else { + if (r.count == 0) + recur->setWeekly(interv,qba,-1,wkst); + else + recur->setWeekly(interv,qba,r.count,wkst); + } + if ( r.by_day[0] == ICAL_RECURRENCE_ARRAY_MAX) { + int wday = incidence->dtStart().date().dayOfWeek ()-1; + //qDebug("weekly error found "); + qba.setBit(wday); + } else { + while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + // kdDebug(5800) << " " << day << endl; + qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 + } + } + break; + case ICAL_MONTHLY_RECURRENCE: + + if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { + if (!icaltime_is_null_time(r.until)) { + recur->setMonthly(Recurrence::rMonthlyPos,interv, + readICalDate(r.until)); + } else { + if (r.count == 0) + recur->setMonthly(Recurrence::rMonthlyPos,interv,-1); + else + recur->setMonthly(Recurrence::rMonthlyPos,interv,r.count); + } + bool useSetPos = false; + short pos = 0; + while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + // kdDebug(5800) << "----a " << index << ": " << day << endl; + pos = icalrecurrencetype_day_position(day); + if (pos) { + day = icalrecurrencetype_day_day_of_week(day); + QBitArray ba(7); // don't wipe qba + ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 + recur->addMonthlyPos(pos,ba); + } else { + qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 + useSetPos = true; + } + } + if (useSetPos) { + if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { + recur->addMonthlyPos(r.by_set_pos[0],qba); + } + } + } else if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { + if (!icaltime_is_null_time(r.until)) { + recur->setMonthly(Recurrence::rMonthlyDay,interv, + readICalDate(r.until)); + } else { + if (r.count == 0) + recur->setMonthly(Recurrence::rMonthlyDay,interv,-1); + else + recur->setMonthly(Recurrence::rMonthlyDay,interv,r.count); + } + while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + // kdDebug(5800) << "----b " << day << endl; + recur->addMonthlyDay(day); + } + } + break; + case ICAL_YEARLY_RECURRENCE: + if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { + if (!icaltime_is_null_time(r.until)) { + recur->setYearly(Recurrence::rYearlyDay,interv, + readICalDate(r.until)); + } else { + if (r.count == 0) + recur->setYearly(Recurrence::rYearlyDay,interv,-1); + else + recur->setYearly(Recurrence::rYearlyDay,interv,r.count); + } + while((day = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + recur->addYearlyNum(day); + } + } else if ( true /*r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX*/) { + if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { + if (!icaltime_is_null_time(r.until)) { + recur->setYearly(Recurrence::rYearlyPos,interv, + readICalDate(r.until)); + } else { + if (r.count == 0) + recur->setYearly(Recurrence::rYearlyPos,interv,-1); + else + recur->setYearly(Recurrence::rYearlyPos,interv,r.count); + } + bool useSetPos = false; + short pos = 0; + while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + // kdDebug(5800) << "----a " << index << ": " << day << endl; + pos = icalrecurrencetype_day_position(day); + if (pos) { + day = icalrecurrencetype_day_day_of_week(day); + QBitArray ba(7); // don't wipe qba + ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 + recur->addYearlyMonthPos(pos,ba); + } else { + qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 + useSetPos = true; + } + } + if (useSetPos) { + if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { + recur->addYearlyMonthPos(r.by_set_pos[0],qba); + } + } + } else { + if (!icaltime_is_null_time(r.until)) { + recur->setYearly(Recurrence::rYearlyMonth,interv, + readICalDate(r.until)); + } else { + if (r.count == 0) + recur->setYearly(Recurrence::rYearlyMonth,interv,-1); + else + recur->setYearly(Recurrence::rYearlyMonth,interv,r.count); + } + } + if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX ) { + index = 0; + while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + recur->addYearlyNum(day); + } + } else { + recur->addYearlyNum(incidence->dtStart().date().month()); + } + } + break; + default: + ; + break; + } +} + +void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence) +{ + //kdDebug(5800) << "Read alarm for " << incidence->summary() << endl; + + Alarm* ialarm = incidence->newAlarm(); + ialarm->setRepeatCount(0); + ialarm->setEnabled(true); + + // Determine the alarm's action type + icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY); + if ( !p ) { + return; + } + + icalproperty_action action = icalproperty_get_action(p); + Alarm::Type type = Alarm::Display; + switch ( action ) { + case ICAL_ACTION_DISPLAY: type = Alarm::Display; break; + case ICAL_ACTION_AUDIO: type = Alarm::Audio; break; + case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure; break; + case ICAL_ACTION_EMAIL: type = Alarm::Email; break; + default: + ; + return; + } + ialarm->setType(type); + + p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY); + while (p) { + icalproperty_kind kind = icalproperty_isa(p); + + switch (kind) { + case ICAL_TRIGGER_PROPERTY: { + icaltriggertype trigger = icalproperty_get_trigger(p); + if (icaltime_is_null_time(trigger.time)) { + if (icaldurationtype_is_null_duration(trigger.duration)) { + kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl; + } else { + Duration duration = icaldurationtype_as_int( trigger.duration ); + icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER); + if (param && icalparameter_get_related(param) == ICAL_RELATED_END) + ialarm->setEndOffset(duration); + else + ialarm->setStartOffset(duration); + } + } else { + ialarm->setTime(readICalDateTime(trigger.time)); + } + break; + } + case ICAL_DURATION_PROPERTY: { + icaldurationtype duration = icalproperty_get_duration(p); + ialarm->setSnoozeTime(icaldurationtype_as_int(duration)/60); + break; + } + case ICAL_REPEAT_PROPERTY: + ialarm->setRepeatCount(icalproperty_get_repeat(p)); + break; + + // Only in DISPLAY and EMAIL and PROCEDURE alarms + case ICAL_DESCRIPTION_PROPERTY: { + QString description = QString::fromUtf8(icalproperty_get_description(p)); + switch ( action ) { + case ICAL_ACTION_DISPLAY: + ialarm->setText( description ); + break; + case ICAL_ACTION_PROCEDURE: + ialarm->setProgramArguments( description ); + break; + case ICAL_ACTION_EMAIL: + ialarm->setMailText( description ); + break; + default: + break; + } + break; + } + // Only in EMAIL alarm + case ICAL_SUMMARY_PROPERTY: + ialarm->setMailSubject(QString::fromUtf8(icalproperty_get_summary(p))); + break; + + // Only in EMAIL alarm + case ICAL_ATTENDEE_PROPERTY: { + QString email = QString::fromUtf8(icalproperty_get_attendee(p)); + QString name; + icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER); + if (param) { + name = QString::fromUtf8(icalparameter_get_cn(param)); + } + ialarm->addMailAddress(Person(name, email)); + break; + } + // Only in AUDIO and EMAIL and PROCEDURE alarms + case ICAL_ATTACH_PROPERTY: { + icalattachtype *attach = icalproperty_get_attach(p); + QString url = QFile::decodeName(icalattachtype_get_url(attach)); + switch ( action ) { + case ICAL_ACTION_AUDIO: + ialarm->setAudioFile( url ); + break; + case ICAL_ACTION_PROCEDURE: + ialarm->setProgramFile( url ); + break; + case ICAL_ACTION_EMAIL: + ialarm->addMailAttachment( url ); + break; + default: + break; + } + break; + } + default: + break; + } + + p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY); + } + + // custom properties + readCustomProperties(alarm, ialarm); + + // TODO: check for consistency of alarm properties +} + +icaltimetype ICalFormatImpl::writeICalDate(const QDate &date) +{ + icaltimetype t; + + t.year = date.year(); + t.month = date.month(); + t.day = date.day(); + + t.hour = 0; + t.minute = 0; + t.second = 0; + + t.is_date = 1; + + t.is_utc = 0; + + t.zone = 0; + + return t; +} + +icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &dt ) +{ + icaltimetype t; + t.is_date = 0; + t.zone = 0; + QDateTime datetime; + if ( mParent->utc() ) { + int offset = KGlobal::locale()->localTimeOffset( dt ); + datetime = dt.addSecs ( -offset*60); + t.is_utc = 1; + } + else { + datetime = dt; + t.is_utc = 0; + + } + t.year = datetime.date().year(); + t.month = datetime.date().month(); + t.day = datetime.date().day(); + + t.hour = datetime.time().hour(); + t.minute = datetime.time().minute(); + t.second = datetime.time().second(); + + //qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() ); + +// if ( mParent->utc() ) { +// datetime = KGlobal::locale()->localTime( dt ); +// qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() ); +// if (mParent->timeZoneId().isEmpty()) +// t = icaltime_as_utc(t, 0); +// else +// t = icaltime_as_utc(t,mParent->timeZoneId().local8Bit()); +// } + + return t; +} + +QDateTime ICalFormatImpl::readICalDateTime(icaltimetype t) +{ + QDateTime dt (QDate(t.year,t.month,t.day), + QTime(t.hour,t.minute,t.second) ); + + if (t.is_utc) { + int offset = KGlobal::locale()->localTimeOffset( dt ); + dt = dt.addSecs ( offset*60); + } + + return dt; +} + +QDate ICalFormatImpl::readICalDate(icaltimetype t) +{ + return QDate(t.year,t.month,t.day); +} + +icaldurationtype ICalFormatImpl::writeICalDuration(int seconds) +{ + icaldurationtype d; + + d.weeks = seconds % gSecondsPerWeek; + seconds -= d.weeks * gSecondsPerWeek; + d.days = seconds % gSecondsPerDay; + seconds -= d.days * gSecondsPerDay; + d.hours = seconds % gSecondsPerHour; + seconds -= d.hours * gSecondsPerHour; + d.minutes = seconds % gSecondsPerMinute; + seconds -= d.minutes * gSecondsPerMinute; + d.seconds = seconds; + d.is_neg = 0; + + return d; +} + +int ICalFormatImpl::readICalDuration(icaldurationtype d) +{ + int result = 0; + + result += d.weeks * gSecondsPerWeek; + result += d.days * gSecondsPerDay; + result += d.hours * gSecondsPerHour; + result += d.minutes * gSecondsPerMinute; + result += d.seconds; + + if (d.is_neg) result *= -1; + + return result; +} + +icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal) +{ + icalcomponent *calendar; + + // Root component + calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT); + + icalproperty *p; + + // Product Identifier + p = icalproperty_new_prodid(CalFormat::productId().utf8()); + icalcomponent_add_property(calendar,p); + + // TODO: Add time zone + + // iCalendar version (2.0) + p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION)); + icalcomponent_add_property(calendar,p); + + // Custom properties + if( cal != 0 ) + writeCustomProperties(calendar, cal); + + return calendar; +} + + + +// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc. +// and break it down from its tree-like format into the dictionary format +// that is used internally in the ICalFormatImpl. +bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar) +{ + // this function will populate the caldict dictionary and other event + // lists. It turns vevents into Events and then inserts them. + + if (!calendar) return false; + +// TODO: check for METHOD +#if 0 + if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) { + char *methodType = 0; + methodType = fakeCString(vObjectUStringZValue(curVO)); + if (mEnableDialogs) + KMessageBox::information(mTopWidget, + i18n("This calendar is an iTIP transaction of type \"%1\".") + .arg(methodType), + i18n("%1: iTIP Transaction").arg(CalFormat::application())); + delete methodType; + } +#endif + + icalproperty *p; + + p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY); + if (!p) { +// TODO: does no PRODID really matter? +// mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); +// return false; + mLoadedProductId = ""; + mCalendarVersion = 0; + } else { + mLoadedProductId = QString::fromUtf8(icalproperty_get_prodid(p)); + mCalendarVersion = CalFormat::calendarVersion(mLoadedProductId); + + delete mCompat; + mCompat = CompatFactory::createCompat( mLoadedProductId ); + } + +// TODO: check for unknown PRODID +#if 0 + if (!mCalendarVersion + && CalFormat::productId() != mLoadedProductId) { + // warn the user that we might have trouble reading non-known calendar. + if (mEnableDialogs) + KMessageBox::information(mTopWidget, + i18n("This vCalendar file was not created by KOrganizer " + "or any other product we support. Loading anyway..."), + i18n("%1: Unknown vCalendar Vendor").arg(CalFormat::application())); + } +#endif + + p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY); + if (!p) { + mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); + return false; + } else { + const char *version = icalproperty_get_version(p); + + if (strcmp(version,"1.0") == 0) { + mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1, + i18n("Expected iCalendar format"))); + return false; + } else if (strcmp(version,"2.0") != 0) { + mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); + return false; + } + } + + +// TODO: check for calendar format version +#if 0 + // warn the user we might have trouble reading this unknown version. + if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) { + char *s = fakeCString(vObjectUStringZValue(curVO)); + if (strcmp(_VCAL_VERSION, s) != 0) + if (mEnableDialogs) + KMessageBox::sorry(mTopWidget, + i18n("This vCalendar file has version %1.\n" + "We only support %2.") + .arg(s).arg(_VCAL_VERSION), + i18n("%1: Unknown vCalendar Version").arg(CalFormat::application())); + deleteStr(s); + } +#endif + + // custom properties + readCustomProperties(calendar, cal); + +// TODO: set time zone +#if 0 + // set the time zone + if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) { + char *s = fakeCString(vObjectUStringZValue(curVO)); + cal->setTimeZone(s); + deleteStr(s); + } +#endif + + // Store all events with a relatedTo property in a list for post-processing + mEventsRelate.clear(); + mTodosRelate.clear(); + // TODO: make sure that only actually added ecvens go to this lists. + + icalcomponent *c; + + // Iterate through all todos + c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT); + while (c) { +// kdDebug(5800) << "----Todo found" << endl; + Todo *todo = readTodo(c); + if (!cal->todo(todo->uid())) cal->addTodo(todo); + c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT); + } + + // Iterate through all events + c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT); + while (c) { +// kdDebug(5800) << "----Event found" << endl; + Event *event = readEvent(c); + if (!cal->event(event->uid())) cal->addEvent(event); + c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT); + } + + // Iterate through all journals + c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT); + while (c) { +// kdDebug(5800) << "----Journal found" << endl; + Journal *journal = readJournal(c); + if (!cal->journal(journal->uid())) cal->addJournal(journal); + c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT); + } + +#if 0 + initPropIterator(&i, vcal); + + // go through all the vobjects in the vcal + while (moreIteration(&i)) { + curVO = nextVObject(&i); + + /************************************************************************/ + + // now, check to see that the object is an event or todo. + if (strcmp(vObjectName(curVO), VCEventProp) == 0) { + + if ((curVOProp = isAPropertyOf(curVO, KPilotStatusProp)) != 0) { + char *s; + s = fakeCString(vObjectUStringZValue(curVOProp)); + // check to see if event was deleted by the kpilot conduit + if (atoi(s) == Event::SYNCDEL) { + deleteStr(s); + goto SKIP; + } + deleteStr(s); + } + + // this code checks to see if we are trying to read in an event + // that we already find to be in the calendar. If we find this + // to be the case, we skip the event. + if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) { + char *s = fakeCString(vObjectUStringZValue(curVOProp)); + QString tmpStr(s); + deleteStr(s); + + if (cal->event(tmpStr)) { + goto SKIP; + } + if (cal->todo(tmpStr)) { + goto SKIP; + } + } + + if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) && + (!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) { + kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl; + goto SKIP; + } + + anEvent = VEventToEvent(curVO); + // we now use addEvent instead of insertEvent so that the + // signal/slot get connected. + if (anEvent) + cal->addEvent(anEvent); + else { + // some sort of error must have occurred while in translation. + goto SKIP; + } + } else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) { + anEvent = VTodoToEvent(curVO); + cal->addTodo(anEvent); + } else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) || + (strcmp(vObjectName(curVO), VCProdIdProp) == 0) || + (strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) { + // do nothing, we know these properties and we want to skip them. + // we have either already processed them or are ignoring them. + ; + } else { + ; + } + SKIP: + ; + } // while +#endif + + // Post-Process list of events with relations, put Event objects in relation + Event *ev; + for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) { + ev->setRelatedTo(cal->event(ev->relatedToUid())); + } + Todo *todo; + for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) { + todo->setRelatedTo(cal->todo(todo->relatedToUid())); + } + + return true; +} + +QString ICalFormatImpl::extractErrorProperty(icalcomponent *c) +{ +// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " +// << icalcomponent_as_ical_string(c) << endl; + + QString errorMessage; + + icalproperty *error; + error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY); + while(error) { + errorMessage += icalproperty_get_xlicerror(error); + errorMessage += "\n"; + error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY); + } + +// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl; + + return errorMessage; +} + +void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r) +{ + int i; + + + if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { + int index = 0; + QString out = " By Day: "; + while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + out.append(QString::number(i) + " "); + } + } + if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { + int index = 0; + QString out = " By Month Day: "; + while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + out.append(QString::number(i) + " "); + } + } + if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { + int index = 0; + QString out = " By Year Day: "; + while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + out.append(QString::number(i) + " "); + } + } + if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { + int index = 0; + QString out = " By Month: "; + while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + out.append(QString::number(i) + " "); + } + } + if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { + int index = 0; + QString out = " By Set Pos: "; + while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { + out.append(QString::number(i) + " "); + } + } +} + +icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence, + Scheduler::Method method) +{ + icalcomponent *message = createCalendarComponent(); + + icalproperty_method icalmethod = ICAL_METHOD_NONE; + + switch (method) { + case Scheduler::Publish: + icalmethod = ICAL_METHOD_PUBLISH; + break; + case Scheduler::Request: + icalmethod = ICAL_METHOD_REQUEST; + break; + case Scheduler::Refresh: + icalmethod = ICAL_METHOD_REFRESH; + break; + case Scheduler::Cancel: + icalmethod = ICAL_METHOD_CANCEL; + break; + case Scheduler::Add: + icalmethod = ICAL_METHOD_ADD; + break; + case Scheduler::Reply: + icalmethod = ICAL_METHOD_REPLY; + break; + case Scheduler::Counter: + icalmethod = ICAL_METHOD_COUNTER; + break; + case Scheduler::Declinecounter: + icalmethod = ICAL_METHOD_DECLINECOUNTER; + break; + default: + + return message; + } + + icalcomponent_add_property(message,icalproperty_new_method(icalmethod)); + + // TODO: check, if dynamic cast is required + if(incidence->type() == "Todo") { + Todo *todo = static_cast<Todo *>(incidence); + icalcomponent_add_component(message,writeTodo(todo)); + } + if(incidence->type() == "Event") { + Event *event = static_cast<Event *>(incidence); + icalcomponent_add_component(message,writeEvent(event)); + } + if(incidence->type() == "FreeBusy") { + FreeBusy *freebusy = static_cast<FreeBusy *>(incidence); + icalcomponent_add_component(message,writeFreeBusy(freebusy, method)); + } + + return message; +} diff --git a/libkcal/icalformatimpl.h b/libkcal/icalformatimpl.h new file mode 100644 index 0000000..2f32365 --- a/dev/null +++ b/libkcal/icalformatimpl.h @@ -0,0 +1,109 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef ICALFORMATIMPL_H +#define ICALFORMATIMPL_H + +#include <qstring.h> + +#include "scheduler.h" +#include "freebusy.h" + +extern "C" { + #include <ical.h> + #include <icalss.h> +} + +namespace KCal { + +class Compat; + +/** + This class provides the libical dependent functions for ICalFormat. +*/ +class ICalFormatImpl { + public: + /** Create new iCal format for calendar object */ + ICalFormatImpl( ICalFormat *parent ); + virtual ~ICalFormatImpl(); + + bool populate( Calendar *, icalcomponent *fs); + + icalcomponent *writeIncidence(Incidence *incidence); + icalcomponent *writeTodo(Todo *todo); + icalcomponent *writeEvent(Event *event); + icalcomponent *writeFreeBusy(FreeBusy *freebusy, + Scheduler::Method method); + icalcomponent *writeJournal(Journal *journal); + void writeIncidence(icalcomponent *parent,Incidence *incidence); + icalproperty *writeAttendee(Attendee *attendee); + icalproperty *writeAttachment(Attachment *attach); + icalproperty *writeRecurrenceRule(Recurrence *); + icalproperty *writeAlarm(Alarm *alarm); + + QString extractErrorProperty(icalcomponent *); + Todo *readTodo(icalcomponent *vtodo); + Event *readEvent(icalcomponent *vevent); + FreeBusy *readFreeBusy(icalcomponent *vfreebusy); + Journal *readJournal(icalcomponent *vjournal); + Attendee *readAttendee(icalproperty *attendee); + Attachment *readAttachment(icalproperty *attach); + void readIncidence(icalcomponent *parent,Incidence *incidence); + void readRecurrenceRule(struct icalrecurrencetype rrule,Incidence *event); + void readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur,Incidence *event ); + void readAlarm(icalcomponent *alarm,Incidence *incidence); + /** Return the PRODID string loaded from calendar file */ + const QString &loadedProductId() { return mLoadedProductId; } + + icaltimetype writeICalDate(const QDate &); + QDate readICalDate(icaltimetype); + icaltimetype writeICalDateTime(const QDateTime &); + QDateTime readICalDateTime(icaltimetype); + icaldurationtype writeICalDuration(int seconds); + int readICalDuration(icaldurationtype); + icalcomponent *createCalendarComponent(Calendar * = 0); + icalcomponent *createScheduleComponent(IncidenceBase *,Scheduler::Method); + + private: + void writeIncidenceBase(icalcomponent *parent,IncidenceBase *); + void readIncidenceBase(icalcomponent *parent,IncidenceBase *); + void writeCustomProperties(icalcomponent *parent,CustomProperties *); + void readCustomProperties(icalcomponent *parent,CustomProperties *); + void dumpIcalRecurrence(icalrecurrencetype); + + ICalFormat *mParent; + Calendar *mCalendar; + + QString mLoadedProductId; // PRODID string loaded from calendar file + int mCalendarVersion; // determines backward compatibility mode on read + + QPtrList<Event> mEventsRelate; // events with relations + QPtrList<Todo> mTodosRelate; // todos with relations + + static const int mSecondsPerWeek; + static const int mSecondsPerDay; + static const int mSecondsPerHour; + static const int mSecondsPerMinute; + + Compat *mCompat; +}; + +} + +#endif diff --git a/libkcal/icalformatimpl.h.bup b/libkcal/icalformatimpl.h.bup new file mode 100644 index 0000000..37cf857 --- a/dev/null +++ b/libkcal/icalformatimpl.h.bup @@ -0,0 +1,109 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef ICALFORMATIMPL_H +#define ICALFORMATIMPL_H + +#include <qstring.h> + +#include "scheduler.h" +#include "freebusy.h" + +extern "C" { + #include <ical.h> + #include <icalss.h> +} + +namespace KCal { + +class Compat; + +/** + This class provides the libical dependent functions for ICalFormat. +*/ +class ICalFormatImpl { + public: + /** Create new iCal format for calendar object */ + ICalFormatImpl( ICalFormat *parent ); + virtual ~ICalFormatImpl(); + + bool populate( Calendar *, icalcomponent *fs); + + icalcomponent *writeIncidence(Incidence *incidence); + icalcomponent *writeTodo(Todo *todo); + icalcomponent *writeEvent(Event *event); + icalcomponent *writeFreeBusy(FreeBusy *freebusy, + Scheduler::Method method); + icalcomponent *writeJournal(Journal *journal); + void writeIncidence(icalcomponent *parent,Incidence *incidence); + icalproperty *writeAttendee(Attendee *attendee); + icalproperty *writeAttachment(Attachment *attach); + icalproperty *writeRecurrenceRule(Recurrence *); + icalproperty *writeAlarm(Alarm *alarm); + + QString extractErrorProperty(icalcomponent *); + Todo *readTodo(icalcomponent *vtodo); + Event *readEvent(icalcomponent *vevent); + FreeBusy *readFreeBusy(icalcomponent *vfreebusy); + Journal *readJournal(icalcomponent *vjournal); + Attendee *readAttendee(icalproperty *attendee); + Attachment *readAttachment(icalproperty *attach); + void readIncidence(icalcomponent *parent,Incidence *incidence); + void readRecurrenceRule(icalproperty *rrule,Incidence *event); + void readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur ); + void readAlarm(icalcomponent *alarm,Incidence *incidence); + /** Return the PRODID string loaded from calendar file */ + const QString &loadedProductId() { return mLoadedProductId; } + + icaltimetype writeICalDate(const QDate &); + QDate readICalDate(icaltimetype); + icaltimetype writeICalDateTime(const QDateTime &); + QDateTime readICalDateTime(icaltimetype); + icaldurationtype writeICalDuration(int seconds); + int readICalDuration(icaldurationtype); + icalcomponent *createCalendarComponent(Calendar * = 0); + icalcomponent *createScheduleComponent(IncidenceBase *,Scheduler::Method); + + private: + void writeIncidenceBase(icalcomponent *parent,IncidenceBase *); + void readIncidenceBase(icalcomponent *parent,IncidenceBase *); + void writeCustomProperties(icalcomponent *parent,CustomProperties *); + void readCustomProperties(icalcomponent *parent,CustomProperties *); + void dumpIcalRecurrence(icalrecurrencetype); + + ICalFormat *mParent; + Calendar *mCalendar; + + QString mLoadedProductId; // PRODID string loaded from calendar file + int mCalendarVersion; // determines backward compatibility mode on read + + QPtrList<Event> mEventsRelate; // events with relations + QPtrList<Todo> mTodosRelate; // todos with relations + + static const int mSecondsPerWeek; + static const int mSecondsPerDay; + static const int mSecondsPerHour; + static const int mSecondsPerMinute; + + Compat *mCompat; +}; + +} + +#endif diff --git a/libkcal/imipscheduler.cpp b/libkcal/imipscheduler.cpp new file mode 100644 index 0000000..e186f8e --- a/dev/null +++ b/libkcal/imipscheduler.cpp @@ -0,0 +1,58 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// +// IMIPScheduler - iMIP implementation of iTIP methods +// + +#include "event.h" +#include "icalformat.h" + +#include "imipscheduler.h" + +using namespace KCal; + +IMIPScheduler::IMIPScheduler(Calendar *calendar) + : Scheduler(calendar) +{ +} + +IMIPScheduler::~IMIPScheduler() +{ +} + +bool IMIPScheduler::publish (IncidenceBase *incidence,const QString &recipients) +{ + return false; +} + +bool IMIPScheduler::performTransaction(IncidenceBase *incidence,Method method) +{ + mFormat->createScheduleMessage(incidence,method); + + return false; +} + +QPtrList<ScheduleMessage> IMIPScheduler::retrieveTransactions() +{ + QPtrList<ScheduleMessage> messageList; + + return messageList; +} diff --git a/libkcal/imipscheduler.h b/libkcal/imipscheduler.h new file mode 100644 index 0000000..f142060 --- a/dev/null +++ b/libkcal/imipscheduler.h @@ -0,0 +1,49 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef IMIPSCHEDULER_H +#define IMIPSCHEDULER_H +// +// iMIP implementation of iTIP methods +// + +#include <qptrlist.h> + +#include "scheduler.h" + +namespace KCal { + +/* + This class implements the iTIP interface using the email interface specified + as iMIP. +*/ +class IMIPScheduler : public Scheduler { + public: + IMIPScheduler(Calendar *); + virtual ~IMIPScheduler(); + + bool publish (IncidenceBase *incidence,const QString &recipients); + bool performTransaction(IncidenceBase *incidence,Method method); + QPtrList<ScheduleMessage> retrieveTransactions(); +}; + +} + +#endif // IMIPSCHEDULER_H + diff --git a/libkcal/incidence.cpp b/libkcal/incidence.cpp new file mode 100644 index 0000000..d9bda64 --- a/dev/null +++ b/libkcal/incidence.cpp @@ -0,0 +1,594 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +#include "calformat.h" + +#include "incidence.h" +#include "todo.h" + +using namespace KCal; + +Incidence::Incidence() : + IncidenceBase(), + mRelatedTo(0), mSecrecy(SecrecyPublic), mPriority(3) +{ + mRecurrence = new Recurrence(this); + mCancelled = false; + recreate(); + mHasStartDate = true; + mAlarms.setAutoDelete(true); + mAttachments.setAutoDelete(true); +} + +Incidence::Incidence( const Incidence &i ) : IncidenceBase( i ) +{ +// TODO: reenable attributes currently commented out. + mRevision = i.mRevision; + mCreated = i.mCreated; + mDescription = i.mDescription; + mSummary = i.mSummary; + mCategories = i.mCategories; +// Incidence *mRelatedTo; Incidence *mRelatedTo; + mRelatedTo = 0; + mRelatedToUid = i.mRelatedToUid; +// QPtrList<Incidence> mRelations; QPtrList<Incidence> mRelations; + mExDates = i.mExDates; + mAttachments = i.mAttachments; + mResources = i.mResources; + mSecrecy = i.mSecrecy; + mPriority = i.mPriority; + mLocation = i.mLocation; + mCancelled = i.mCancelled; + mHasStartDate = i.mHasStartDate; + QPtrListIterator<Alarm> it( i.mAlarms ); + const Alarm *a; + while( (a = it.current()) ) { + Alarm *b = new Alarm( *a ); + b->setParent( this ); + mAlarms.append( b ); + + ++it; + } + mAlarms.setAutoDelete(true); + + mRecurrence = new Recurrence( *(i.mRecurrence), this ); +} + +Incidence::~Incidence() +{ + + Incidence *ev; + QPtrList<Incidence> Relations = relations(); + for (ev=Relations.first();ev;ev=Relations.next()) { + if (ev->relatedTo() == this) ev->setRelatedTo(0); + } + if (relatedTo()) relatedTo()->removeRelation(this); + delete mRecurrence; + +} + +bool Incidence::cancelled() const +{ + return mCancelled; +} +void Incidence::setCancelled( bool b ) +{ + mCancelled = b; + updated(); +} +bool Incidence::hasStartDate() const +{ + return mHasStartDate; +} + +void Incidence::setHasStartDate(bool f) +{ + if (mReadOnly) return; + mHasStartDate = f; + updated(); +} + +// A string comparison that considers that null and empty are the same +static bool stringCompare( const QString& s1, const QString& s2 ) +{ + if ( s1.isEmpty() && s2.isEmpty() ) + return true; + return s1 == s2; +} + +bool KCal::operator==( const Incidence& i1, const Incidence& i2 ) +{ + + if( i1.alarms().count() != i2.alarms().count() ) { + return false; // no need to check further + } + if ( i1.alarms().count() > 0 ) { + if ( !( *(i1.alarms().first()) == *(i2.alarms().first())) ) + { + qDebug("alarm not equal "); + return false; + } + } +#if 0 + QPtrListIterator<Alarm> a1( i1.alarms() ); + QPtrListIterator<Alarm> a2( i2.alarms() ); + for( ; a1.current() && a2.current(); ++a1, ++a2 ) { + if( *a1.current() == *a2.current() ) { + continue; + } + else { + return false; + } + } +#endif + + if ( ! operator==( (const IncidenceBase&)i1, (const IncidenceBase&)i2 ) ) + return false; + if ( i1.hasStartDate() == i2.hasStartDate() ) { + if ( i1.hasStartDate() ) { + if ( i1.dtStart() != i2.dtStart() ) + return false; + } + } else { + return false; + } + if (!( *i1.recurrence() == *i2.recurrence()) ) { + qDebug("recurrence is NOT equal "); + return false; + } + return + // i1.created() == i2.created() && + stringCompare( i1.description(), i2.description() ) && + stringCompare( i1.summary(), i2.summary() ) && + i1.categories() == i2.categories() && + // no need to compare mRelatedTo + stringCompare( i1.relatedToUid(), i2.relatedToUid() ) && + // i1.relations() == i2.relations() && + i1.exDates() == i2.exDates() && + i1.attachments() == i2.attachments() && + i1.resources() == i2.resources() && + i1.secrecy() == i2.secrecy() && + i1.priority() == i2.priority() && + stringCompare( i1.location(), i2.location() ); +} + + +void Incidence::recreate() +{ + setCreated(QDateTime::currentDateTime()); + + setUid(CalFormat::createUniqueId()); + + setRevision(0); + + setLastModified(QDateTime::currentDateTime()); +} + +void Incidence::setReadOnly( bool readOnly ) +{ + IncidenceBase::setReadOnly( readOnly ); + recurrence()->setRecurReadOnly( readOnly); +} + +void Incidence::setCreated(QDateTime created) +{ + if (mReadOnly) return; + mCreated = getEvenTime(created); +} + +QDateTime Incidence::created() const +{ + return mCreated; +} + +void Incidence::setRevision(int rev) +{ + if (mReadOnly) return; + mRevision = rev; + + updated(); +} + +int Incidence::revision() const +{ + return mRevision; +} + +void Incidence::setDtStart(const QDateTime &dtStart) +{ + + QDateTime dt = getEvenTime(dtStart); + recurrence()->setRecurStart( dt); + IncidenceBase::setDtStart( dt ); +} + +void Incidence::setDescription(const QString &description) +{ + if (mReadOnly) return; + mDescription = description; + updated(); +} + +QString Incidence::description() const +{ + return mDescription; +} + + +void Incidence::setSummary(const QString &summary) +{ + if (mReadOnly) return; + mSummary = summary; + updated(); +} + +QString Incidence::summary() const +{ + return mSummary; +} + +void Incidence::setCategories(const QStringList &categories) +{ + if (mReadOnly) return; + mCategories = categories; + updated(); +} + +// TODO: remove setCategories(QString) function +void Incidence::setCategories(const QString &catStr) +{ + if (mReadOnly) return; + mCategories.clear(); + + if (catStr.isEmpty()) return; + + mCategories = QStringList::split(",",catStr); + + QStringList::Iterator it; + for(it = mCategories.begin();it != mCategories.end(); ++it) { + *it = (*it).stripWhiteSpace(); + } + + updated(); +} + +QStringList Incidence::categories() const +{ + return mCategories; +} + +QString Incidence::categoriesStr() +{ + return mCategories.join(","); +} + +void Incidence::setRelatedToUid(const QString &relatedToUid) +{ + if (mReadOnly) return; + mRelatedToUid = relatedToUid; +} + +QString Incidence::relatedToUid() const +{ + return mRelatedToUid; +} + +void Incidence::setRelatedTo(Incidence *relatedTo) +{ + //qDebug("Incidence::setRelatedTo %d ", relatedTo); + //qDebug("setRelatedTo(Incidence *relatedTo) %s %s", summary().latin1(), relatedTo->summary().latin1() ); + if (mReadOnly || mRelatedTo == relatedTo) return; + if(mRelatedTo) { + // updated(); + mRelatedTo->removeRelation(this); + } + mRelatedTo = relatedTo; + if (mRelatedTo) mRelatedTo->addRelation(this); +} + +Incidence *Incidence::relatedTo() const +{ + return mRelatedTo; +} + +QPtrList<Incidence> Incidence::relations() const +{ + return mRelations; +} + +void Incidence::addRelation(Incidence *event) +{ + if( mRelations.findRef( event ) == -1 ) { + mRelations.append(event); + //updated(); + } +} + +void Incidence::removeRelation(Incidence *event) +{ + + mRelations.removeRef(event); + +// if (event->getRelatedTo() == this) event->setRelatedTo(0); +} + +bool Incidence::recursOn(const QDate &qd) const +{ + if (recurrence()->recursOnPure(qd) && !isException(qd)) return true; + else return false; +} + +void Incidence::setExDates(const DateList &exDates) +{ + if (mReadOnly) return; + mExDates = exDates; + + recurrence()->setRecurExDatesCount(mExDates.count()); + + updated(); +} + +void Incidence::addExDate(const QDate &date) +{ + if (mReadOnly) return; + mExDates.append(date); + + recurrence()->setRecurExDatesCount(mExDates.count()); + + updated(); +} + +DateList Incidence::exDates() const +{ + return mExDates; +} + +bool Incidence::isException(const QDate &date) const +{ + DateList::ConstIterator it; + for( it = mExDates.begin(); it != mExDates.end(); ++it ) { + if ( (*it) == date ) { + return true; + } + } + + return false; +} + +void Incidence::addAttachment(Attachment *attachment) +{ + if (mReadOnly || !attachment) return; + mAttachments.append(attachment); + updated(); +} + +void Incidence::deleteAttachment(Attachment *attachment) +{ + mAttachments.removeRef(attachment); +} + +void Incidence::deleteAttachments(const QString& mime) +{ + Attachment *at = mAttachments.first(); + while (at) { + if (at->mimeType() == mime) + mAttachments.remove(); + else + at = mAttachments.next(); + } +} + +QPtrList<Attachment> Incidence::attachments() const +{ + return mAttachments; +} + +QPtrList<Attachment> Incidence::attachments(const QString& mime) const +{ + QPtrList<Attachment> attachments; + QPtrListIterator<Attachment> it( mAttachments ); + Attachment *at; + while ( (at = it.current()) ) { + if (at->mimeType() == mime) + attachments.append(at); + ++it; + } + + return attachments; +} + +void Incidence::setResources(const QStringList &resources) +{ + if (mReadOnly) return; + mResources = resources; + updated(); +} + +QStringList Incidence::resources() const +{ + return mResources; +} + + +void Incidence::setPriority(int priority) +{ + if (mReadOnly) return; + mPriority = priority; + updated(); +} + +int Incidence::priority() const +{ + return mPriority; +} + +void Incidence::setSecrecy(int sec) +{ + if (mReadOnly) return; + mSecrecy = sec; + updated(); +} + +int Incidence::secrecy() const +{ + return mSecrecy; +} + +QString Incidence::secrecyStr() const +{ + return secrecyName(mSecrecy); +} + +QString Incidence::secrecyName(int secrecy) +{ + switch (secrecy) { + case SecrecyPublic: + return i18n("Public"); + break; + case SecrecyPrivate: + return i18n("Private"); + break; + case SecrecyConfidential: + return i18n("Confidential"); + break; + default: + return i18n("Undefined"); + break; + } +} + +QStringList Incidence::secrecyList() +{ + QStringList list; + list << secrecyName(SecrecyPublic); + list << secrecyName(SecrecyPrivate); + list << secrecyName(SecrecyConfidential); + + return list; +} + + +QPtrList<Alarm> Incidence::alarms() const +{ + return mAlarms; +} + +Alarm* Incidence::newAlarm() +{ + Alarm* alarm = new Alarm(this); + mAlarms.append(alarm); +// updated(); + return alarm; +} + +void Incidence::addAlarm(Alarm *alarm) +{ + mAlarms.append(alarm); + updated(); +} + +void Incidence::removeAlarm(Alarm *alarm) +{ + mAlarms.removeRef(alarm); + updated(); +} + +void Incidence::clearAlarms() +{ + mAlarms.clear(); + updated(); +} + +bool Incidence::isAlarmEnabled() const +{ + Alarm* alarm; + for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) { + if (alarm->enabled()) + return true; + } + return false; +} + +Recurrence *Incidence::recurrence() const +{ + return mRecurrence; +} + +void Incidence::setLocation(const QString &location) +{ + if (mReadOnly) return; + mLocation = location; + updated(); +} + +QString Incidence::location() const +{ + return mLocation; +} + +ushort Incidence::doesRecur() const +{ + if ( mRecurrence ) return mRecurrence->doesRecur(); + else return Recurrence::rNone; +} + +QDateTime Incidence::getNextOccurence( const QDateTime& dt, bool* ok ) const +{ + QDateTime incidenceStart = dt; + *ok = false; + if ( doesRecur() ) { + bool last; + recurrence()->getPreviousDateTime( incidenceStart , &last ); + int count = 0; + if ( !last ) { + while ( !last ) { + ++count; + incidenceStart = recurrence()->getNextDateTime( incidenceStart, &last ); + if ( recursOn( incidenceStart.date() ) ) { + last = true; // exit while llop + } else { + if ( last ) { // no alarm on last recurrence + return QDateTime (); + } + int year = incidenceStart.date().year(); + // workaround for bug in recurrence + if ( count == 100 || year < 1980 || year > 5000 ) { + return QDateTime (); + } + incidenceStart = incidenceStart.addSecs( 1 ); + } + } + } else { + return QDateTime (); + } + } else { + if ( hasStartDate () ) { + incidenceStart = dtStart(); + + } + } + if ( incidenceStart > dt ) + *ok = true; + return incidenceStart; +} diff --git a/libkcal/incidence.h b/libkcal/incidence.h new file mode 100644 index 0000000..d1972cb --- a/dev/null +++ b/libkcal/incidence.h @@ -0,0 +1,298 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef INCIDENCE_H +#define INCIDENCE_H +// +// Incidence - base class of calendaring components +// + +#include <qdatetime.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +#include "recurrence.h" +#include "alarm.h" +#include "attachment.h" +#include "listbase.h" +#include "incidencebase.h" + +namespace KCal { + +class Event; +class Todo; +class Journal; + +/** + This class provides the base class common to all calendar components. +*/ +class Incidence : public IncidenceBase +{ + public: + /** + This class provides the interface for a visitor of calendar components. It + serves as base class for concrete visitors, which implement certain actions on + calendar components. It allows to add functions, which operate on the concrete + types of calendar components, without changing the calendar component classes. + */ + class Visitor + { + public: + /** Destruct Incidence::Visitor */ + virtual ~Visitor() {} + + /** + Reimplement this function in your concrete subclass of IncidenceVisitor to perform actions + on an Event object. + */ + virtual bool visit(Event *) { return false; } + /** + Reimplement this function in your concrete subclass of IncidenceVisitor to perform actions + on an Todo object. + */ + virtual bool visit(Todo *) { return false; } + /** + Reimplement this function in your concrete subclass of IncidenceVisitor to perform actions + on an Journal object. + */ + virtual bool visit(Journal *) { return false; } + + protected: + /** Constructor is protected to prevent direct creation of visitor base class. */ + Visitor() {} + }; + + /** + This class implements a visitor for adding an Incidence to a resource + supporting addEvent(), addTodo() and addJournal() calls. + */ + template<class T> + class AddVisitor : public Visitor + { + public: + AddVisitor( T *r ) : mResource( r ) {} + bool visit( Event *e ) { return mResource->addEvent( e ); } + bool visit( Todo *t ) { return mResource->addTodo( t ); } + bool visit( Journal *j ) { return mResource->addJournal( j ); } + + private: + T *mResource; + }; + + /** enumeration for describing an event's secrecy. */ + enum { SecrecyPublic = 0, SecrecyPrivate = 1, SecrecyConfidential = 2 }; + typedef ListBase<Incidence> List; + Incidence(); + Incidence(const Incidence &); + ~Incidence(); + + /** + Accept IncidenceVisitor. A class taking part in the visitor mechanism has to + provide this implementation: + <pre> + bool accept(Visitor &v) { return v.visit(this); } + </pre> + */ + virtual bool accept(Visitor &) { return false; } + + virtual Incidence *clone() = 0; + + virtual QDateTime getNextAlarmDateTime( bool * ok, int * offset ) const = 0; + void setReadOnly( bool ); + + /** + Recreate event. The event is made a new unique event, but already stored + event information is preserved. Sets uniquie id, creation date, last + modification date and revision number. + */ + void recreate(); + + /** set creation date */ + void setCreated(QDateTime); + /** return time and date of creation. */ + QDateTime created() const; + + /** set the number of revisions this event has seen */ + void setRevision(int rev); + /** return the number of revisions this event has seen */ + int revision() const; + + /** Set starting date/time. */ + virtual void setDtStart(const QDateTime &dtStart); + /** Return the incidence's ending date/time as a QDateTime. */ + virtual QDateTime dtEnd() const { return QDateTime(); } + + /** sets the event's lengthy description. */ + void setDescription(const QString &description); + /** returns a reference to the event's description. */ + QString description() const; + + /** sets the event's short summary. */ + void setSummary(const QString &summary); + /** returns a reference to the event's summary. */ + QString summary() const; + + /** set event's applicable categories */ + void setCategories(const QStringList &categories); + /** set event's categories based on a comma delimited string */ + void setCategories(const QString &catStr); + /** return categories in a list */ + QStringList categories() const; + /** return categories as a comma separated string */ + QString categoriesStr(); + + /** point at some other event to which the event relates. This function should + * only be used when constructing a calendar before the related Event + * exists. */ + void setRelatedToUid(const QString &); + /** what event does this one relate to? This function should + * only be used when constructing a calendar before the related Event + * exists. */ + QString relatedToUid() const; + /** point at some other event to which the event relates */ + void setRelatedTo(Incidence *relatedTo); + /** what event does this one relate to? */ + Incidence *relatedTo() const; + /** All events that are related to this event */ + QPtrList<Incidence> relations() const; + /** Add an event which is related to this event */ + void addRelation(Incidence *); + /** Remove event that is related to this event */ + void removeRelation(Incidence *); + + /** returns the list of dates which are exceptions to the recurrence rule */ + DateList exDates() const; + /** sets the list of dates which are exceptions to the recurrence rule */ + void setExDates(const DateList &_exDates); + void setExDates(const char *dates); + /** Add a date to the list of exceptions of the recurrence rule. */ + void addExDate(const QDate &date); + + /** returns true if there is an exception for this date in the recurrence + rule set, or false otherwise. */ + bool isException(const QDate &qd) const; + + /** add attachment to this event */ + void addAttachment(Attachment *attachment); + /** remove and delete a specific attachment */ + void deleteAttachment(Attachment *attachment); + /** remove and delete all attachments with this mime type */ + void deleteAttachments(const QString& mime); + /** return list of all associated attachments */ + QPtrList<Attachment> attachments() const; + /** find a list of attachments with this mime type */ + QPtrList<Attachment> attachments(const QString& mime) const; + + /** sets the event's status the value specified. See the enumeration + * above for possible values. */ + void setSecrecy(int); + /** return the event's secrecy. */ + int secrecy() const; + /** return the event's secrecy in string format. */ + QString secrecyStr() const; + /** return list of all availbale secrecy classes */ + static QStringList secrecyList(); + /** return human-readable name of secrecy class */ + static QString secrecyName(int); + + /** returns TRUE if the date specified is one on which the event will + * recur. */ + bool recursOn(const QDate &qd) const; + + // VEVENT and VTODO, but not VJOURNAL (move to EventBase class?): + + /** set resources used, such as Office, Car, etc. */ + void setResources(const QStringList &resources); + /** return list of current resources */ + QStringList resources() const; + + /** set the event's priority, 0 is undefined, 1 highest (decreasing order) */ + void setPriority(int priority); + /** get the event's priority */ + int priority() const; + + /** All alarms that are associated with this incidence */ + QPtrList<Alarm> alarms() const; + /** Create a new alarm which is associated with this incidence */ + Alarm* newAlarm(); + /** Add an alarm which is associated with this incidence */ + void addAlarm(Alarm*); + /** Remove an alarm that is associated with this incidence */ + void removeAlarm(Alarm*); + /** Remove all alarms that are associated with this incidence */ + void clearAlarms(); + /** return whether any alarm associated with this incidence is enabled */ + bool isAlarmEnabled() const; + + /** + Return the recurrence rule associated with this incidence. If there is + none, returns an appropriate (non-0) object. + */ + Recurrence *recurrence() const; + + /** + Forward to Recurrence::doesRecur(). + */ + ushort doesRecur() const; + + /** set the event's/todo's location. Do _not_ use it with journal */ + void setLocation(const QString &location); + /** return the event's/todo's location. Do _not_ use it with journal */ + QString location() const; + /** returns TRUE or FALSE depending on whether the todo has a start date */ + bool hasStartDate() const; + /** sets the event's hasStartDate value. */ + void setHasStartDate(bool f); + QDateTime getNextOccurence( const QDateTime& dt, bool* yes ) const; + bool cancelled() const; + void setCancelled( bool b ); + +protected: + QPtrList<Alarm> mAlarms; + private: + int mRevision; + bool mCancelled; + + // base components of jounal, event and todo + QDateTime mCreated; + QString mDescription; + QString mSummary; + QStringList mCategories; + Incidence *mRelatedTo; + QString mRelatedToUid; + QPtrList<Incidence> mRelations; + DateList mExDates; + QPtrList<Attachment> mAttachments; + QStringList mResources; + bool mHasStartDate; // if todo has associated start date + + int mSecrecy; + int mPriority; // 1 = highest, 2 = less, etc. + + //QPtrList<Alarm> mAlarms; + Recurrence *mRecurrence; + + QString mLocation; +}; + +bool operator==( const Incidence&, const Incidence& ); + +} + +#endif diff --git a/libkcal/incidencebase.cpp b/libkcal/incidencebase.cpp new file mode 100644 index 0000000..9479048 --- a/dev/null +++ b/libkcal/incidencebase.cpp @@ -0,0 +1,393 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +#include "calformat.h" + +#include "incidencebase.h" + +using namespace KCal; + +IncidenceBase::IncidenceBase() : + mReadOnly(false), mFloats(true), mDuration(0), mHasDuration(false), + mPilotId(0), mSyncStatus(SYNCMOD) +{ + setUid(CalFormat::createUniqueId()); + mOrganizer = ""; + mFloats = false; + mDuration = 0; + mHasDuration = false; + mPilotId = 0; + mZaurusId = -1; + mZaurusUid = 0; + mZaurusStat = 0; + mSyncStatus = 0; + mAttendees.setAutoDelete( true ); +} + +IncidenceBase::IncidenceBase(const IncidenceBase &i) : + CustomProperties( i ) +{ + mReadOnly = i.mReadOnly; + mDtStart = i.mDtStart; + mDuration = i.mDuration; + mHasDuration = i.mHasDuration; + mOrganizer = i.mOrganizer; + mUid = i.mUid; + QPtrList<Attendee> attendees = i.attendees(); + for( Attendee *a = attendees.first(); a; a = attendees.next() ) { + mAttendees.append( new Attendee( *a ) ); + } + mFloats = i.mFloats; + mLastModified = i.mLastModified; + mPilotId = i.mPilotId; + mZaurusId = i.mZaurusId; + mZaurusUid = i.mZaurusUid; + mZaurusStat = i.mZaurusStat; + mSyncStatus = i.mSyncStatus; + + // The copied object is a new one, so it isn't observed by the observer + // of the original object. + mObservers.clear(); + + mAttendees.setAutoDelete( true ); +} + +IncidenceBase::~IncidenceBase() +{ +} + + +bool KCal::operator==( const IncidenceBase& i1, const IncidenceBase& i2 ) +{ + + if( i1.attendees().count() != i2.attendees().count() ) { + return false; // no need to check further + } + if ( i1.attendees().count() > 0 ) { + Attendee * a1 = i1.attendees().first(), *a2 =i2.attendees().first() ; + while ( a1 ) { + if ( !( (*a1) == (*a2)) ) + { + //qDebug("Attendee not equal "); + return false; + } + a1 = i1.attendees().next(); + a2 = i2.attendees().next(); + } + } + //if ( i1.dtStart() != i2.dtStart() ) + // return false; +#if 0 + qDebug("1 %d ",i1.doesFloat() == i2.doesFloat() ); + qDebug("1 %d ",i1.duration() == i2.duration() ); + qDebug("3 %d ",i1.hasDuration() == i2.hasDuration() ); + qDebug("1 %d ",i1.pilotId() == i2.pilotId() ); + qDebug("1 %d %d %d",i1.syncStatus() == i2.syncStatus() , i1.syncStatus(),i2.syncStatus() ); + qDebug("6 %d ",i1.organizer() == i2.organizer() ); + +#endif + return ( i1.organizer() == i2.organizer() && + // i1.uid() == i2.uid() && + // Don't compare lastModified, otherwise the operator is not + // of much use. We are not comparing for identity, after all. + i1.doesFloat() == i2.doesFloat() && + i1.duration() == i2.duration() && + i1.hasDuration() == i2.hasDuration() && + i1.pilotId() == i2.pilotId() );// && i1.syncStatus() == i2.syncStatus() ); + // no need to compare mObserver +} + + +QDateTime IncidenceBase::getEvenTime( QDateTime dt ) +{ + QTime t = dt.time(); + dt.setTime( QTime (t.hour (), t.minute (), t.second () ) ); + return dt; +} + + +void IncidenceBase::setUid(const QString &uid) +{ + mUid = uid; + updated(); +} + +QString IncidenceBase::uid() const +{ + return mUid; +} + +void IncidenceBase::setLastModified(const QDateTime &lm) +{ + // DON'T! updated() because we call this from + // Calendar::updateEvent(). + mLastModified = getEvenTime(lm); + //qDebug("IncidenceBase::setLastModified %s ",lm.toString().latin1()); +} + +QDateTime IncidenceBase::lastModified() const +{ + return mLastModified; +} + +void IncidenceBase::setOrganizer(const QString &o) +{ + // we don't check for readonly here, because it is + // possible that by setting the organizer we are changing + // the event's readonly status... + mOrganizer = o; + if (mOrganizer.left(7).upper() == "MAILTO:") + mOrganizer = mOrganizer.remove(0,7); + + updated(); +} + +QString IncidenceBase::organizer() const +{ + return mOrganizer; +} + +void IncidenceBase::setReadOnly( bool readOnly ) +{ + mReadOnly = readOnly; +} + +void IncidenceBase::setDtStart(const QDateTime &dtStart) +{ +// if (mReadOnly) return; + mDtStart = getEvenTime(dtStart); + updated(); +} + +QDateTime IncidenceBase::dtStart() const +{ + return mDtStart; +} + +QString IncidenceBase::dtStartTimeStr() const +{ + return KGlobal::locale()->formatTime(dtStart().time()); +} + +QString IncidenceBase::dtStartDateStr(bool shortfmt) const +{ + return KGlobal::locale()->formatDate(dtStart().date(),shortfmt); +} + +QString IncidenceBase::dtStartStr(bool shortfmt) const +{ + return KGlobal::locale()->formatDateTime(dtStart(), shortfmt); +} + + +bool IncidenceBase::doesFloat() const +{ + return mFloats; +} + +void IncidenceBase::setFloats(bool f) +{ + if (mReadOnly) return; + mFloats = f; + updated(); +} + + +void IncidenceBase::addAttendee(Attendee *a, bool doupdate) +{ + if (mReadOnly) return; + if (a->name().left(7).upper() == "MAILTO:") + a->setName(a->name().remove(0,7)); + + mAttendees.append(a); + if (doupdate) updated(); +} + +#if 0 +void IncidenceBase::removeAttendee(Attendee *a) +{ + if (mReadOnly) return; + mAttendees.removeRef(a); + updated(); +} + +void IncidenceBase::removeAttendee(const char *n) +{ + Attendee *a; + + if (mReadOnly) return; + for (a = mAttendees.first(); a; a = mAttendees.next()) + if (a->getName() == n) { + mAttendees.remove(); + break; + } +} +#endif + +void IncidenceBase::clearAttendees() +{ + if (mReadOnly) return; + mAttendees.clear(); +} + +#if 0 +Attendee *IncidenceBase::getAttendee(const char *n) const +{ + QPtrListIterator<Attendee> qli(mAttendees); + + qli.toFirst(); + while (qli) { + if (qli.current()->getName() == n) + return qli.current(); + ++qli; + } + return 0L; +} +#endif + +Attendee *IncidenceBase::attendeeByMail(const QString &email) +{ + QPtrListIterator<Attendee> qli(mAttendees); + + qli.toFirst(); + while (qli) { + if (qli.current()->email() == email) + return qli.current(); + ++qli; + } + return 0L; +} + +Attendee *IncidenceBase::attendeeByMails(const QStringList &emails, const QString& email) +{ + QPtrListIterator<Attendee> qli(mAttendees); + + QStringList mails = emails; + if (!email.isEmpty()) { + mails.append(email); + } + qli.toFirst(); + while (qli) { + for ( QStringList::Iterator it = mails.begin(); it != mails.end(); ++it ) { + if (qli.current()->email() == *it) + return qli.current(); + } + + ++qli; + } + return 0L; +} + +void IncidenceBase::setDuration(int seconds) +{ + mDuration = seconds; + setHasDuration(true); +} + +int IncidenceBase::duration() const +{ + return mDuration; +} + +void IncidenceBase::setHasDuration(bool b) +{ + mHasDuration = b; +} + +bool IncidenceBase::hasDuration() const +{ + return mHasDuration; +} + +void IncidenceBase::setSyncStatus(int stat) +{ + if (mReadOnly) return; + mSyncStatus = stat; +} + +int IncidenceBase::syncStatus() const +{ + return mSyncStatus; +} + +void IncidenceBase::setPilotId( int id ) +{ + if (mReadOnly) return; + mPilotId = id; +} + +int IncidenceBase::pilotId() const +{ + return mPilotId; +} +void IncidenceBase::setZaurusId( int id ) +{ + if (mReadOnly) return; + mZaurusId = id; +} + +int IncidenceBase::zaurusId() const +{ + return mZaurusId; +} + +int IncidenceBase::zaurusUid() const +{ + return mZaurusUid; +} +void IncidenceBase::setZaurusUid( int id ) +{ + if (mReadOnly) return; + mZaurusUid = id; +} + +int IncidenceBase::zaurusStat() const +{ + return mZaurusStat; +} +void IncidenceBase::setZaurusStat( int id ) +{ + if (mReadOnly) return; + mZaurusStat = id; +} + +void IncidenceBase::registerObserver( IncidenceBase::Observer *observer ) +{ + if( !mObservers.contains(observer) ) mObservers.append( observer ); +} + +void IncidenceBase::unRegisterObserver( IncidenceBase::Observer *observer ) +{ + mObservers.remove( observer ); +} + +void IncidenceBase::updated() +{ + QPtrListIterator<Observer> it(mObservers); + while( it.current() ) { + Observer *o = it.current(); + ++it; + o->incidenceUpdated( this ); + } +} diff --git a/libkcal/incidencebase.h b/libkcal/incidencebase.h new file mode 100644 index 0000000..0ab7eef --- a/dev/null +++ b/libkcal/incidencebase.h @@ -0,0 +1,170 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_INCIDENCEBASE_H +#define KCAL_INCIDENCEBASE_H +// +// Incidence - base class of calendaring components +// + +#include <qdatetime.h> +#include <qstringlist.h> +#include <qvaluelist.h> +#include <qptrlist.h> + +#include "customproperties.h" +#include "attendee.h" + +namespace KCal { + +typedef QValueList<QDate> DateList; + +/** + This class provides the base class common to all calendar components. +*/ +class IncidenceBase : public CustomProperties +{ + public: + class Observer { + public: + virtual void incidenceUpdated( IncidenceBase * ) = 0; + }; + + IncidenceBase(); + IncidenceBase(const IncidenceBase &); + virtual ~IncidenceBase(); + + virtual QCString type() const = 0; + + /** Set the unique id for the event */ + void setUid(const QString &); + /** Return the unique id for the event */ + QString uid() const; + + /** Sets the time the incidence was last modified. */ + void setLastModified(const QDateTime &lm); + /** Return the time the incidence was last modified. */ + QDateTime lastModified() const; + + /** sets the organizer for the event */ + void setOrganizer(const QString &o); + QString organizer() const; + + /** Set readonly status. */ + virtual void setReadOnly( bool ); + /** Return if the object is read-only. */ + bool isReadOnly() const { return mReadOnly; } + + /** for setting the event's starting date/time with a QDateTime. */ + virtual void setDtStart(const QDateTime &dtStart); + /** returns an event's starting date/time as a QDateTime. */ + QDateTime dtStart() const; + /** returns an event's starting time as a string formatted according to the + users locale settings */ + QString dtStartTimeStr() const; + /** returns an event's starting date as a string formatted according to the + users locale settings */ + QString dtStartDateStr(bool shortfmt=true) const; + /** returns an event's starting date and time as a string formatted according + to the users locale settings */ + QString dtStartStr(bool shortfmt=true) const; + + virtual void setDuration(int seconds); + int duration() const; + void setHasDuration(bool); + bool hasDuration() const; + + /** Return true or false depending on whether the incidence "floats," + * i.e. has a date but no time attached to it. */ + bool doesFloat() const; + /** Set whether the incidence floats, i.e. has a date but no time attached to it. */ + void setFloats(bool f); + + /** + Add Attendee to this incidence. IncidenceBase takes ownership of the + Attendee object. + */ + void addAttendee(Attendee *a, bool doupdate=true ); +// void removeAttendee(Attendee *a); +// void removeAttendee(const char *n); + /** Remove all Attendees. */ + void clearAttendees(); + /** Return list of attendees. */ + QPtrList<Attendee> attendees() const { return mAttendees; }; + /** Return number of attendees. */ + int attendeeCount() const { return mAttendees.count(); }; + /** Return the Attendee with this email */ + Attendee* attendeeByMail(const QString &); + /** Return first Attendee with one of this emails */ + Attendee* attendeeByMails(const QStringList &, const QString& email = QString::null); + + /** pilot syncronization states */ + enum { SYNCNONE = 0, SYNCMOD = 1, SYNCDEL = 3 }; + /** Set synchronisation satus. */ + void setSyncStatus(int stat); + /** Return synchronisation status. */ + int syncStatus() const; + + /** Set Pilot Id. */ + void setPilotId(int id); + /** Return Pilot Id. */ + int pilotId() const; + + void setZaurusId(int id); + int zaurusId() const; + void setZaurusUid(int id); + int zaurusUid() const; + void setZaurusStat(int id); + int zaurusStat() const; + + void registerObserver( Observer * ); + void unRegisterObserver( Observer * ); + void updated(); + + protected: + bool mReadOnly; + QDateTime getEvenTime( QDateTime ); + + private: + // base components + QDateTime mDtStart; + QString mOrganizer; + QString mUid; + QDateTime mLastModified; + QPtrList<Attendee> mAttendees; + + bool mFloats; + + int mDuration; + bool mHasDuration; + int mZaurusId; + int mZaurusUid; + int mZaurusStat; + + // PILOT SYNCHRONIZATION STUFF + int mPilotId; // unique id for pilot sync + int mSyncStatus; // status (for sync) + + QPtrList<Observer> mObservers; +}; + +bool operator==( const IncidenceBase&, const IncidenceBase& ); +} + +#endif diff --git a/libkcal/journal.cpp b/libkcal/journal.cpp new file mode 100644 index 0000000..351fb32 --- a/dev/null +++ b/libkcal/journal.cpp @@ -0,0 +1,49 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "journal.h" + +using namespace KCal; + +Journal::Journal() +{ +} + +Journal::~Journal() +{ +} + +Incidence *Journal::clone() +{ + return new Journal(*this); +} + + +bool KCal::operator==( const Journal& j1, const Journal& j2 ) +{ + return operator==( (const Incidence&)j1, (const Incidence&)j2 ); +} + + +QDateTime Journal::getNextAlarmDateTime( bool * ok, int * offset ) const +{ + *ok = false; + return QDateTime (); +} diff --git a/libkcal/journal.h b/libkcal/journal.h new file mode 100644 index 0000000..cb90c7a --- a/dev/null +++ b/libkcal/journal.h @@ -0,0 +1,50 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef JOURNAL_H +#define JOURNAL_H +// +// Journal component, representing a VJOURNAL object +// + +#include "incidence.h" + +namespace KCal { + +/** + This class provides a Journal in the sense of RFC2445. +*/ +class Journal : public Incidence +{ + public: + Journal(); + ~Journal(); + + QCString type() const { return "Journal"; } + + Incidence *clone(); + QDateTime getNextAlarmDateTime( bool * ok, int * offset ) const; +private: + bool accept(Visitor &v) { return v.visit(this); } +}; + + bool operator==( const Journal&, const Journal& ); +} + +#endif diff --git a/libkcal/kcal.pro.back b/libkcal/kcal.pro.back new file mode 100644 index 0000000..a33c5f9 --- a/dev/null +++ b/libkcal/kcal.pro.back @@ -0,0 +1,84 @@ +TEMPLATE = lib +CONFIG = qt warn_on release +TARGET = kcal +INCLUDEPATH += ../microkde ../qtcompat versit +INCLUDEPATH += ../libical/src/libical +INCLUDEPATH += ../libical/src/libicalss +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc +DESTDIR = $(QPEDIR)/lib +LIBS += -lical +LIBS += -licalss + +INTERFACES = \ + +HEADERS = \ + alarm.h \ + attachment.h \ + attendee.h \ + calendar.h \ + calendarlocal.h \ + calfilter.h \ + calformat.h \ + calstorage.h \ + compat.h \ + customproperties.h \ + dummyscheduler.h \ + duration.h \ + event.h \ + exceptions.h \ + filestorage.h \ + freebusy.h \ + icaldrag.h \ + icalformat.h \ + icalformatimpl.h \ + imipscheduler.h \ + incidence.h \ + incidencebase.h \ + journal.h \ + period.h \ + person.h \ + qtopiaformat.h \ + recurrence.h \ + scheduler.h \ + todo.h \ + vcaldrag.h \ + vcalformat.h \ + versit/port.h \ + versit/vcc.h \ + versit/vobject.h \ + +SOURCES = \ + alarm.cpp \ + attachment.cpp \ + attendee.cpp \ + calendar.cpp \ + calendarlocal.cpp \ + calfilter.cpp \ + calformat.cpp \ + compat.cpp \ + customproperties.cpp \ + dummyscheduler.cpp \ + duration.cpp \ + event.cpp \ + exceptions.cpp \ + filestorage.cpp \ + freebusy.cpp \ + icaldrag.cpp \ + icalformat.cpp \ + icalformatimpl.cpp \ + imipscheduler.cpp \ + incidence.cpp \ + incidencebase.cpp \ + journal.cpp \ + period.cpp \ + person.cpp \ + qtopiaformat.cpp \ + recurrence.cpp \ + scheduler.cpp \ + todo.cpp \ + vcaldrag.cpp \ + vcalformat.cpp \ + versit/vcc.c \ + versit/vobject.c \ + diff --git a/libkcal/libkcal.pro b/libkcal/libkcal.pro new file mode 100644 index 0000000..49aa24b --- a/dev/null +++ b/libkcal/libkcal.pro @@ -0,0 +1,100 @@ +TEMPLATE = lib +CONFIG += qt warn_on +TARGET = microkcal + +include( ../variables.pri ) + +INCLUDEPATH += ../microkde versit ../microkde/kdecore +#../qtcompat +INCLUDEPATH += ../libical/src/libical +INCLUDEPATH += ../libical/src/libicalss +DESTDIR = ../bin +DEFINES += DESKTOP_VERSION +unix: { +LIBS += ../libical/lib/libical.a +LIBS += ../libical/lib/libicalss.a +OBJECTS_DIR = obj/unix +MOC_DIR = moc/unix +} +win32: { +DEFINES += _WIN32_ + +LIBS += ../libical/lib/ical.lib +LIBS += ../libical/lib/icalss.lib +OBJECTS_DIR = obj/win +MOC_DIR = moc/win + +} + +INTERFACES = \ + +HEADERS = \ + alarm.h \ + attachment.h \ + attendee.h \ + calendar.h \ + calendarlocal.h \ + calfilter.h \ + calformat.h \ + calstorage.h \ + compat.h \ + customproperties.h \ + dummyscheduler.h \ + duration.h \ + event.h \ + exceptions.h \ + filestorage.h \ + freebusy.h \ + icaldrag.h \ + icalformat.h \ + icalformatimpl.h \ + imipscheduler.h \ + incidence.h \ + incidencebase.h \ + journal.h \ + period.h \ + person.h \ + qtopiaformat.h \ + recurrence.h \ + scheduler.h \ + todo.h \ + vcaldrag.h \ + vcalformat.h \ + versit/port.h \ + versit/vcc.h \ + versit/vobject.h \ + +SOURCES = \ + alarm.cpp \ + attachment.cpp \ + attendee.cpp \ + calendar.cpp \ + calendarlocal.cpp \ + calfilter.cpp \ + calformat.cpp \ + compat.cpp \ + customproperties.cpp \ + dummyscheduler.cpp \ + duration.cpp \ + event.cpp \ + exceptions.cpp \ + filestorage.cpp \ + freebusy.cpp \ + icaldrag.cpp \ + icalformat.cpp \ + icalformatimpl.cpp \ + imipscheduler.cpp \ + incidence.cpp \ + incidencebase.cpp \ + journal.cpp \ + period.cpp \ + person.cpp \ + qtopiaformat.cpp \ + recurrence.cpp \ + scheduler.cpp \ + todo.cpp \ + vcaldrag.cpp \ + vcalformat.cpp \ + versit/vcc.c \ + versit/vobject.c \ + diff --git a/libkcal/libkcalE.pro b/libkcal/libkcalE.pro new file mode 100644 index 0000000..e27c10f --- a/dev/null +++ b/libkcal/libkcalE.pro @@ -0,0 +1,88 @@ +TEMPLATE = lib +CONFIG += qt warn_on +TARGET = microkcal + + +INCLUDEPATH += ../microkde ../qtcompat versit ../microkde/kdecore versit $(QPEDIR)/include +INCLUDEPATH += ../libical/src/libical +INCLUDEPATH += ../libical/src/libicalss +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR = $(QPEDIR)/lib +LIBS += ../libical/lib/$(PLATFORM)/libical.a +LIBS += ../libical/lib/$(PLATFORM)/libicalss.a + +INTERFACES = \ + +HEADERS = \ + alarm.h \ + attachment.h \ + attendee.h \ + calendar.h \ + calendarlocal.h \ + calfilter.h \ + calformat.h \ + calstorage.h \ + compat.h \ + customproperties.h \ + dummyscheduler.h \ + duration.h \ + event.h \ + exceptions.h \ + filestorage.h \ + freebusy.h \ + icaldrag.h \ + icalformat.h \ + icalformatimpl.h \ + imipscheduler.h \ + incidence.h \ + incidencebase.h \ + journal.h \ + period.h \ + person.h \ + qtopiaformat.h \ + sharpformat.h \ + recurrence.h \ + scheduler.h \ + todo.h \ + vcaldrag.h \ + vcalformat.h \ + versit/port.h \ + versit/vcc.h \ + versit/vobject.h \ + +SOURCES = \ + alarm.cpp \ + attachment.cpp \ + attendee.cpp \ + calendar.cpp \ + calendarlocal.cpp \ + calfilter.cpp \ + calformat.cpp \ + compat.cpp \ + customproperties.cpp \ + dummyscheduler.cpp \ + duration.cpp \ + event.cpp \ + exceptions.cpp \ + filestorage.cpp \ + freebusy.cpp \ + icaldrag.cpp \ + icalformat.cpp \ + icalformatimpl.cpp \ + imipscheduler.cpp \ + incidence.cpp \ + incidencebase.cpp \ + journal.cpp \ + period.cpp \ + person.cpp \ + qtopiaformat.cpp \ + sharpformat.cpp \ + recurrence.cpp \ + scheduler.cpp \ + todo.cpp \ + vcaldrag.cpp \ + vcalformat.cpp \ + versit/vcc.c \ + versit/vobject.c \ + diff --git a/libkcal/listbase.h b/libkcal/listbase.h new file mode 100644 index 0000000..085b13d --- a/dev/null +++ b/libkcal/listbase.h @@ -0,0 +1,97 @@ +/* + This file is part of libkcal. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_LISTBASE_H +#define KCAL_LISTBASE_H + +#include <qvaluelist.h> + +namespace KCal { + class Event; + class Todo; +/** + This class provides a template for lists of pointers. It extends QValueList<T + *> by auto delete funtionality known from QPtrList. +*/ +template<class T> +class ListBase : public QValueList<T *> +{ + public: + ListBase() + : QValueList<T *>(), mAutoDelete( false ) + { + } + + ListBase( const ListBase &l ) + : QValueList<T *>( l ), mAutoDelete( false ) + { + } + + ~ListBase() + { + if ( mAutoDelete ) { + QValueListIterator<T *> it; + for( it = QValueList<T*>::begin(); it != QValueList<T*>::end(); ++it ) { + delete *it; + } + } + } + + ListBase &operator=( const ListBase &l ) + { + if ( this == &l ) return *this; + QValueList<T *>::operator=( l ); + return *this; + } + + void setAutoDelete( bool autoDelete ) + { + mAutoDelete = autoDelete; + } + + bool removeRef( T *t ) + { + QValueListIterator<T *> it = find( t ); + if ( it == QValueList<T*>::end() ) { + return false; + } else { + if ( mAutoDelete ) delete t; + remove( it ); + return true; + } + } + void fill ( QPtrList<T> list ) { + QPtrListIterator<T> it (list); + T *item; + while ( (item = it.current()) != 0 ) { + append( item ); + ++it; + } + + } + + + private: + bool mAutoDelete; +}; + +} + +#endif diff --git a/libkcal/period.cpp b/libkcal/period.cpp new file mode 100644 index 0000000..d188a4c --- a/dev/null +++ b/libkcal/period.cpp @@ -0,0 +1,65 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> +#include <klocale.h> + +#include "period.h" + +using namespace KCal; + +Period::Period() +{ + mHasDuration = false; +} + +Period::Period( const QDateTime &start, const QDateTime &end ) +{ + mStart = start; + mEnd = end; + mHasDuration = false; +} + +Period::Period( const QDateTime &start, const Duration &duration ) +{ + mStart = start; + mEnd = duration.end( start ); + mHasDuration = true; +} + +QDateTime Period::start() const +{ + return mStart; +} + +QDateTime Period::end()const +{ + return mEnd; +} + +Duration Period::duration() +{ + return Duration( mStart, mEnd ); +} + +bool Period::hasDuration()const +{ + return mHasDuration; +} diff --git a/libkcal/period.h b/libkcal/period.h new file mode 100644 index 0000000..9d40f12 --- a/dev/null +++ b/libkcal/period.h @@ -0,0 +1,51 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_PERIOD_H +#define KCAL_PERIOD_H + +#include <qdatetime.h> + +#include "duration.h" + +namespace KCal { + +class Period +{ + public: + Period(); + Period( const QDateTime &start, const QDateTime &end ); + Period( const QDateTime &start, const Duration &duration ); + + QDateTime start()const; + QDateTime end()const; + Duration duration(); + + bool hasDuration()const; + + private: + QDateTime mStart; + QDateTime mEnd; + + bool mHasDuration; +}; + +} + +#endif diff --git a/libkcal/person.cpp b/libkcal/person.cpp new file mode 100644 index 0000000..aca28c2 --- a/dev/null +++ b/libkcal/person.cpp @@ -0,0 +1,77 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> +#include <klocale.h> + +#include "person.h" + +using namespace KCal; + +Person::Person( const QString &fullName ) +{ + int emailPos = fullName.find( '<' ); + if ( emailPos < 0 ) { + setEmail(fullName); + } else { + setEmail(fullName.mid( emailPos + 1, fullName.length() - 1 )); + setName(fullName.left( emailPos - 2 )); + } +} + +Person::Person( const QString &name, const QString &email ) +{ + setName(name); + setEmail(email); +} + + +bool KCal::operator==( const Person& p1, const Person& p2 ) +{ + return ( p1.name() == p2.name() && + p1.email() == p2.email() ); +} + + +QString Person::fullName() const +{ + if( mName.isEmpty() ) { + return mEmail; + } else { + if( mEmail.isEmpty() ) + return mName; + else + return mName + " <" + mEmail + ">"; + } +} + +void Person::setName(const QString &name) +{ + mName = name; +} + +void Person::setEmail(const QString &email) +{ + if (email.left(7).lower() == "mailto:") { + mEmail = email.mid(7); + } else { + mEmail = email; + } +} diff --git a/libkcal/person.h b/libkcal/person.h new file mode 100644 index 0000000..c46c5f0 --- a/dev/null +++ b/libkcal/person.h @@ -0,0 +1,50 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_PERSON_H +#define KCAL_PERSON_H + +#include <qstring.h> + +namespace KCal { + +class Person +{ + public: + Person() {} + Person( const QString &fullName ); + Person( const QString &name, const QString &email ); + + QString fullName( ) const; + + void setName(const QString &); + QString name() const { return mName; } + + void setEmail(const QString &); + QString email() const { return mEmail; } + + private: + QString mName; + QString mEmail; +}; + + bool operator==( const Person& p1, const Person& p2 ); +} + +#endif diff --git a/libkcal/qtopiaformat.cpp b/libkcal/qtopiaformat.cpp new file mode 100644 index 0000000..0a4a031 --- a/dev/null +++ b/libkcal/qtopiaformat.cpp @@ -0,0 +1,333 @@ +/* + This file is part of libkcal. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdatetime.h> +#include <qstring.h> +#include <qptrlist.h> +#include <qregexp.h> +#include <qclipboard.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qxml.h> + +#include <kdebug.h> +#include <klocale.h> + +#include "calendar.h" +#include "calendarlocal.h" + +#include "qtopiaformat.h" + +using namespace KCal; + +class QtopiaParser : public QXmlDefaultHandler +{ + public: + QtopiaParser( Calendar *calendar ) : mCalendar( calendar ) { + oldCategories = 0; + } + + bool startElement( const QString &, const QString &, const QString & qName, + const QXmlAttributes &attributes ) + { + if ( qName == "event" ) { + Event *event = new Event; + QString uid = "Qtopia" + attributes.value( "uid" ); + // event->setUid( uid ); + + event->setSummary( attributes.value( "description" ) ); + event->setLocation( attributes.value( "location" ) ); + event->setDescription( attributes.value( "note" ) ); + event->setDtStart( toDateTime( attributes.value( "start" ) ) ); + event->setDtEnd( toDateTime( attributes.value( "end" ) ) ); + + if ( attributes.value( "type" ) == "AllDay" ) { + event->setFloats( true ); + } else { + event->setFloats( false ); + } + + QString rtype = attributes.value( "rtype" ); + if ( !rtype.isEmpty() ) { + QDate startDate = event->dtStart().date(); + + QString freqStr = attributes.value( "rfreq" ); + int freq = freqStr.toInt(); + + QString hasEndDateStr = attributes.value( "rhasenddate" ); + bool hasEndDate = hasEndDateStr == "1"; + + QString endDateStr = attributes.value( "enddt" ); + QDate endDate = toDateTime( endDateStr ).date(); + + QString weekDaysStr = attributes.value( "rweekdays" ); + int weekDaysNum = weekDaysStr.toInt(); + if ( weekDaysNum == 0 ) + weekDaysNum = (1 << (event->dtStart().date().dayOfWeek()-1)); + + QBitArray weekDays( 7 ); + weekDays.fill( false ); + int i; + for( i = 0; i < 7; ++i ) { + weekDays.setBit( i , ( 1 << i ) & weekDaysNum ); + qDebug("%d %d %d ",i, weekDaysNum, weekDays.at(i) ); + } + + QString posStr = attributes.value( "rposition" ); + int pos = posStr.toInt(); + + Recurrence *r = event->recurrence(); + + if ( rtype == "Daily" ) { + if ( hasEndDate ) r->setDaily( freq, endDate ); + else r->setDaily( freq, -1 ); + } else if ( rtype == "Weekly" ) { + // fix needed here + // rweekdays not set in XML file + if ( hasEndDate ) r->setWeekly( freq, weekDays, endDate ); + else r->setWeekly( freq, weekDays, -1 ); + } else if ( rtype == "MonthlyDate" ) { + if ( hasEndDate ) + r->setMonthly( Recurrence::rMonthlyDay, freq, endDate ); + else + r->setMonthly( Recurrence::rMonthlyDay, freq, -1 ); + r->addMonthlyDay( startDate.day() ); + } else if ( rtype == "MonthlyDay" ) { + if ( hasEndDate ) + r->setMonthly( Recurrence::rMonthlyPos, freq, endDate ); + else + r->setMonthly( Recurrence::rMonthlyPos, freq, -1 ); + QBitArray days( 7 ); + days.fill( false ); + days.setBit( startDate.dayOfWeek() - 1 ); + r->addMonthlyPos( pos, days ); + } else if ( rtype == "Yearly" ) { + if ( hasEndDate ) + r->setYearly( Recurrence::rYearlyMonth, freq, endDate ); + else + r->setYearly( Recurrence::rYearlyMonth, freq, -1 ); + r->addYearlyNum( startDate.month() ); + } + } + + QString categoryList = attributes.value( "categories" ); + event->setCategories( lookupCategories( categoryList ) ); + + QString alarmStr = attributes.value( "alarm" ); + if ( !alarmStr.isEmpty() ) { + Alarm *alarm = new Alarm( event ); + alarm->setType( Alarm::Display ); + alarm->setEnabled( true ); + int alarmOffset = alarmStr.toInt(); + alarm->setStartOffset( alarmOffset * -60 ); + event->addAlarm( alarm ); + } + // the following may not be + //Event *oldEvent = mCalendar->event( uid ); + //if ( oldEvent ) mCalendar->deleteEvent( oldEvent ); + + mCalendar->addEventNoDup( event ); + } else if ( qName == "Task" ) { + Todo *todo = new Todo; + + QString uid = "Qtopia" + attributes.value( "Uid" ); + //todo->setUid( uid ); + + QString description = attributes.value( "Description" ); + int pos = description.find( '\n' ); + if ( pos > 0 ) { + QString summary = description.left( pos ); + todo->setSummary( summary ); + todo->setDescription( description ); + } else { + todo->setSummary( description ); + } + + int priority = attributes.value( "Priority" ).toInt(); + if ( priority == 0 ) priority = 3; + todo->setPriority( priority ); + + QString categoryList = attributes.value( "Categories" ); + todo->setCategories( lookupCategories( categoryList ) ); + + QString completedStr = attributes.value( "Completed" ); + if ( completedStr == "1" ) todo->setCompleted( true ); + + QString hasDateStr = attributes.value( "HasDate" ); + if ( hasDateStr == "1" ) { + int year = attributes.value( "DateYear" ).toInt(); + int month = attributes.value( "DateMonth" ).toInt(); + int day = attributes.value( "DateDay" ).toInt(); + + todo->setDtDue( QDateTime( QDate( year, month, day ) ) ); + todo->setHasDueDate( true ); + } + + // Todo *oldTodo = mCalendar->todo( uid ); + //if ( oldTodo ) mCalendar->deleteTodo( oldTodo ); + + mCalendar->addTodoNoDup( todo ); + } else if ( qName == "Category" ) { + QString id = attributes.value( "id" ); + QString name = attributes.value( "name" ); + setCategory( id, name ); + } + + return true; + } + + bool warning ( const QXmlParseException &exception ) + { + printException( exception ); + return true; + } + + bool error ( const QXmlParseException &exception ) + { + printException( exception ); + return false; + } + + bool fatalError ( const QXmlParseException &exception ) + { + printException( exception ); + return false; + } + + QString errorString () + { + return "QtopiaParser: Error!"; + } + void setCategoriesList ( QStringList * c ) + { + oldCategories = c; + } + + protected: + void printException( const QXmlParseException &exception ) + { + kdError() << "XML Parse Error (line " << exception.lineNumber() + << ", col " << exception.columnNumber() << "): " + << exception.message() << "(public ID: '" + << exception.publicId() << "' system ID: '" + << exception.systemId() << "')" << endl; + } + + QDateTime toDateTime( const QString &value ) + { + QDateTime dt; + dt.setTime_t( value.toUInt() ); + + return dt; + } + + QStringList lookupCategories( const QString &categoryList ) + { + QStringList categoryIds = QStringList::split( ";", categoryList ); + QStringList categories; + QStringList::ConstIterator it; + for( it = categoryIds.begin(); it != categoryIds.end(); ++it ) { + QString cate = category( *it ); + if ( oldCategories ) { + if ( ! oldCategories->contains( cate ) ) + oldCategories->append( cate ); + } + categories.append(cate ); + } + return categories; + } + + private: + Calendar *mCalendar; + QStringList * oldCategories; + static QString category( const QString &id ) + { + QMap<QString,QString>::ConstIterator it = mCategoriesMap.find( id ); + if ( it == mCategoriesMap.end() ) return id; + else return *it; + } + + static void setCategory( const QString &id, const QString &name ) + { + mCategoriesMap.insert( id, name ); + } + + static QMap<QString,QString> mCategoriesMap; +}; + +QMap<QString,QString> QtopiaParser::mCategoriesMap; + +QtopiaFormat::QtopiaFormat() +{ + mCategories = 0; +} + +QtopiaFormat::~QtopiaFormat() +{ +} +#include <qdom.h> +bool QtopiaFormat::load( Calendar *calendar, const QString &fileName ) +{ + clearException(); + // qDebug("load QtopiaFormat: %s ",fileName.latin1() ); + QtopiaParser handler( calendar ); + handler.setCategoriesList( mCategories ); + QFile xmlFile( fileName ); + QXmlInputSource source( xmlFile ); + QXmlSimpleReader reader; + reader.setContentHandler( &handler ); + return reader.parse( source ); +} + +bool QtopiaFormat::save( Calendar *calendar, const QString &fileName ) +{ + + clearException(); + + QString text = toString( calendar ); + + if ( text.isNull() ) return false; + + // TODO: write backup file + + QFile file( fileName ); + if (!file.open( IO_WriteOnly ) ) { + setException(new ErrorFormat(ErrorFormat::SaveError, + i18n("Could not open file '%1'").arg(fileName))); + return false; + } + QTextStream ts( &file ); + ts << text; + file.close(); + + return true; +} + +bool QtopiaFormat::fromString( Calendar *, const QString & ) +{ + + return false; +} + +QString QtopiaFormat::toString( Calendar * ) +{ + return QString::null; +} diff --git a/libkcal/qtopiaformat.h b/libkcal/qtopiaformat.h new file mode 100644 index 0000000..2c69a4e --- a/dev/null +++ b/libkcal/qtopiaformat.h @@ -0,0 +1,53 @@ +/* + This file is part of libkcal. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef QTOPIAFORMAT_H +#define QTOPIAFORMAT_H + +#include <qstring.h> + +#include "scheduler.h" + +#include "calformat.h" + +namespace KCal { + +/** + This class implements the calendar format used by Qtopia. +*/ +class QtopiaFormat : public CalFormat { + public: + /** Create new iCalendar format. */ + QtopiaFormat(); + virtual ~QtopiaFormat(); + + bool load( Calendar *, const QString &fileName ); + bool save( Calendar *, const QString &fileName ); + void setCategoriesList ( QStringList * cat ){ mCategories = cat; } + bool fromString( Calendar *, const QString & ); + QString toString( Calendar * ); + + private: + QStringList *mCategories; +}; + +} + +#endif diff --git a/libkcal/recurrence.cpp b/libkcal/recurrence.cpp new file mode 100644 index 0000000..5fc5d1f --- a/dev/null +++ b/libkcal/recurrence.cpp @@ -0,0 +1,3360 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2002 David Jarvie <software@astrojar.org.uk> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <limits.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> + +#include "incidence.h" + +#include "recurrence.h" + +using namespace KCal; + +Recurrence::Feb29Type Recurrence::mFeb29YearlyDefaultType = Recurrence::rMar1; + + +Recurrence::Recurrence(Incidence *parent, int compatVersion) +: recurs(rNone), // by default, it's not a recurring event + rWeekStart(1), // default is Monday + rDays(7), + mFloats(parent ? parent->doesFloat() : false), + mRecurReadOnly(false), + mRecurExDatesCount(0), + mFeb29YearlyType(mFeb29YearlyDefaultType), + mCompatVersion(compatVersion ? compatVersion : INT_MAX), + mCompatRecurs(rNone), + mCompatDuration(0), + mParent(parent) +{ + rMonthDays.setAutoDelete( true ); + rMonthPositions.setAutoDelete( true ); + rYearNums.setAutoDelete( true ); +} + +Recurrence::Recurrence(const Recurrence &r, Incidence *parent) +: recurs(r.recurs), + rWeekStart(r.rWeekStart), + rDays(r.rDays.copy()), + rFreq(r.rFreq), + rDuration(r.rDuration), + rEndDateTime(r.rEndDateTime), + mRecurStart(r.mRecurStart), + mFloats(r.mFloats), + mRecurReadOnly(r.mRecurReadOnly), + mRecurExDatesCount(r.mRecurExDatesCount), + mFeb29YearlyType(r.mFeb29YearlyType), + mCompatVersion(r.mCompatVersion), + mCompatRecurs(r.mCompatRecurs), + mCompatDuration(r.mCompatDuration), + mParent(parent) +{ + for (QPtrListIterator<rMonthPos> mp(r.rMonthPositions); mp.current(); ++mp) { + rMonthPos *tmp = new rMonthPos; + tmp->rPos = mp.current()->rPos; + tmp->negative = mp.current()->negative; + tmp->rDays = mp.current()->rDays.copy(); + rMonthPositions.append(tmp); + } + for (QPtrListIterator<int> md(r.rMonthDays); md.current(); ++md) { + int *tmp = new int; + *tmp = *md.current(); + rMonthDays.append(tmp); + } + for (QPtrListIterator<int> yn(r.rYearNums); yn.current(); ++yn) { + int *tmp = new int; + *tmp = *yn.current(); + rYearNums.append(tmp); + } + rMonthDays.setAutoDelete( true ); + rMonthPositions.setAutoDelete( true ); + rYearNums.setAutoDelete( true ); +} + +Recurrence::~Recurrence() +{ +} + + +bool Recurrence::operator==( const Recurrence& r2 ) const +{ + + // the following line is obvious + if ( recurs == rNone && r2.recurs == rNone ) + return true; + // we need the above line, because two non recurring events may + // differ in the other settings, because one (or both) + // may be not initialized properly + if ( recurs != r2.recurs + || rFreq != r2.rFreq + || rDuration != r2.rDuration + || !rDuration && rEndDateTime != r2.rEndDateTime + || mRecurStart != r2.mRecurStart + || mFloats != r2.mFloats + || mRecurReadOnly != r2.mRecurReadOnly + || mRecurExDatesCount != r2.mRecurExDatesCount ) + return false; + // no need to compare mCompat* and mParent + // OK to compare the pointers + switch ( recurs ) + { + case rWeekly: + return rDays == r2.rDays + && rWeekStart == r2.rWeekStart; + case rMonthlyPos: + return rMonthPositions.count() == r2.rMonthPositions.count(); + case rMonthlyDay: + return rMonthDays.count() == r2.rMonthDays.count(); + case rYearlyPos: + return rYearNums.count() == r2.rYearNums.count() + && rMonthPositions.count() == r2.rMonthPositions.count(); + case rYearlyMonth: + return rYearNums.count() == r2.rYearNums.count() + && mFeb29YearlyType == r2.mFeb29YearlyType; + case rYearlyDay: + return rYearNums == r2.rYearNums; + case rNone: + case rMinutely: + case rHourly: + case rDaily: + default: + return true; + } +} +/* +bool Recurrence::compareLists( const QPtrList<int> &l1 ,const QPtrList<int> &l2) +{ + if ( l1.count() != l2.count() ) + return false; + int count = l1.count(); + int i; + for ( i = 0; i < count ; ++i ) { + // if ( l1.at(i) != l2.at(i) ) + return false; + qDebug("compüare "); + } + return true; +} +*/ +QString Recurrence::recurrenceText() const +{ + QString recurText = i18n("No"); + if ( recurs == Recurrence::rMinutely ) + recurText = i18n("minutely"); + else if ( recurs == Recurrence::rHourly ) + recurText = i18n("hourly"); + else if ( recurs == Recurrence::rDaily ) + recurText = i18n("daily"); + else if ( recurs == Recurrence::rWeekly ) + recurText = i18n("weekly"); + else if ( recurs == Recurrence::rMonthlyPos ) + recurText = i18n("monthly"); + else if ( recurs == Recurrence::rMonthlyDay ) + recurText = i18n("day-monthly"); + else if ( recurs == Recurrence::rYearlyMonth ) + recurText = i18n("month-yearly"); + else if ( recurs == Recurrence::rYearlyDay ) + recurText = i18n("day-yearly"); + else if ( recurs == Recurrence::rYearlyPos ) + recurText = i18n("position-yearly"); + return recurText; +} + +void Recurrence::setCompatVersion(int version) +{ + mCompatVersion = version ? version : INT_MAX; +} + +ushort Recurrence::doesRecur() const +{ + return recurs; +} + +bool Recurrence::recursOnPure(const QDate &qd) const +{ + switch(recurs) { + case rMinutely: + return recursSecondly(qd, rFreq*60); + case rHourly: + return recursSecondly(qd, rFreq*3600); + case rDaily: + return recursDaily(qd); + case rWeekly: + return recursWeekly(qd); + case rMonthlyPos: + case rMonthlyDay: + return recursMonthly(qd); + case rYearlyMonth: + return recursYearlyByMonth(qd); + case rYearlyDay: + return recursYearlyByDay(qd); + case rYearlyPos: + return recursYearlyByPos(qd); + default: + return false; + case rNone: + return false; + } // case + return false; +} + +bool Recurrence::recursAtPure(const QDateTime &dt) const +{ + switch(recurs) { + case rMinutely: + return recursMinutelyAt(dt, rFreq); + case rHourly: + return recursMinutelyAt(dt, rFreq*60); + default: + if (dt.time() != mRecurStart.time()) + return false; + switch(recurs) { + case rDaily: + return recursDaily(dt.date()); + case rWeekly: + return recursWeekly(dt.date()); + case rMonthlyPos: + case rMonthlyDay: + return recursMonthly(dt.date()); + case rYearlyMonth: + return recursYearlyByMonth(dt.date()); + case rYearlyDay: + return recursYearlyByDay(dt.date()); + case rYearlyPos: + return recursYearlyByPos(dt.date()); + default: + return false; + case rNone: + return false; + } + } // case + return false; +} + +QDate Recurrence::endDate() const +{ + int count = 0; + QDate end; + if (recurs != rNone) { + if (rDuration < 0) + return QDate(); // infinite recurrence + if (rDuration == 0) + return rEndDateTime.date(); + + // The end date is determined by the recurrence count + QDate dStart = mRecurStart.date(); + switch (recurs) + { + case rMinutely: + return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60).date(); + case rHourly: + return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600).date(); + case rDaily: + return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq); + + case rWeekly: + count = weeklyCalc(END_DATE_AND_COUNT, end); + break; + case rMonthlyPos: + case rMonthlyDay: + count = monthlyCalc(END_DATE_AND_COUNT, end); + break; + case rYearlyMonth: + count = yearlyMonthCalc(END_DATE_AND_COUNT, end); + break; + case rYearlyDay: + count = yearlyDayCalc(END_DATE_AND_COUNT, end); + break; + case rYearlyPos: + count = yearlyPosCalc(END_DATE_AND_COUNT, end); + break; + default: + // catch-all. Should never get here. + kdDebug(5800) << "Control should never reach here in endDate()!" << endl; + break; + } + } + if (!count) + return QDate(); // error - there is no recurrence + return end; +} + +QDateTime Recurrence::endDateTime() const +{ + int count = 0; + QDate end; + if (recurs != rNone) { + if (rDuration < 0) + return QDateTime(); // infinite recurrence + if (rDuration == 0) + return rEndDateTime; + + // The end date is determined by the recurrence count + QDate dStart = mRecurStart.date(); + switch (recurs) + { + case rMinutely: + return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60); + case rHourly: + return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600); + case rDaily: + return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq); + + case rWeekly: + count = weeklyCalc(END_DATE_AND_COUNT, end); + break; + case rMonthlyPos: + case rMonthlyDay: + count = monthlyCalc(END_DATE_AND_COUNT, end); + break; + case rYearlyMonth: + count = yearlyMonthCalc(END_DATE_AND_COUNT, end); + break; + case rYearlyDay: + count = yearlyDayCalc(END_DATE_AND_COUNT, end); + break; + case rYearlyPos: + count = yearlyPosCalc(END_DATE_AND_COUNT, end); + break; + default: + // catch-all. Should never get here. + kdDebug(5800) << "Control should never reach here in endDate()!" << endl; + break; + } + } + if (!count) + return QDateTime(); // error - there is no recurrence + return QDateTime(end, mRecurStart.time()); +} + +int Recurrence::durationTo(const QDate &date) const +{ + QDate d = date; + return recurCalc(COUNT_TO_DATE, d); +} + +int Recurrence::durationTo(const QDateTime &datetime) const +{ + QDateTime dt = datetime; + return recurCalc(COUNT_TO_DATE, dt); +} + +void Recurrence::unsetRecurs() +{ + if (mRecurReadOnly) return; + recurs = rNone; + rMonthPositions.clear(); + rMonthDays.clear(); + rYearNums.clear(); +} + +void Recurrence::setRecurStart(const QDateTime &start) +{ + mRecurStart = start; + mFloats = false; + switch (recurs) + { + case rMinutely: + case rHourly: + break; + case rDaily: + case rWeekly: + case rMonthlyPos: + case rMonthlyDay: + case rYearlyMonth: + case rYearlyDay: + case rYearlyPos: + default: + rEndDateTime.setTime(start.time()); + break; + } +} + +void Recurrence::setRecurStart(const QDate &start) +{ + mRecurStart.setDate(start); + mRecurStart.setTime(QTime(0,0,0)); + switch (recurs) + { + case rMinutely: + case rHourly: + break; + case rDaily: + case rWeekly: + case rMonthlyPos: + case rMonthlyDay: + case rYearlyMonth: + case rYearlyDay: + case rYearlyPos: + default: + mFloats = true; + break; + } +} + +void Recurrence::setFloats(bool f) +{ + switch (recurs) + { + case rDaily: + case rWeekly: + case rMonthlyPos: + case rMonthlyDay: + case rYearlyMonth: + case rYearlyDay: + case rYearlyPos: + break; + case rMinutely: + case rHourly: + default: + return; // can't set sub-daily to floating + } + mFloats = f; + if (f) { + mRecurStart.setTime(QTime(0,0,0)); + rEndDateTime.setTime(QTime(0,0,0)); + } +} + +int Recurrence::frequency() const +{ + return rFreq; +} + +int Recurrence::duration() const +{ + return rDuration; +} + +void Recurrence::setDuration(int _rDuration) +{ + if (mRecurReadOnly) return; + if (_rDuration > 0) { + rDuration = _rDuration; + // Compatibility mode is only needed when reading the calendar in ICalFormatImpl, + // so explicitly setting the duration means no backwards compatibility is needed. + mCompatDuration = 0; + } +} + +QString Recurrence::endDateStr(bool shortfmt) const +{ + return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt); +} + +const QBitArray &Recurrence::days() const +{ + return rDays; +} + +const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const +{ + return rMonthPositions; +} + +const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const +{ + return rMonthPositions; +} + +const QPtrList<int> &Recurrence::monthDays() const +{ + return rMonthDays; +} + +void Recurrence::setMinutely(int _rFreq, int _rDuration) +{ + if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) + return; + setDailySub(rMinutely, _rFreq, _rDuration); +} + +void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime) +{ + if (mRecurReadOnly) return; + rEndDateTime = _rEndDateTime; + setDailySub(rMinutely, _rFreq, 0); +} + +void Recurrence::setHourly(int _rFreq, int _rDuration) +{ + if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) + return; + setDailySub(rHourly, _rFreq, _rDuration); +} + +void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime) +{ + if (mRecurReadOnly) return; + rEndDateTime = _rEndDateTime; + setDailySub(rHourly, _rFreq, 0); +} + +void Recurrence::setDaily(int _rFreq, int _rDuration) +{ + if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) + return; + setDailySub(rDaily, _rFreq, _rDuration); +} + +void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate) +{ + if (mRecurReadOnly) return; + rEndDateTime.setDate(_rEndDate); + rEndDateTime.setTime(mRecurStart.time()); + setDailySub(rDaily, _rFreq, 0); +} + +void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, + int _rDuration, int _rWeekStart) +{ + if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) + return; + recurs = rWeekly; + + rFreq = _rFreq; + rDays = _rDays; + rWeekStart = _rWeekStart; + rDuration = _rDuration; + if (mCompatVersion < 310 && _rDuration > 0) { + // Backwards compatibility for KDE < 3.1. + // rDuration was set to the number of time periods to recur, + // with week start always on a Monday. + // Convert this to the number of occurrences. + mCompatDuration = _rDuration; + int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek()); + QDate end(mRecurStart.date().addDays(weeks * rFreq)); + rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly + rDuration = weeklyCalc(COUNT_TO_DATE, end); + } else { + mCompatDuration = 0; + } + rMonthPositions.clear(); + rMonthDays.clear(); + if (mParent) mParent->updated(); +} + +void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, + const QDate &_rEndDate, int _rWeekStart) +{ + if (mRecurReadOnly) return; + recurs = rWeekly; + + rFreq = _rFreq; + rDays = _rDays; + rWeekStart = _rWeekStart; + rEndDateTime.setDate(_rEndDate); + rEndDateTime.setTime(mRecurStart.time()); + rDuration = 0; // set to 0 because there is an end date + mCompatDuration = 0; + rMonthPositions.clear(); + rMonthDays.clear(); + rYearNums.clear(); + if (mParent) mParent->updated(); +} + +void Recurrence::setMonthly(short type, int _rFreq, int _rDuration) +{ + if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) + return; + recurs = type; + + rFreq = _rFreq; + rDuration = _rDuration; + if (mCompatVersion < 310) + mCompatDuration = (_rDuration > 0) ? _rDuration : 0; + rYearNums.clear(); + if (mParent) mParent->updated(); +} + +void Recurrence::setMonthly(short type, int _rFreq, + const QDate &_rEndDate) +{ + if (mRecurReadOnly) return; + recurs = type; + + rFreq = _rFreq; + rEndDateTime.setDate(_rEndDate); + rEndDateTime.setTime(mRecurStart.time()); + rDuration = 0; // set to 0 because there is an end date + mCompatDuration = 0; + rYearNums.clear(); + if (mParent) mParent->updated(); +} + +void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays) +{ + if (recurs == rMonthlyPos) + addMonthlyPos_(_rPos, _rDays); +} + +void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays) +{ + if (mRecurReadOnly + || _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number + return; + + for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) { + int itPos = it->negative ? -it->rPos : it->rPos; + if (_rPos == itPos) { + // This week is already in the list. + // Combine the specified days with those in the list. + it->rDays |= _rDays; + if (mParent) mParent->updated(); + return; + } + } + // Add the new position to the list + rMonthPos *tmpPos = new rMonthPos; + if (_rPos > 0) { + tmpPos->rPos = _rPos; + tmpPos->negative = false; + } else { + tmpPos->rPos = -_rPos; // take abs() + tmpPos->negative = true; + } + tmpPos->rDays = _rDays; + tmpPos->rDays.detach(); + rMonthPositions.append(tmpPos); + + if (mCompatVersion < 310 && mCompatDuration > 0) { + // Backwards compatibility for KDE < 3.1. + // rDuration was set to the number of time periods to recur. + // Convert this to the number of occurrences. + int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; + int month = mRecurStart.date().month() - 1 + monthsAhead; + QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); + rDuration = INT_MAX; // ensure that recurCalc() does its job correctly + rDuration = recurCalc(COUNT_TO_DATE, end); + } + + if (mParent) mParent->updated(); +} + +void Recurrence::addMonthlyDay(short _rDay) +{ + if (mRecurReadOnly || recurs != rMonthlyDay + || _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number + return; + for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) { + if (_rDay == *it) + return; // this day is already in the list - avoid duplication + } + int *tmpDay = new int; + *tmpDay = _rDay; + rMonthDays.append(tmpDay); + + if (mCompatVersion < 310 && mCompatDuration > 0) { + // Backwards compatibility for KDE < 3.1. + // rDuration was set to the number of time periods to recur. + // Convert this to the number of occurrences. + int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; + int month = mRecurStart.date().month() - 1 + monthsAhead; + QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); + rDuration = INT_MAX; // ensure that recurCalc() does its job correctly + rDuration = recurCalc(COUNT_TO_DATE, end); + } + + if (mParent) mParent->updated(); +} + +void Recurrence::setYearly(int type, int _rFreq, int _rDuration) +{ + if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) + return; + if (mCompatVersion < 310) + mCompatDuration = (_rDuration > 0) ? _rDuration : 0; + setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration); +} + +void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate) +{ + if (mRecurReadOnly) return; + rEndDateTime.setDate(_rEndDate); + rEndDateTime.setTime(mRecurStart.time()); + mCompatDuration = 0; + setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0); +} + +void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration) +{ + if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) + return; + if (mCompatVersion < 310) + mCompatDuration = (_rDuration > 0) ? _rDuration : 0; + setYearly_(rYearlyMonth, type, _rFreq, _rDuration); +} + +void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate) +{ + if (mRecurReadOnly) return; + rEndDateTime.setDate(_rEndDate); + rEndDateTime.setTime(mRecurStart.time()); + mCompatDuration = 0; + setYearly_(rYearlyMonth, type, _rFreq, 0); +} + +void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays) +{ + if (recurs == rYearlyPos) + addMonthlyPos_(_rPos, _rDays); +} + +const QPtrList<int> &Recurrence::yearNums() const +{ + return rYearNums; +} + +void Recurrence::addYearlyNum(short _rNum) +{ + if (mRecurReadOnly + || (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos) + || _rNum <= 0) // invalid day/month number + return; + + if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) { + // Backwards compatibility for KDE < 3.1. + // Dates were stored as day numbers, with a fiddle to take account of leap years. + // Convert the day number to a month. + if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366)) + return; // invalid day number + _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month(); + } else + if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12 + || recurs == rYearlyDay && _rNum > 366) + return; // invalid day number + + uint i = 0; + for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) { + if (_rNum == *it) + return; // this day/month is already in the list - avoid duplication + ++i; + } + + int *tmpNum = new int; + *tmpNum = _rNum; + rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position + + if (mCompatVersion < 310 && mCompatDuration > 0) { + // Backwards compatibility for KDE < 3.1. + // rDuration was set to the number of time periods to recur. + // Convert this to the number of occurrences. + QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31); + rDuration = INT_MAX; // ensure that recurCalc() does its job correctly + rDuration = recurCalc(COUNT_TO_DATE, end); + } + + if (mParent) mParent->updated(); +} + + +QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const +{ + if (last) + *last = false; + int freq; + switch (recurs) + { + case rMinutely: + freq = rFreq * 60; + break; + case rHourly: + freq = rFreq * 3600; + break; + case rDaily: + case rWeekly: + case rMonthlyPos: + case rMonthlyDay: + case rYearlyMonth: + case rYearlyDay: + case rYearlyPos: { + QDate preDate = preDateTime.date(); + if (!mFloats && mRecurStart.time() > preDateTime.time()) + preDate = preDate.addDays(-1); + return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time()); + } + default: + return QDateTime(); + } + + // It's a sub-daily recurrence + if (preDateTime < mRecurStart) + return mRecurStart; + int count = mRecurStart.secsTo(preDateTime) / freq + 2; + if (rDuration > 0) { + if (count > rDuration) + return QDateTime(); + if (last && count == rDuration) + *last = true; + } + QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); + if (rDuration == 0) { + if (endtime > rEndDateTime) + return QDateTime(); + if (last && endtime == rEndDateTime) + *last = true; + } + return endtime; +} + +QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const +{ + if (last) + *last = false; + switch (recurs) + { + case rMinutely: + case rHourly: + return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date(); + case rDaily: + case rWeekly: + case rMonthlyPos: + case rMonthlyDay: + case rYearlyMonth: + case rYearlyDay: + case rYearlyPos: + return getNextDateNoTime(preDate, last); + default: + return QDate(); + } +} + + +QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const +{ + if (last) + *last = false; + int freq; + switch (recurs) + { + case rMinutely: + freq = rFreq * 60; + break; + case rHourly: + freq = rFreq * 3600; + break; + case rDaily: + case rWeekly: + case rMonthlyPos: + case rMonthlyDay: + case rYearlyMonth: + case rYearlyDay: + case rYearlyPos: { + QDate afterDate = afterDateTime.date(); + if (!mFloats && mRecurStart.time() < afterDateTime.time()) + afterDate = afterDate.addDays(1); + return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time()); + } + default: + return QDateTime(); + } + + // It's a sub-daily recurrence + if (afterDateTime <= mRecurStart) + return QDateTime(); + int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1; + if (rDuration > 0) { + if (count > rDuration) + count = rDuration; + if (last && count == rDuration) + *last = true; + } + QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); + if (rDuration == 0) { + if (endtime > rEndDateTime) + endtime = rEndDateTime; + if (last && endtime == rEndDateTime) + *last = true; + } + return endtime; +} + +QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const +{ + if (last) + *last = false; + switch (recurs) + { + case rMinutely: + case rHourly: + return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date(); + case rDaily: + case rWeekly: + case rMonthlyPos: + case rMonthlyDay: + case rYearlyMonth: + case rYearlyDay: + case rYearlyPos: + return getPreviousDateNoTime(afterDate, last); + default: + return QDate(); + } +} + + +/***************************** PROTECTED FUNCTIONS ***************************/ + +bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const +{ + if ((qd >= mRecurStart.date()) && + ((rDuration > 0) && (qd <= endDate()) || + ((rDuration == 0) && (qd <= rEndDateTime.date())) || + (rDuration == -1))) { + // The date queried falls within the range of the event. + if (secondFreq < 24*3600) + return true; // the event recurs at least once each day + int after = mRecurStart.secsTo(QDateTime(qd)); + if (after / secondFreq != (after + 24*3600) / secondFreq) + return true; + } + return false; +} + +bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const +{ + if ((dt >= mRecurStart) && + ((rDuration > 0) && (dt <= endDateTime()) || + ((rDuration == 0) && (dt <= rEndDateTime)) || + (rDuration == -1))) { + // The time queried falls within the range of the event. + if (((mRecurStart.secsTo(dt) / 60) % minuteFreq) == 0) + return true; + } + return false; +} + +bool Recurrence::recursDaily(const QDate &qd) const +{ + QDate dStart = mRecurStart.date(); + if ((dStart.daysTo(qd) % rFreq) == 0) { + // The date is a day which recurs + if (qd >= dStart + && ((rDuration > 0 && qd <= endDate()) || + (rDuration == 0 && qd <= rEndDateTime.date()) || + rDuration == -1)) { + // The date queried falls within the range of the event. + return true; + } + } + return false; +} + +bool Recurrence::recursWeekly(const QDate &qd) const +{ + QDate dStart = mRecurStart.date(); + if ((dStart.daysTo(qd)/7) % rFreq == 0) { + // The date is in a week which recurs + if (qd >= dStart + && ((rDuration > 0 && qd <= endDate()) || + (rDuration == 0 && qd <= rEndDateTime.date()) || + rDuration == -1)) { + // The date queried falls within the range of the event. + // check if the bits set match today. + int i = qd.dayOfWeek()-1; + if (rDays.testBit((uint) i)) + return true; + } + } + return false; +} + +bool Recurrence::recursMonthly(const QDate &qd) const +{ + QDate dStart = mRecurStart.date(); + int year = qd.year(); + int month = qd.month(); + int day = qd.day(); + // calculate how many months ahead this date is from the original + // event's date + int monthsAhead = (year - dStart.year()) * 12 + (month - dStart.month()); + if ((monthsAhead % rFreq) == 0) { + // The date is in a month which recurs + if (qd >= dStart + && ((rDuration > 0 && qd <= endDate()) || + (rDuration == 0 && qd <= rEndDateTime.date()) || + rDuration == -1)) { + // The date queried falls within the range of the event. + QValueList<int> days; + int daysInMonth = qd.daysInMonth(); + if (recurs == rMonthlyDay) + getMonthlyDayDays(days, daysInMonth); + else if (recurs == rMonthlyPos) + getMonthlyPosDays(days, daysInMonth, QDate(year, month, 1).dayOfWeek()); + for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { + if (*it == day) + return true; + } + // no dates matched + } + } + return false; +} + +bool Recurrence::recursYearlyByMonth(const QDate &qd) const +{ + QDate dStart = mRecurStart.date(); + int startDay = dStart.day(); + int qday = qd.day(); + int qmonth = qd.month(); + int qyear = qd.year(); + bool match = (qday == startDay); + if (!match && startDay == 29 && dStart.month() == 2) { + // It's a recurrence on February 29th + switch (mFeb29YearlyType) { + case rFeb28: + if (qday == 28 && qmonth == 2 && !QDate::leapYear(qyear)) + match = true; + break; + case rMar1: + if (qday == 1 && qmonth == 3 && !QDate::leapYear(qyear)) { + qmonth = 2; + match = true; + } + break; + case rFeb29: + break; + } + } + + if (match) { + // The day of the month matches. Calculate how many years ahead + // this date is from the original event's date. + int yearsAhead = (qyear - dStart.year()); + if (yearsAhead % rFreq == 0) { + // The date is in a year which recurs + if (qd >= dStart + && ((rDuration > 0 && qd <= endDate()) || + (rDuration == 0 && qd <= rEndDateTime.date()) || + rDuration == -1)) { + // The date queried falls within the range of the event. + int i = qmonth; + for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { + if (i == *qlin.current()) + return true; + } + } + } + } + return false; +} + +bool Recurrence::recursYearlyByPos(const QDate &qd) const +{ + QDate dStart = mRecurStart.date(); + int year = qd.year(); + int month = qd.month(); + int day = qd.day(); + // calculate how many years ahead this date is from the original + // event's date + int yearsAhead = (year - dStart.year()); + if (yearsAhead % rFreq == 0) { + // The date is in a year which recurs + if (qd >= dStart + && ((rDuration > 0 && qd <= endDate()) || + (rDuration == 0 && qd <= rEndDateTime.date()) || + rDuration == -1)) { + // The date queried falls within the range of the event. + for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { + if (month == *qlin.current()) { + // The month recurs + QValueList<int> days; + getMonthlyPosDays(days, qd.daysInMonth(), QDate(year, month, 1).dayOfWeek()); + for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { + if (*it == day) + return true; + } + } + } + } + } + return false; +} + +bool Recurrence::recursYearlyByDay(const QDate &qd) const +{ + QDate dStart = mRecurStart.date(); + // calculate how many years ahead this date is from the original + // event's date + int yearsAhead = (qd.year() - dStart.year()); + if (yearsAhead % rFreq == 0) { + // The date is in a year which recurs + if (qd >= dStart + && ((rDuration > 0 && qd <= endDate()) || + (rDuration == 0 && qd <= rEndDateTime.date()) || + rDuration == -1)) { + // The date queried falls within the range of the event. + int i = qd.dayOfYear(); + for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { + if (i == *qlin.current()) + return true; + } + } + } + return false; +} + +/* Get the date of the next recurrence, after the specified date. + * If 'last' is non-null, '*last' is set to true if the next recurrence is the + * last recurrence, else false. + * Reply = date of next recurrence, or invalid date if none. + */ +QDate Recurrence::getNextDateNoTime(const QDate &preDate, bool *last) const +{ + if (last) + *last = false; + QDate dStart = mRecurStart.date(); + if (preDate < dStart) + return dStart; + QDate earliestDate = preDate.addDays(1); + QDate nextDate; + + switch (recurs) { + case rDaily: + nextDate = dStart.addDays((dStart.daysTo(preDate)/rFreq + 1) * rFreq); + break; + + case rWeekly: { + QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart + int earliestDayOfWeek = earliestDate.dayOfWeek(); + int weeksAhead = start.daysTo(earliestDate) / 7; + int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week + weeksAhead -= notThisWeek; // latest week which recurred + int weekday = 0; + // First check for any remaining day this week, if this week is a recurring week + if (!notThisWeek) + weekday = getFirstDayInWeek(earliestDayOfWeek); + // Check for a day in the next scheduled week + if (!weekday && earliestDayOfWeek > 1) + weekday = getFirstDayInWeek(rWeekStart) + rFreq*7; + if (weekday) + nextDate = start.addDays(weeksAhead*7 + weekday - 1); + break; + } + case rMonthlyDay: + case rMonthlyPos: { + int startYear = dStart.year(); + int startMonth = dStart.month(); // 1..12 + int earliestYear = earliestDate.year(); + int monthsAhead = (earliestYear - startYear)*12 + earliestDate.month() - startMonth; + int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month + monthsAhead -= notThisMonth; // latest month which recurred + // Check for the first later day in the current month + if (!notThisMonth) + nextDate = getFirstDateInMonth(earliestDate); + if (!nextDate.isValid() && earliestDate.day() > 1) { + // Check for a day in the next scheduled month + int months = startMonth - 1 + monthsAhead + rFreq; + nextDate = getFirstDateInMonth(QDate(startYear + months/12, months%12 + 1, 1)); + } + break; + } + case rYearlyMonth: + case rYearlyPos: + case rYearlyDay: { + int startYear = dStart.year(); + int yearsAhead = earliestDate.year() - startYear; + int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year + yearsAhead -= notThisYear; // latest year which recurred + // Check for the first later date in the current year + if (!notThisYear) + nextDate = getFirstDateInYear(earliestDate); + // Check for a date in the next scheduled year + if (!nextDate.isValid() && earliestDate.dayOfYear() > 1) + nextDate = getFirstDateInYear(QDate(startYear + yearsAhead + rFreq, 1, 1)); + break; + } + case rNone: + default: + return QDate(); + } + + if (rDuration >= 0 && nextDate.isValid()) { + // Check that the date found is within the range of the recurrence + QDate end = endDate(); + if (nextDate > end) + return QDate(); + if (last && nextDate == end) + *last = true; + } + return nextDate; +} + +/* Get the date of the last previous recurrence, before the specified date. + * Reply = date of previous recurrence, or invalid date if none. + */ +QDate Recurrence::getPreviousDateNoTime(const QDate &afterDate, bool *last) const +{ + if (last) + *last = false; + QDate dStart = mRecurStart.date(); + QDate latestDate = afterDate.addDays(-1); + if (latestDate < dStart) + return QDate(); + QDate prevDate; + + switch (recurs) { + case rDaily: + prevDate = dStart.addDays((dStart.daysTo(latestDate) / rFreq) * rFreq); + break; + + case rWeekly: { + QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart + int latestDayOfWeek = latestDate.dayOfWeek(); + int weeksAhead = start.daysTo(latestDate) / 7; + int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week + weeksAhead -= notThisWeek; // latest week which recurred + int weekday = 0; + // First check for any previous day this week, if this week is a recurring week + if (!notThisWeek) + weekday = getLastDayInWeek(latestDayOfWeek); + // Check for a day in the previous scheduled week + if (!weekday) { + int weekEnd = (rWeekStart + 5)%7 + 1; + if (latestDayOfWeek < weekEnd) { + if (!notThisWeek) + weeksAhead -= rFreq; + weekday = getLastDayInWeek(weekEnd); + } + } + if (weekday) + prevDate = start.addDays(weeksAhead*7 + weekday - 1); + break; + } + case rMonthlyDay: + case rMonthlyPos: { + int startYear = dStart.year(); + int startMonth = dStart.month(); // 1..12 + int latestYear = latestDate.year(); + int monthsAhead = (latestYear - startYear)*12 + latestDate.month() - startMonth; + int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month + monthsAhead -= notThisMonth; // latest month which recurred + // Check for the last earlier day in the current month + if (!notThisMonth) + prevDate = getLastDateInMonth(latestDate); + if (!prevDate.isValid() && latestDate.day() < latestDate.daysInMonth()) { + // Check for a day in the previous scheduled month + if (!notThisMonth) + monthsAhead -= rFreq; + int months = startMonth + monthsAhead; // get the month after the one that recurs + prevDate = getLastDateInMonth(QDate(startYear + months/12, months%12 + 1, 1).addDays(-1)); + } + break; + } + case rYearlyMonth: + case rYearlyPos: + case rYearlyDay: { + int startYear = dStart.year(); + int yearsAhead = latestDate.year() - startYear; + int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year + yearsAhead -= notThisYear; // latest year which recurred + // Check for the first later date in the current year + if (!notThisYear) + prevDate = getLastDateInYear(latestDate); + if (!prevDate.isValid() && latestDate.dayOfYear() < latestDate.daysInYear()) { + // Check for a date in the next scheduled year + if (!notThisYear) + yearsAhead -= rFreq; + prevDate = getLastDateInYear(QDate(startYear + yearsAhead, 12, 31)); + } + break; + } + case rNone: + default: + return QDate(); + } + + if (prevDate.isValid()) { + // Check that the date found is within the range of the recurrence + if (prevDate < dStart) + return QDate(); + if (rDuration >= 0) { + QDate end = endDate(); + if (prevDate >= end) { + if (last) + *last = true; + return end; + } + } + } + return prevDate; +} + +void Recurrence::setDailySub(short type, int freq, int duration) +{ + recurs = type; + rFreq = freq; + rDuration = duration; + rMonthPositions.clear(); + rMonthDays.clear(); + rYearNums.clear(); + if (type != rDaily) + mFloats = false; // sub-daily types can't be floating + + if (mParent) mParent->updated(); +} + +void Recurrence::setYearly_(short type, Feb29Type feb29type, int freq, int duration) +{ + recurs = type; + if (mCompatVersion < 310 && type == rYearlyDay) { + mCompatRecurs = rYearlyDay; + recurs = rYearlyMonth; // convert old yearly-by-day to yearly-by-month + feb29type = rMar1; // retain the same day number in the year + } + + mFeb29YearlyType = feb29type; + rFreq = freq; + rDuration = duration; + if (type != rYearlyPos) + rMonthPositions.clear(); + rMonthDays.clear(); + if (mParent) mParent->updated(); +} + +int Recurrence::recurCalc(PeriodFunc func, QDateTime &endtime) const +{ + QDate enddate = endtime.date(); + switch (func) { + case END_DATE_AND_COUNT: + if (rDuration < 0) { + endtime = QDateTime(); + return 0; // infinite recurrence + } + if (rDuration == 0) { + endtime = rEndDateTime; + func = COUNT_TO_DATE; + } + break; + case COUNT_TO_DATE: + // Count recurrences up to and including the specified date/time. + if (endtime < mRecurStart) + return 0; + if (rDuration == 0 && endtime > rEndDateTime) + enddate = rEndDateTime.date(); + else if (!mFloats && mRecurStart.time() > endtime.time()) + enddate = enddate.addDays(-1); + break; + case NEXT_AFTER_DATE: + // Find next recurrence AFTER endtime + if (endtime < mRecurStart) { + endtime = mRecurStart; + return 1; + } + if (rDuration == 0 && endtime >= rEndDateTime) { + endtime = QDateTime(); + return 0; + } + if (!mFloats && mRecurStart.time() > endtime.time()) + enddate = enddate.addDays(-1); + break; + default: + endtime = QDateTime(); + return 0; + } + + int count = 0; // default = error + bool timed = false; + switch (recurs) { + case rMinutely: + timed = true; + count = secondlyCalc(func, endtime, rFreq*60); + break; + case rHourly: + timed = true; + count = secondlyCalc(func, endtime, rFreq*3600); + break; + case rDaily: + count = dailyCalc(func, enddate); + break; + case rWeekly: + count = weeklyCalc(func, enddate); + break; + case rMonthlyPos: + case rMonthlyDay: + count = monthlyCalc(func, enddate); + break; + case rYearlyMonth: + count = yearlyMonthCalc(func, enddate); + break; + case rYearlyPos: + count = yearlyPosCalc(func, enddate); + break; + case rYearlyDay: + count = yearlyDayCalc(func, enddate); + break; + default: + break; + } + + switch (func) { + case END_DATE_AND_COUNT: + case NEXT_AFTER_DATE: + if (count == 0) + endtime = QDateTime(); + else if (!timed) { + endtime.setDate(enddate); + endtime.setTime(mRecurStart.time()); + } + break; + case COUNT_TO_DATE: + break; + } + return count; +} + +int Recurrence::recurCalc(PeriodFunc func, QDate &enddate) const +{ + QDateTime endtime(enddate, QTime(23,59,59)); + switch (func) { + case END_DATE_AND_COUNT: + if (rDuration < 0) { + enddate = QDate(); + return 0; // infinite recurrence + } + if (rDuration == 0) { + enddate = rEndDateTime.date(); + func = COUNT_TO_DATE; + } + break; + case COUNT_TO_DATE: + // Count recurrences up to and including the specified date. + if (enddate < mRecurStart.date()) + return 0; + if (rDuration == 0 && enddate > rEndDateTime.date()) { + enddate = rEndDateTime.date(); + endtime.setDate(enddate); + } + break; + case NEXT_AFTER_DATE: + if (enddate < mRecurStart.date()) { + enddate = mRecurStart.date(); + return 1; + } + if (rDuration == 0 && enddate >= rEndDateTime.date()) { + enddate = QDate(); + return 0; + } + break; + default: + enddate = QDate(); + return 0; + } + + int count = 0; // default = error + bool timed = false; + switch (recurs) { + case rMinutely: + timed = true; + count = secondlyCalc(func, endtime, rFreq*60); + break; + case rHourly: + timed = true; + count = secondlyCalc(func, endtime, rFreq*3600); + break; + case rDaily: + count = dailyCalc(func, enddate); + break; + case rWeekly: + count = weeklyCalc(func, enddate); + break; + case rMonthlyPos: + case rMonthlyDay: + count = monthlyCalc(func, enddate); + break; + case rYearlyMonth: + count = yearlyMonthCalc(func, enddate); + break; + case rYearlyPos: + count = yearlyPosCalc(func, enddate); + break; + case rYearlyDay: + count = yearlyDayCalc(func, enddate); + break; + default: + break; + } + + switch (func) { + case END_DATE_AND_COUNT: + case NEXT_AFTER_DATE: + if (count == 0) + endtime = QDate(); + else if (timed) + enddate = endtime.date(); + break; + case COUNT_TO_DATE: + break; + } + return count; +} + +/* Find count and, depending on 'func', the end date/time of a secondly recurrence. + * Reply = total number of occurrences up to 'endtime', or 0 if error. + * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'endtime' is updated to the + * recurrence end date/time. + */ +int Recurrence::secondlyCalc(PeriodFunc func, QDateTime &endtime, int freq) const +{ + switch (func) { + case END_DATE_AND_COUNT: + endtime = mRecurStart.addSecs((rDuration + mRecurExDatesCount - 1) * freq); + return rDuration + mRecurExDatesCount; + case COUNT_TO_DATE: { + int n = mRecurStart.secsTo(endtime)/freq + 1; + if (rDuration > 0 && n > rDuration + mRecurExDatesCount) + return rDuration + mRecurExDatesCount; + return n; + } + case NEXT_AFTER_DATE: { + int count = mRecurStart.secsTo(endtime) / freq + 2; + if (rDuration > 0 && count > rDuration) + return 0; + endtime = mRecurStart.addSecs((count - 1)*freq); + return count; + } + } + return 0; +} + +/* Find count and, depending on 'func', the end date of a daily recurrence. + * Reply = total number of occurrences up to 'enddate', or 0 if error. + * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the + * recurrence end date. + */ +int Recurrence::dailyCalc(PeriodFunc func, QDate &enddate) const +{ + QDate dStart = mRecurStart.date(); + switch (func) { + case END_DATE_AND_COUNT: + enddate = dStart.addDays((rDuration + mRecurExDatesCount - 1) * rFreq); + return rDuration + mRecurExDatesCount; + case COUNT_TO_DATE: { + int n = dStart.daysTo(enddate)/rFreq + 1; + if (rDuration > 0 && n > rDuration + mRecurExDatesCount) + return rDuration + mRecurExDatesCount; + return n; + } + case NEXT_AFTER_DATE: { + int count = dStart.daysTo(enddate) / rFreq + 2; + if (rDuration > 0 && count > rDuration) + return 0; + enddate = dStart.addDays((count - 1)*rFreq); + return count; + } + } + return 0; +} + +/* Find count and, depending on 'func', the end date of a weekly recurrence. + * Reply = total number of occurrences up to 'enddate', or 0 if error. + * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the + * recurrence end date. + */ +int Recurrence::weeklyCalc(PeriodFunc func, QDate &enddate) const +{ + int daysPerWeek = 0; + for (int i = 0; i < 7; ++i) { + if (rDays.testBit((uint)i)) + ++daysPerWeek; + } + if (!daysPerWeek) + return 0; // there are no days to recur on + + switch (func) { + case END_DATE_AND_COUNT: + return weeklyCalcEndDate(enddate, daysPerWeek); + case COUNT_TO_DATE: + return weeklyCalcToDate(enddate, daysPerWeek); + case NEXT_AFTER_DATE: + return weeklyCalcNextAfter(enddate, daysPerWeek); + } + return 0; +} + +int Recurrence::weeklyCalcEndDate(QDate &enddate, int daysPerWeek) const +{ + int startDayOfWeek = mRecurStart.date().dayOfWeek(); // 1..7 + int countGone = 0; + int daysGone = 0; + uint countTogo = rDuration + mRecurExDatesCount; + if (startDayOfWeek != rWeekStart) { + // Check what remains of the start week + for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { + ++daysGone; + if (rDays.testBit((uint)i)) { + ++countGone; + if (--countTogo == 0) + break; + } + } + daysGone += 7 * (rFreq - 1); + } + if (countTogo) { + // Skip the remaining whole weeks + // Leave at least 1 recurrence remaining, in order to get its date + int wholeWeeks = (countTogo - 1) / daysPerWeek; + daysGone += wholeWeeks * 7 * rFreq; + countGone += wholeWeeks * daysPerWeek; + countTogo -= wholeWeeks * daysPerWeek; + // Check the last week in the recurrence + for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { + ++daysGone; + if (rDays.testBit((uint)i)) { + ++countGone; + if (--countTogo == 0) + break; + } + } + } + enddate = mRecurStart.date().addDays(daysGone); + return countGone; +} + +int Recurrence::weeklyCalcToDate(const QDate &enddate, int daysPerWeek) const +{ + QDate dStart = mRecurStart.date(); + int startDayOfWeek = dStart.dayOfWeek(); // 1..7 + int countGone = 0; + int daysGone = 0; + int totalDays = dStart.daysTo(enddate) + 1; + int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; + + if (startDayOfWeek != rWeekStart) { + // Check what remains of the start week + for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { + if (rDays.testBit((uint)i)) { + if (++countGone >= countMax) + return countMax; + } + if (++daysGone == totalDays) + return countGone; + } + daysGone += 7 * (rFreq - 1); + if (daysGone >= totalDays) + return countGone; + } + // Skip the remaining whole weeks + int wholeWeeks = (totalDays - daysGone) / 7; + countGone += (wholeWeeks / rFreq) * daysPerWeek; + if (countGone >= countMax) + return countMax; + daysGone += wholeWeeks * 7; + if (daysGone >= totalDays // have we reached the end date? + || wholeWeeks % rFreq) // is end week a recurrence week? + return countGone; + + // Check the last week in the recurrence + for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { + if (rDays.testBit((uint)i)) { + if (++countGone >= countMax) + return countMax; + } + if (++daysGone == totalDays) + return countGone; + } + return countGone; +} + +int Recurrence::weeklyCalcNextAfter(QDate &enddate, int daysPerWeek) const +{ + QDate dStart = mRecurStart.date(); + int startDayOfWeek = dStart.dayOfWeek(); // 1..7 + int totalDays = dStart.daysTo(enddate) + 1; + uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; + int countGone = 0; + int daysGone = 0; + int recurWeeks; + + if (startDayOfWeek != rWeekStart) { + // Check what remains of the start week + for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { + ++daysGone; + if (rDays.testBit((uint)i)) { + ++countGone; + if (daysGone > totalDays) + goto ex; + if (--countTogo == 0) + return 0; + } + } + daysGone += 7 * (rFreq - 1); + } + + // Skip the remaining whole weeks + recurWeeks = (totalDays - daysGone) / (7 * rFreq); + if (recurWeeks) { + int n = recurWeeks * daysPerWeek; + if (static_cast<uint>(n) > countTogo) + return 0; // reached end of recurrence + countGone += n; + countTogo -= n; + daysGone += recurWeeks * 7 * rFreq; + } + + // Check the last week or two in the recurrence + for ( ; ; ) { + for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { + ++daysGone; + if (rDays.testBit((uint)i)) { + ++countGone; + if (daysGone > totalDays) + goto ex; + if (--countTogo == 0) + return 0; + } + } + daysGone += 7 * (rFreq - 1); + } +ex: + enddate = dStart.addDays(daysGone); + return countGone; +} + +/* Find count and, depending on 'func', the end date of a monthly recurrence. + * Reply = total number of occurrences up to 'enddate', or 0 if error. + * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the + * recurrence end date. + */ +struct Recurrence::MonthlyData { + const Recurrence *recurrence; + int year; // current year + int month; // current month 0..11 + int day; // current day of month 1..31 + bool varies; // true if recurring days vary between different months + private: + QValueList<int> days28, days29, days30, days31; // recurring days in months of each length + QValueList<int> *recurDays[4]; + public: + MonthlyData(const Recurrence* r, const QDate &date) + : recurrence(r), year(date.year()), month(date.month()-1), day(date.day()) + { recurDays[0] = &days28; + recurDays[1] = &days29; + recurDays[2] = &days30; + recurDays[3] = &days31; + varies = (recurrence->recurs == rMonthlyPos) + ? true : recurrence->getMonthlyDayDays(days31, 31); + } + const QValueList<int>* dayList() const { + if (!varies) + return &days31; + QDate startOfMonth(year, month + 1, 1); + int daysInMonth = startOfMonth.daysInMonth(); + QValueList<int>* days = recurDays[daysInMonth - 28]; + if (recurrence->recurs == rMonthlyPos) + recurrence->getMonthlyPosDays(*days, daysInMonth, startOfMonth.dayOfWeek()); + else if (days->isEmpty()) + recurrence->getMonthlyDayDays(*days, daysInMonth); + return days; + } + int yearMonth() const { return year*12 + month; } + void addMonths(int diff) { month += diff; year += month / 12; month %= 12; } + QDate date() const { return QDate(year, month + 1, day); } +}; + +int Recurrence::monthlyCalc(PeriodFunc func, QDate &enddate) const +{ + if (recurs == rMonthlyPos && rMonthPositions.isEmpty() + || recurs == rMonthlyDay && rMonthDays.isEmpty()) + return 0; + + MonthlyData data(this, mRecurStart.date()); + switch (func) { + case END_DATE_AND_COUNT: + return monthlyCalcEndDate(enddate, data); + case COUNT_TO_DATE: + return monthlyCalcToDate(enddate, data); + case NEXT_AFTER_DATE: + return monthlyCalcNextAfter(enddate, data); + } + return 0; +} + +int Recurrence::monthlyCalcEndDate(QDate &enddate, MonthlyData &data) const +{ + uint countTogo = rDuration + mRecurExDatesCount; + int countGone = 0; + QValueList<int>::ConstIterator it; + const QValueList<int>* days = data.dayList(); + + if (data.day > 1) { + // Check what remains of the start month + for (it = days->begin(); it != days->end(); ++it) { + if (*it >= data.day) { + ++countGone; + if (--countTogo == 0) { + data.day = *it; + break; + } + } + } + if (countTogo) { + data.day = 1; + data.addMonths(rFreq); + } + } + if (countTogo) { + if (data.varies) { + // The number of recurrence days varies from month to month, + // so we need to check month by month. + for ( ; ; ) { + days = data.dayList(); + uint n = days->count(); // number of recurrence days in this month + if (n >= countTogo) + break; + countTogo -= n; + countGone += n; + data.addMonths(rFreq); + } + } else { + // The number of recurrences is the same every month, + // so skip the month-by-month check. + // Skip the remaining whole months, but leave at least + // 1 recurrence remaining, in order to get its date. + int daysPerMonth = days->count(); + int wholeMonths = (countTogo - 1) / daysPerMonth; + data.addMonths(wholeMonths * rFreq); + countGone += wholeMonths * daysPerMonth; + countTogo -= wholeMonths * daysPerMonth; + } + if (countTogo) { + // Check the last month in the recurrence + for (it = days->begin(); it != days->end(); ++it) { + ++countGone; + if (--countTogo == 0) { + data.day = *it; + break; + } + } + } + } + enddate = data.date(); + return countGone; +} + +int Recurrence::monthlyCalcToDate(const QDate &enddate, MonthlyData &data) const +{ + int countGone = 0; + int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; + int endYear = enddate.year(); + int endMonth = enddate.month() - 1; // zero-based + int endDay = enddate.day(); + int endYearMonth = endYear*12 + endMonth; + QValueList<int>::ConstIterator it; + const QValueList<int>* days = data.dayList(); + + if (data.day > 1) { + // Check what remains of the start month + for (it = days->begin(); it != days->end(); ++it) { + if (*it >= data.day) { + if (data.yearMonth() == endYearMonth && *it > endDay) + return countGone; + if (++countGone >= countMax) + return countMax; + } + } + data.day = 1; + data.addMonths(rFreq); + } + + if (data.varies) { + // The number of recurrence days varies from month to month, + // so we need to check month by month. + while (data.yearMonth() < endYearMonth) { + countGone += data.dayList()->count(); + if (countGone >= countMax) + return countMax; + data.addMonths(rFreq); + } + days = data.dayList(); + } else { + // The number of recurrences is the same every month, + // so skip the month-by-month check. + // Skip the remaining whole months. + int daysPerMonth = days->count(); + int wholeMonths = endYearMonth - data.yearMonth(); + countGone += (wholeMonths / rFreq) * daysPerMonth; + if (countGone >= countMax) + return countMax; + if (wholeMonths % rFreq) + return countGone; // end year isn't a recurrence year + data.year = endYear; + data.month = endMonth; + } + + // Check the last month in the recurrence + for (it = days->begin(); it != days->end(); ++it) { + if (*it > endDay) + return countGone; + if (++countGone >= countMax) + return countMax; + } + return countGone; +} + +int Recurrence::monthlyCalcNextAfter(QDate &enddate, MonthlyData &data) const +{ + uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; + int countGone = 0; + int endYear = enddate.year(); + int endDay = enddate.day(); + int endYearMonth = endYear*12 + enddate.month() - 1; + QValueList<int>::ConstIterator it; + const QValueList<int>* days = data.dayList(); + + if (data.day > 1) { + // Check what remains of the start month + for (it = days->begin(); it != days->end(); ++it) { + if (*it >= data.day) { + ++countGone; + if (data.yearMonth() == endYearMonth && *it > endDay) { + data.day = *it; + goto ex; + } + if (--countTogo == 0) + return 0; + } + } + data.day = 1; + data.addMonths(rFreq); + } + + if (data.varies) { + // The number of recurrence days varies from month to month, + // so we need to check month by month. + while (data.yearMonth() <= endYearMonth) { + days = data.dayList(); + uint n = days->count(); // number of recurrence days in this month + if (data.yearMonth() == endYearMonth && days->last() > endDay) + break; + if (n >= countTogo) + return 0; + countGone += n; + countTogo -= n; + data.addMonths(rFreq); + } + days = data.dayList(); + } else { + // The number of recurrences is the same every month, + // so skip the month-by-month check. + // Skip the remaining whole months to at least end year/month. + int daysPerMonth = days->count(); + int elapsed = endYearMonth - data.yearMonth(); + int recurMonths = (elapsed + rFreq - 1) / rFreq; + if (elapsed % rFreq == 0 && days->last() <= endDay) + ++recurMonths; // required month is after endYearMonth + if (recurMonths) { + int n = recurMonths * daysPerMonth; + if (static_cast<uint>(n) > countTogo) + return 0; // reached end of recurrence + countTogo -= n; + countGone += n; + data.addMonths(recurMonths * rFreq); + } + } + + // Check the last month in the recurrence + for (it = days->begin(); it != days->end(); ++it) { + ++countGone; + if (data.yearMonth() > endYearMonth || *it > endDay) { + data.day = *it; + break; + } + if (--countTogo == 0) + return 0; + } +ex: + enddate = data.date(); + return countGone; +} + + +/* Find count and, depending on 'func', the end date of an annual recurrence by date. + * Reply = total number of occurrences up to 'enddate', or 0 if error. + * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the + * recurrence end date. + */ +struct Recurrence::YearlyMonthData { + const Recurrence *recurrence; + int year; // current year + int month; // current month 1..12 + int day; // current day of month 1..31 + bool leapyear; // true if February 29th recurs and current year is a leap year + bool feb29; // true if February 29th recurs + private: + QValueList<int> months; // recurring months in non-leap years 1..12 + QValueList<int> leapMonths; // recurring months in leap years 1..12 + public: + YearlyMonthData(const Recurrence* r, const QDate &date) + : recurrence(r), year(date.year()), month(date.month()), day(date.day()) + { feb29 = recurrence->getYearlyMonthMonths(day, months, leapMonths); + leapyear = feb29 && QDate::leapYear(year); + } + const QValueList<int>* monthList() const + { return leapyear ? &leapMonths : &months; } + const QValueList<int>* leapMonthList() const { return &leapMonths; } + QDate date() const { return QDate(year, month, day); } +}; + +int Recurrence::yearlyMonthCalc(PeriodFunc func, QDate &enddate) const +{ + if (rYearNums.isEmpty()) + return 0; + YearlyMonthData data(this, mRecurStart.date()); + switch (func) { + case END_DATE_AND_COUNT: + return yearlyMonthCalcEndDate(enddate, data); + case COUNT_TO_DATE: + return yearlyMonthCalcToDate(enddate, data); + case NEXT_AFTER_DATE: + return yearlyMonthCalcNextAfter(enddate, data); + } + return 0; +} + +// Find total count and end date of an annual recurrence by date. +// Reply = total number of occurrences. +int Recurrence::yearlyMonthCalcEndDate(QDate &enddate, YearlyMonthData &data) const +{ + uint countTogo = rDuration + mRecurExDatesCount; + int countGone = 0; + QValueList<int>::ConstIterator it; + const QValueList<int>* mons = data.monthList(); // get recurring months for this year + + if (data.month > 1) { + // Check what remains of the start year + for (it = mons->begin(); it != mons->end(); ++it) { + if (*it >= data.month) { + ++countGone; + if (--countTogo == 0) { + data.month = *it; + if (data.month == 2 && data.feb29 && !data.leapyear) { + // The recurrence should end on February 29th, but it's a non-leap year + switch (mFeb29YearlyType) { + case rFeb28: + data.day = 28; + break; + case rMar1: + data.month = 3; + data.day = 1; + break; + case rFeb29: + break; + } + } + break; + } + } + } + if (countTogo) { + data.month = 1; + data.year += rFreq; + } + } + if (countTogo) { + if (data.feb29 && mFeb29YearlyType == rFeb29) { + // The number of recurrences is different on leap years, + // so check year-by-year. + for ( ; ; ) { + mons = data.monthList(); + uint n = mons->count(); + if (n >= countTogo) + break; + countTogo -= n; + countGone += n; + data.year += rFreq; + } + } else { + // The number of recurrences is the same every year, + // so skip the year-by-year check. + // Skip the remaining whole years, but leave at least + // 1 recurrence remaining, in order to get its date. + int monthsPerYear = mons->count(); + int wholeYears = (countTogo - 1) / monthsPerYear; + data.year += wholeYears * rFreq; + countGone += wholeYears * monthsPerYear; + countTogo -= wholeYears * monthsPerYear; + } + if (countTogo) { + // Check the last year in the recurrence + for (it = mons->begin(); it != mons->end(); ++it) { + ++countGone; + if (--countTogo == 0) { + data.month = *it; + if (data.month == 2 && data.feb29 && !QDate::leapYear(data.year)) { + // The recurrence should end on February 29th, but it's a non-leap year + switch (mFeb29YearlyType) { + case rFeb28: + data.day = 28; + break; + case rMar1: + data.month = 3; + data.day = 1; + break; + case rFeb29: + break; + } + } + break; + } + } + } + } + enddate = data.date(); + return countGone; +} + +// Find count of an annual recurrence by date. +// Reply = total number of occurrences up to 'enddate'. +int Recurrence::yearlyMonthCalcToDate(const QDate &enddate, YearlyMonthData &data) const +{ + int countGone = 0; + int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; + int endYear = enddate.year(); + int endMonth = enddate.month(); + int endDay = enddate.day(); + if (endDay < data.day) { + /* The end day of the month is earlier than the recurrence day of the month. + * If Feb 29th recurs and: + * 1) it recurs on Feb 28th in non-leap years, don't adjust the end month + * if enddate is Feb 28th on a non-leap year. + * 2) it recurs on Mar 1st in non-leap years, allow the end month to be + * adjusted to February, to simplify calculations. + */ + if (data.feb29 && !QDate::leapYear(endYear) + && mFeb29YearlyType == rFeb28 && endDay == 28 && endMonth == 2) { + } + else if (--endMonth == 0) { + endMonth = 12; + --endYear; + } + } + QValueList<int>::ConstIterator it; + const QValueList<int>* mons = data.monthList(); + + if (data.month > 1) { + // Check what remains of the start year + for (it = mons->begin(); it != mons->end(); ++it) { + if (*it >= data.month) { + if (data.year == endYear && *it > endMonth) + return countGone; + if (++countGone >= countMax) + return countMax; + } + } + data.month = 1; + data.year += rFreq; + } + if (data.feb29 && mFeb29YearlyType == rFeb29) { + // The number of recurrences is different on leap years, + // so check year-by-year. + while (data.year < endYear) { + countGone += data.monthList()->count(); + if (countGone >= countMax) + return countMax; + data.year += rFreq; + } + mons = data.monthList(); + } else { + // The number of recurrences is the same every year, + // so skip the year-by-year check. + // Skip the remaining whole years. + int monthsPerYear = mons->count(); + int wholeYears = endYear - data.year; + countGone += (wholeYears / rFreq) * monthsPerYear; + if (countGone >= countMax) + return countMax; + if (wholeYears % rFreq) + return countGone; // end year isn't a recurrence year + data.year = endYear; + } + + // Check the last year in the recurrence + for (it = mons->begin(); it != mons->end(); ++it) { + if (*it > endMonth) + return countGone; + if (++countGone >= countMax) + return countMax; + } + return countGone; +} + +// Find count and date of first recurrence after 'enddate' of an annual recurrence by date. +// Reply = total number of occurrences up to 'enddate'. +int Recurrence::yearlyMonthCalcNextAfter(QDate &enddate, YearlyMonthData &data) const +{ + uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; + int countGone = 0; + int endYear = enddate.year(); + int endMonth = enddate.month(); + int endDay = enddate.day(); + bool mar1TooEarly = false; + bool feb28ok = false; + if (endDay < data.day) { + if (data.feb29 && mFeb29YearlyType == rMar1 && endMonth == 3) + mar1TooEarly = true; + if (data.feb29 && mFeb29YearlyType == rFeb28 && endMonth == 2 && endDay == 28) + feb28ok = true; + else if (--endMonth == 0) { + endMonth = 12; + --endYear; + } + } + QValueList<int>::ConstIterator it; + const QValueList<int>* mons = data.monthList(); + + if (data.month > 1) { + // Check what remains of the start year + for (it = mons->begin(); it != mons->end(); ++it) { + if (*it >= data.month) { + ++countGone; + if (data.year == endYear + && ( *it > endMonth && (*it > 3 || !mar1TooEarly) + || *it == 2 && feb28ok && data.leapyear)) { + if (*it == 2 && data.feb29 && !data.leapyear) { + // The next recurrence should be on February 29th, but it's a non-leap year + switch (mFeb29YearlyType) { + case rFeb28: + data.month = 2; + data.day = 28; + break; + case rMar1: + data.month = 3; + data.day = 1; + break; + case rFeb29: // impossible in this context! + break; + } + } + else + data.month = *it; + goto ex; + } + if (--countTogo == 0) + return 0; + } + } + data.month = 1; + data.year += rFreq; + } + + if (data.feb29 && mFeb29YearlyType == rFeb29) { + // The number of recurrences is different on leap years, + // so check year-by-year. + while (data.year <= endYear) { + mons = data.monthList(); + if (data.year == endYear && mons->last() > endMonth) + break; + uint n = mons->count(); + if (n >= countTogo) + break; + countTogo -= n; + countGone += n; + data.year += rFreq; + } + mons = data.monthList(); + } else { + // The number of recurrences is the same every year, + // so skip the year-by-year check. + // Skip the remaining whole years to at least endYear. + int monthsPerYear = mons->count(); + int recurYears = (endYear - data.year + rFreq - 1) / rFreq; + if ((endYear - data.year)%rFreq == 0 + && mons->last() <= endMonth) + ++recurYears; // required year is after endYear + if (recurYears) { + int n = recurYears * monthsPerYear; + if (static_cast<uint>(n) > countTogo) + return 0; // reached end of recurrence + countTogo -= n; + countGone += n; + data.year += recurYears * rFreq; + } + } + + // Check the last year in the recurrence + for (it = mons->begin(); it != mons->end(); ++it) { + ++countGone; + if (data.year > endYear + || ( *it > endMonth && (*it > 3 || !mar1TooEarly) + || *it == 2 && feb28ok && QDate::leapYear(data.year))) { + if (*it == 2 && data.feb29 && !QDate::leapYear(data.year)) { + // The next recurrence should be on February 29th, but it's a non-leap year + switch (mFeb29YearlyType) { + case rFeb28: + data.month = 2; + data.day = 28; + break; + case rMar1: + data.month = 3; + data.day = 1; + break; + case rFeb29: // impossible in this context! + break; + } + } + else + data.month = *it; + break; + } + if (--countTogo == 0) + return 0; + } +ex: + enddate = data.date(); + return countGone; +} + + +/* Find count and, depending on 'func', the end date of an annual recurrence by date. + * Reply = total number of occurrences up to 'enddate', or 0 if error. + * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the + * recurrence end date. + */ +struct Recurrence::YearlyPosData { + const Recurrence *recurrence; + int year; // current year + int month; // current month 1..12 + int day; // current day of month 1..31 + int daysPerMonth; // number of days which recur each month, or -1 if variable + int count; // number of days which recur each year, or -1 if variable + bool varies; // true if number of days varies from year to year + private: + mutable QValueList<int> days; + public: + YearlyPosData(const Recurrence* r, const QDate &date) + : recurrence(r), year(date.year()), month(date.month()), day(date.day()), count(-1) + { if ((daysPerMonth = r->countMonthlyPosDays()) > 0) + count = daysPerMonth * r->rYearNums.count(); + varies = (daysPerMonth < 0); + } + const QValueList<int>* dayList() const { + QDate startOfMonth(year, month, 1); + recurrence->getMonthlyPosDays(days, startOfMonth.daysInMonth(), startOfMonth.dayOfWeek()); + return &days; + } + int yearMonth() const { return year*12 + month - 1; } + void addMonths(int diff) { month += diff - 1; year += month / 12; month = month % 12 + 1; } + QDate date() const { return QDate(year, month, day); } +}; + +int Recurrence::yearlyPosCalc(PeriodFunc func, QDate &enddate) const +{ + if (rYearNums.isEmpty() || rMonthPositions.isEmpty()) + return 0; + YearlyPosData data(this, mRecurStart.date()); + switch (func) { + case END_DATE_AND_COUNT: + return yearlyPosCalcEndDate(enddate, data); + case COUNT_TO_DATE: + return yearlyPosCalcToDate(enddate, data); + case NEXT_AFTER_DATE: + return yearlyPosCalcNextAfter(enddate, data); + } + return 0; +} + +int Recurrence::yearlyPosCalcEndDate(QDate &enddate, YearlyPosData &data) const +{ + uint countTogo = rDuration + mRecurExDatesCount; + int countGone = 0; + QValueList<int>::ConstIterator id; + const QValueList<int>* days; + + if (data.month > 1 || data.day > 1) { + // Check what remains of the start year + for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { + if (*im.current() >= data.month) { + // Check what remains of the start month + if (data.day > 1 || data.varies + || static_cast<uint>(data.daysPerMonth) >= countTogo) { + data.month = *im.current(); + days = data.dayList(); + for (id = days->begin(); id != days->end(); ++id) { + if (*id >= data.day) { + ++countGone; + if (--countTogo == 0) { + data.month = *im.current(); + data.day = *id; + goto ex; + } + } + } + data.day = 1; + } else { + // The number of days per month is constant, so skip + // the whole month. + countTogo -= data.daysPerMonth; + countGone += data.daysPerMonth; + } + } + } + data.month = 1; + data.year += rFreq; + } + + if (data.varies) { + // The number of recurrences varies from year to year. + for ( ; ; ) { + for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { + data.month = *im.current(); + days = data.dayList(); + int n = days->count(); + if (static_cast<uint>(n) >= countTogo) { + // Check the last month in the recurrence + for (id = days->begin(); id != days->end(); ++id) { + ++countGone; + if (--countTogo == 0) { + data.day = *id; + goto ex; + } + } + } + countTogo -= n; + countGone += n; + } + data.year += rFreq; + } + } else { + // The number of recurrences is the same every year, + // so skip the year-by-year check. + // Skip the remaining whole years, but leave at least + // 1 recurrence remaining, in order to get its date. + int wholeYears = (countTogo - 1) / data.count; + data.year += wholeYears * rFreq; + countGone += wholeYears * data.count; + countTogo -= wholeYears * data.count; + + // Check the last year in the recurrence. + for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { + if (static_cast<uint>(data.daysPerMonth) >= countTogo) { + // Check the last month in the recurrence + data.month = *im.current(); + days = data.dayList(); + for (id = days->begin(); id != days->end(); ++id) { + ++countGone; + if (--countTogo == 0) { + data.day = *id; + goto ex; + } + } + } + countTogo -= data.daysPerMonth; + countGone += data.daysPerMonth; + } + data.year += rFreq; + } +ex: + enddate = data.date(); + return countGone; +} + +int Recurrence::yearlyPosCalcToDate(const QDate &enddate, YearlyPosData &data) const +{ + int countGone = 0; + int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; + int endYear = enddate.year(); + int endMonth = enddate.month(); + int endDay = enddate.day(); + if (endDay < data.day && --endMonth == 0) { + endMonth = 12; + --endYear; + } + int endYearMonth = endYear*12 + endMonth; + QValueList<int>::ConstIterator id; + const QValueList<int>* days; + + if (data.month > 1 || data.day > 1) { + // Check what remains of the start year + for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { + if (*im.current() >= data.month) { + data.month = *im.current(); + if (data.yearMonth() > endYearMonth) + return countGone; + // Check what remains of the start month + bool lastMonth = (data.yearMonth() == endYearMonth); + if (lastMonth || data.day > 1 || data.varies) { + days = data.dayList(); + if (lastMonth || data.day > 1) { + for (id = days->begin(); id != days->end(); ++id) { + if (*id >= data.day) { + if (lastMonth && *id > endDay) + return countGone; + if (++countGone >= countMax) + return countMax; + } + } + } else { + countGone += days->count(); + if (countGone >= countMax) + return countMax; + } + data.day = 1; + } else { + // The number of days per month is constant, so skip + // the whole month. + countGone += data.daysPerMonth; + if (countGone >= countMax) + return countMax; + } + } + } + data.month = 1; + data.year += rFreq; + } + + if (data.varies) { + // The number of recurrences varies from year to year. + for ( ; ; ) { + for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { + data.month = *im.current(); + days = data.dayList(); + if (data.yearMonth() >= endYearMonth) { + if (data.yearMonth() > endYearMonth) + return countGone; + // Check the last month in the recurrence + for (id = days->begin(); id != days->end(); ++id) { + if (*id > endDay) + return countGone; + if (++countGone >= countMax) + return countMax; + } + } else { + countGone += days->count(); + if (countGone >= countMax) + return countMax; + } + } + data.year += rFreq; + } + } else { + // The number of recurrences is the same every year, + // so skip the year-by-year check. + // Skip the remaining whole years, but leave at least + // 1 recurrence remaining, in order to get its date. + int wholeYears = endYear - data.year; + countGone += (wholeYears / rFreq) * data.count; + if (countGone >= countMax) + return countMax; + if (wholeYears % rFreq) + return countGone; // end year isn't a recurrence year + data.year = endYear; + + // Check the last year in the recurrence. + for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { + data.month = *im.current(); + if (data.month >= endMonth) { + if (data.month > endMonth) + return countGone; + // Check the last month in the recurrence + days = data.dayList(); + for (id = days->begin(); id != days->end(); ++id) { + if (*id > endDay) + return countGone; + if (++countGone >= countMax) + return countMax; + } + } else { + countGone += data.daysPerMonth; + if (countGone >= countMax) + return countMax; + } + } + } + return countGone; +} + +int Recurrence::yearlyPosCalcNextAfter(QDate &enddate, YearlyPosData &data) const +{ + uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; + int countGone = 0; + int endYear = enddate.year(); + int endMonth = enddate.month(); + int endDay = enddate.day(); + if (endDay < data.day && --endMonth == 0) { + endMonth = 12; + --endYear; + } + int endYearMonth = endYear*12 + endMonth; + QValueList<int>::ConstIterator id; + const QValueList<int>* days; + + if (data.varies) { + // The number of recurrences varies from year to year. + for ( ; ; ) { + // Check the next year + for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { + if (*im.current() >= data.month) { + // Check the next month + data.month = *im.current(); + int ended = data.yearMonth() - endYearMonth; + days = data.dayList(); + if (ended >= 0 || data.day > 1) { + // This is the start or end month, so check each day + for (id = days->begin(); id != days->end(); ++id) { + if (*id >= data.day) { + ++countGone; + if (ended > 0 || (ended == 0 && *id > endDay)) { + data.day = *id; + goto ex; + } + if (--countTogo == 0) + return 0; + } + } + } else { + // Skip the whole month + uint n = days->count(); + if (n >= countTogo) + return 0; + countGone += n; + } + data.day = 1; // we've checked the start month now + } + } + data.month = 1; // we've checked the start year now + data.year += rFreq; + } + } else { + // The number of recurrences is the same every year. + if (data.month > 1 || data.day > 1) { + // Check what remains of the start year + for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { + if (*im.current() >= data.month) { + // Check what remains of the start month + data.month = *im.current(); + int ended = data.yearMonth() - endYearMonth; + if (ended >= 0 || data.day > 1) { + // This is the start or end month, so check each day + days = data.dayList(); + for (id = days->begin(); id != days->end(); ++id) { + if (*id >= data.day) { + ++countGone; + if (ended > 0 || (ended == 0 && *id > endDay)) { + data.day = *id; + goto ex; + } + if (--countTogo == 0) + return 0; + } + } + data.day = 1; // we've checked the start month now + } else { + // Skip the whole month. + if (static_cast<uint>(data.daysPerMonth) >= countTogo) + return 0; + countGone += data.daysPerMonth; + } + } + } + data.year += rFreq; + } + // Skip the remaining whole years to at least endYear. + int recurYears = (endYear - data.year + rFreq - 1) / rFreq; + if ((endYear - data.year)%rFreq == 0 + && *rYearNums.getLast() <= endMonth) + ++recurYears; // required year is after endYear + if (recurYears) { + int n = recurYears * data.count; + if (static_cast<uint>(n) > countTogo) + return 0; // reached end of recurrence + countTogo -= n; + countGone += n; + data.year += recurYears * rFreq; + } + + // Check the last year in the recurrence + for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { + data.month = *im.current(); + int ended = data.yearMonth() - endYearMonth; + if (ended >= 0) { + // This is the end month, so check each day + days = data.dayList(); + for (id = days->begin(); id != days->end(); ++id) { + ++countGone; + if (ended > 0 || (ended == 0 && *id > endDay)) { + data.day = *id; + goto ex; + } + if (--countTogo == 0) + return 0; + } + } else { + // Skip the whole month. + if (static_cast<uint>(data.daysPerMonth) >= countTogo) + return 0; + countGone += data.daysPerMonth; + } + } + } +ex: + enddate = data.date(); + return countGone; +} + + +/* Find count and, depending on 'func', the end date of an annual recurrence by day. + * Reply = total number of occurrences up to 'enddate', or 0 if error. + * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the + * recurrence end date. + */ +struct Recurrence::YearlyDayData { + int year; // current year + int day; // current day of year 1..366 + bool varies; // true if day 366 recurs + private: + int daycount; + public: + YearlyDayData(const Recurrence* r, const QDate &date) + : year(date.year()), day(date.dayOfYear()), varies(*r->rYearNums.getLast() == 366), + daycount(r->rYearNums.count()) { } + bool leapYear() const { return QDate::leapYear(year); } + int dayCount() const { return daycount - (varies && !QDate::leapYear(year) ? 1 : 0); } + bool isMaxDayCount() const { return !varies || QDate::leapYear(year); } + QDate date() const { return QDate(year, 1, 1).addDays(day - 1); } +}; + +int Recurrence::yearlyDayCalc(PeriodFunc func, QDate &enddate) const +{ + if (rYearNums.isEmpty()) + return 0; + YearlyDayData data(this, mRecurStart.date()); + switch (func) { + case END_DATE_AND_COUNT: + return yearlyDayCalcEndDate(enddate, data); + case COUNT_TO_DATE: + return yearlyDayCalcToDate(enddate, data); + case NEXT_AFTER_DATE: + return yearlyDayCalcNextAfter(enddate, data); + } + return 0; +} + +int Recurrence::yearlyDayCalcEndDate(QDate &enddate, YearlyDayData &data) const +{ + uint countTogo = rDuration + mRecurExDatesCount; + int countGone = 0; + + if (data.day > 1) { + // Check what remains of the start year + bool leapOK = data.isMaxDayCount(); + for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { + int d = *it.current(); + if (d >= data.day && (leapOK || d < 366)) { + ++countGone; + if (--countTogo == 0) { + data.day = d; + goto ex; + } + } + } + data.day = 1; + data.year += rFreq; + } + + if (data.varies) { + // The number of recurrences is different in leap years, + // so check year-by-year. + for ( ; ; ) { + uint n = data.dayCount(); + if (n >= countTogo) + break; + countTogo -= n; + countGone += n; + data.year += rFreq; + } + } else { + // The number of recurrences is the same every year, + // so skip the year-by-year check. + // Skip the remaining whole years, but leave at least + // 1 recurrence remaining, in order to get its date. + int daysPerYear = rYearNums.count(); + int wholeYears = (countTogo - 1) / daysPerYear; + data.year += wholeYears * rFreq; + countGone += wholeYears * daysPerYear; + countTogo -= wholeYears * daysPerYear; + } + if (countTogo) { + // Check the last year in the recurrence + for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { + ++countGone; + if (--countTogo == 0) { + data.day = *it.current(); + break; + } + } + } +ex: + enddate = data.date(); + return countGone; +} + +int Recurrence::yearlyDayCalcToDate(const QDate &enddate, YearlyDayData &data) const +{ + int countGone = 0; + int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; + int endYear = enddate.year(); + int endDay = enddate.dayOfYear(); + + if (data.day > 1) { + // Check what remains of the start year + bool leapOK = data.isMaxDayCount(); + for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { + int d = *it.current(); + if (d >= data.day && (leapOK || d < 366)) { + if (data.year == endYear && d > endDay) + return countGone; + if (++countGone >= countMax) + return countMax; + } + } + data.day = 1; + data.year += rFreq; + } + + if (data.varies) { + // The number of recurrences is different in leap years, + // so check year-by-year. + while (data.year < endYear) { + uint n = data.dayCount(); + countGone += n; + if (countGone >= countMax) + return countMax; + data.year += rFreq; + } + if (data.year > endYear) + return countGone; + } else { + // The number of recurrences is the same every year. + // Skip the remaining whole years. + int wholeYears = endYear - data.year; + countGone += (wholeYears / rFreq) * rYearNums.count(); + if (countGone >= countMax) + return countMax; + if (wholeYears % rFreq) + return countGone; // end year isn't a recurrence year + data.year = endYear; + } + + if (data.year <= endYear) { + // Check the last year in the recurrence + for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { + if (*it.current() > endDay) + return countGone; + if (++countGone >= countMax) + return countMax; + } + } + return countGone; +} + +int Recurrence::yearlyDayCalcNextAfter(QDate &enddate, YearlyDayData &data) const +{ + uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; + int countGone = 0; + int endYear = enddate.year(); + int endDay = enddate.dayOfYear(); + + if (data.day > 1) { + // Check what remains of the start year + bool leapOK = data.isMaxDayCount(); + for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { + int d = *it.current(); + if (d >= data.day && (leapOK || d < 366)) { + ++countGone; + if (data.year == endYear && d > endDay) { + data.day = d; + goto ex; + } + if (--countTogo == 0) + return 0; + } + } + data.day = 1; + data.year += rFreq; + } + + if (data.varies) { + // The number of recurrences is different in leap years, + // so check year-by-year. + while (data.year <= endYear) { + uint n = data.dayCount(); + if (data.year == endYear && *rYearNums.getLast() > endDay) + break; + if (n >= countTogo) + break; + countTogo -= n; + countGone += n; + data.year += rFreq; + } + } else { + // The number of recurrences is the same every year, + // so skip the year-by-year check. + // Skip the remaining whole years to at least endYear. + int daysPerYear = rYearNums.count(); + int recurYears = (endYear - data.year + rFreq - 1) / rFreq; + if ((endYear - data.year)%rFreq == 0 + && *rYearNums.getLast() <= endDay) + ++recurYears; // required year is after endYear + if (recurYears) { + int n = recurYears * daysPerYear; + if (static_cast<uint>(n) > countTogo) + return 0; // reached end of recurrence + countTogo -= n; + countGone += n; + data.year += recurYears * rFreq; + } + } + + // Check the last year in the recurrence + for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { + ++countGone; + int d = *it.current(); + if (data.year > endYear || d > endDay) { + data.day = d; + break; + } + if (--countTogo == 0) + return 0; + } +ex: + enddate = data.date(); + return countGone; +} + +// Get the days in this month which recur, in numerical order. +// Parameters: daysInMonth = number of days in this month +// startDayOfWeek = day of week for first day of month. +void Recurrence::getMonthlyPosDays(QValueList<int> &list, int daysInMonth, int startDayOfWeek) const +{ + list.clear(); + int endDayOfWeek = (startDayOfWeek + daysInMonth - 2) % 7 + 1; + // Go through the list, compiling a bit list of actual day numbers + Q_UINT32 days = 0; + for (QPtrListIterator<rMonthPos> pos(rMonthPositions); pos.current(); ++pos) { + int weeknum = pos.current()->rPos - 1; // get 0-based week number + QBitArray &rdays = pos.current()->rDays; + if (pos.current()->negative) { + // nth days before the end of the month + for (uint i = 1; i <= 7; ++i) { + if (rdays.testBit(i - 1)) { + int day = daysInMonth - weeknum*7 - (endDayOfWeek - i + 7) % 7; + if (day > 0) + days |= 1 << (day - 1); + } + } + } else { + // nth days after the start of the month + for (uint i = 1; i <= 7; ++i) { + if (rdays.testBit(i - 1)) { + int day = 1 + weeknum*7 + (i - startDayOfWeek + 7) % 7; + if (day <= daysInMonth) + days |= 1 << (day - 1); + } + } + } + } + // Compile the ordered list + Q_UINT32 mask = 1; + for (int i = 0; i < daysInMonth; mask <<= 1, ++i) { + if (days & mask) + list.append(i + 1); + } +} + +// Get the number of days in the month which recur. +// Reply = -1 if the number varies from month to month. +int Recurrence::countMonthlyPosDays() const +{ + int count = 0; + Q_UINT8 positive[5] = { 0, 0, 0, 0, 0 }; + Q_UINT8 negative[4] = { 0, 0, 0, 0 }; + for (QPtrListIterator<rMonthPos> pos(rMonthPositions); pos.current(); ++pos) { + int weeknum = pos.current()->rPos; + Q_UINT8* wk; + if (pos.current()->negative) { + // nth days before the end of the month + if (weeknum > 4) + return -1; // days in 5th week are often missing + wk = &negative[4 - weeknum]; + } else { + // nth days after the start of the month + if (weeknum > 4) + return -1; // days in 5th week are often missing + wk = &positive[weeknum - 1]; + } + QBitArray &rdays = pos.current()->rDays; + for (uint i = 0; i < 7; ++i) { + if (rdays.testBit(i)) { + ++count; + *wk |= (1 << i); + } + } + } + // Check for any possible days which could be duplicated by + // a positive and a negative position. + for (int i = 0; i < 4; ++i) { + if (negative[i] & (positive[i] | positive[i+1])) + return -1; + } + return count; +} + +// Get the days in this month which recur, in numerical order. +// Reply = true if day numbers varies from month to month. +bool Recurrence::getMonthlyDayDays(QValueList<int> &list, int daysInMonth) const +{ + list.clear(); + bool variable = false; + Q_UINT32 days = 0; + for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) { + int day = *it.current(); + if (day > 0) { + // date in the month + if (day <= daysInMonth) + days |= 1 << (day - 1); + if (day > 28 && day <= 31) + variable = true; // this date does not appear in some months + } else if (day < 0) { + // days before the end of the month + variable = true; // this date varies depending on the month length + day = daysInMonth + day; // zero-based day of month + if (day >= 0) + days |= 1 << day; + } + } + // Compile the ordered list + Q_UINT32 mask = 1; + for (int i = 0; i < daysInMonth; mask <<= 1, ++i) { + if (days & mask) + list.append(i + 1); + } + return variable; +} + +// Get the months which recur, in numerical order, for both leap years and non-leap years. +// N.B. If February 29th recurs on March 1st in non-leap years, February (not March) is +// included in the non-leap year month list. +// Reply = true if February 29th also recurs. +bool Recurrence::getYearlyMonthMonths(int day, QValueList<int> &list, QValueList<int> &leaplist) const +{ + list.clear(); + leaplist.clear(); + bool feb29 = false; + for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { + int month = *it.current(); + if (month == 2) { + if (day <= 28) { + list.append(month); // date appears in February + leaplist.append(month); + } + else if (day == 29) { + // February 29th + leaplist.append(month); + switch (mFeb29YearlyType) { + case rFeb28: + case rMar1: + list.append(2); + break; + case rFeb29: + break; + } + feb29 = true; + } + } + else if (day <= 30 || QDate(2000, month, 1).daysInMonth() == 31) { + list.append(month); // date appears in every month + leaplist.append(month); + } + } + return feb29; +} + +/* From the recurrence day of the week list, get the earliest day in the + * specified week which is >= the startDay. + * Parameters: startDay = 1..7 (Monday..Sunday) + * useWeekStart = true to end search at day before next rWeekStart + * = false to search for a full 7 days + * Reply = day of the week (1..7), or 0 if none found. + */ +int Recurrence::getFirstDayInWeek(int startDay, bool useWeekStart) const +{ + int last = ((useWeekStart ? rWeekStart : startDay) + 5)%7; + for (int i = startDay - 1; ; i = (i + 1)%7) { + if (rDays.testBit(i)) + return i + 1; + if (i == last) + return 0; + } +} + +/* From the recurrence day of the week list, get the latest day in the + * specified week which is <= the endDay. + * Parameters: endDay = 1..7 (Monday..Sunday) + * useWeekStart = true to end search at rWeekStart + * = false to search for a full 7 days + * Reply = day of the week (1..7), or 0 if none found. + */ +int Recurrence::getLastDayInWeek(int endDay, bool useWeekStart) const +{ + int last = useWeekStart ? rWeekStart - 1 : endDay%7; + for (int i = endDay - 1; ; i = (i + 6)%7) { + if (rDays.testBit(i)) + return i + 1; + if (i == last) + return 0; + } +} + +/* From the recurrence monthly day number list or monthly day of week/week of + * month list, get the earliest day in the specified month which is >= the + * earliestDate. + */ +QDate Recurrence::getFirstDateInMonth(const QDate &earliestDate) const +{ + int earliestDay = earliestDate.day(); + int daysInMonth = earliestDate.daysInMonth(); + switch (recurs) { + case rMonthlyDay: { + int minday = daysInMonth + 1; + for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) { + int day = *it.current(); + if (day < 0) + day = daysInMonth + day + 1; + if (day >= earliestDay && day < minday) + minday = day; + } + if (minday <= daysInMonth) + return earliestDate.addDays(minday - earliestDay); + break; + } + case rMonthlyPos: + case rYearlyPos: { + QDate monthBegin(earliestDate.addDays(1 - earliestDay)); + QValueList<int> dayList; + getMonthlyPosDays(dayList, daysInMonth, monthBegin.dayOfWeek()); + for (QValueList<int>::ConstIterator id = dayList.begin(); id != dayList.end(); ++id) { + if (*id >= earliestDay) + return monthBegin.addDays(*id - 1); + } + break; + } + } + return QDate(); +} + +/* From the recurrence monthly day number list or monthly day of week/week of + * month list, get the latest day in the specified month which is <= the + * latestDate. + */ +QDate Recurrence::getLastDateInMonth(const QDate &latestDate) const +{ + int latestDay = latestDate.day(); + int daysInMonth = latestDate.daysInMonth(); + switch (recurs) { + case rMonthlyDay: { + int maxday = -1; + for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) { + int day = *it.current(); + if (day < 0) + day = daysInMonth + day + 1; + if (day <= latestDay && day > maxday) + maxday = day; + } + if (maxday > 0) + return QDate(latestDate.year(), latestDate.month(), maxday); + break; + } + case rMonthlyPos: + case rYearlyPos: { + QDate monthBegin(latestDate.addDays(1 - latestDay)); + QValueList<int> dayList; + getMonthlyPosDays(dayList, daysInMonth, monthBegin.dayOfWeek()); + for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) { + if (*id <= latestDay) + return monthBegin.addDays(*id - 1); + } + break; + } + } + return QDate(); +} + +/* From the recurrence yearly month list or yearly day list, get the earliest + * month or day in the specified year which is >= the earliestDate. + * Note that rYearNums is sorted in numerical order. + */ +QDate Recurrence::getFirstDateInYear(const QDate &earliestDate) const +{ + QPtrListIterator<int> it(rYearNums); + switch (recurs) { + case rYearlyMonth: { + int day = recurStart().date().day(); + int earliestYear = earliestDate.year(); + int earliestMonth = earliestDate.month(); + int earliestDay = earliestDate.day(); + if (earliestDay > day) { + // The earliest date is later in the month than the recurrence date, + // so skip to the next month before starting to check + if (++earliestMonth > 12) + return QDate(); + } + for ( ; it.current(); ++it) { + int month = *it.current(); + if (month >= earliestMonth) { + if (day <= 28 || QDate::isValid(earliestYear, month, day)) + return QDate(earliestYear, month, day); + if (day == 29 && month == 2) { + // It's a recurrence on February 29th, in a non-leap year + switch (mFeb29YearlyType) { + case rMar1: + return QDate(earliestYear, 3, 1); + case rFeb28: + if (earliestDay <= 28) + return QDate(earliestYear, 2, 28); + break; + case rFeb29: + break; + } + } + } + } + break; + } + case rYearlyPos: { + QValueList<int> dayList; + int earliestYear = earliestDate.year(); + int earliestMonth = earliestDate.month(); + int earliestDay = earliestDate.day(); + for ( ; it.current(); ++it) { + int month = *it.current(); + if (month >= earliestMonth) { + QDate monthBegin(earliestYear, month, 1); + getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek()); + for (QValueList<int>::ConstIterator id = dayList.begin(); id != dayList.end(); ++id) { + if (*id >= earliestDay) + return monthBegin.addDays(*id - 1); + } + earliestDay = 1; + } + } + break; + } + case rYearlyDay: { + int earliestDay = earliestDate.dayOfYear(); + for ( ; it.current(); ++it) { + int day = *it.current(); + if (day >= earliestDay && (day <= 365 || day <= earliestDate.daysInYear())) + return earliestDate.addDays(day - earliestDay); + } + break; + } + } + return QDate(); +} + +/* From the recurrence yearly month list or yearly day list, get the latest + * month or day in the specified year which is <= the latestDate. + * Note that rYearNums is sorted in numerical order. + */ +QDate Recurrence::getLastDateInYear(const QDate &latestDate) const +{ + QPtrListIterator<int> it(rYearNums); + switch (recurs) { + case rYearlyMonth: { + int day = recurStart().date().day(); + int latestYear = latestDate.year(); + int latestMonth = latestDate.month(); + if (latestDate.day() > day) { + // The latest date is earlier in the month than the recurrence date, + // so skip to the previous month before starting to check + if (--latestMonth <= 0) + return QDate(); + } + for (it.toLast(); it.current(); --it) { + int month = *it.current(); + if (month <= latestMonth) { + if (day <= 28 || QDate::isValid(latestYear, month, day)) + return QDate(latestYear, month, day); + if (day == 29 && month == 2) { + // It's a recurrence on February 29th, in a non-leap year + switch (mFeb29YearlyType) { + case rMar1: + if (latestMonth >= 3) + return QDate(latestYear, 3, 1); + break; + case rFeb28: + return QDate(latestYear, 2, 28); + case rFeb29: + break; + } + } + } + } + break; + } + case rYearlyPos: { + QValueList<int> dayList; + int latestYear = latestDate.year(); + int latestMonth = latestDate.month(); + int latestDay = latestDate.day(); + for (it.toLast(); it.current(); --it) { + int month = *it.current(); + if (month <= latestMonth) { + QDate monthBegin(latestYear, month, 1); + getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek()); + for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) { + if (*id <= latestDay) + return monthBegin.addDays(*id - 1); + } + latestDay = 31; + } + } + break; + } + case rYearlyDay: { + int latestDay = latestDate.dayOfYear(); + for (it.toLast(); it.current(); --it) { + int day = *it.current(); + if (day <= latestDay) + return latestDate.addDays(day - latestDay); + } + break; + } + } + return QDate(); +} + +void Recurrence::dump() const +{ + kdDebug() << "Recurrence::dump():" << endl; + + kdDebug() << " type: " << recurs << endl; + + kdDebug() << " rDays: " << endl; + int i; + for( i = 0; i < 7; ++i ) { + kdDebug() << " " << i << ": " + << ( rDays.testBit( i ) ? "true" : "false" ) << endl; + } +} diff --git a/libkcal/recurrence.h b/libkcal/recurrence.h new file mode 100644 index 0000000..a0f6d84 --- a/dev/null +++ b/libkcal/recurrence.h @@ -0,0 +1,401 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2002 David Jarvie <software@astrojar.org.uk> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KCAL_RECURRENCE_H +#define KCAL_RECURRENCE_H + +#include <qstring.h> +#include <qbitarray.h> +#include <qptrlist.h> + +namespace KCal { + +class Incidence; + +/** + This class represents a recurrence rule for a calendar incidence. +*/ +class Recurrence +{ + public: + /** enumeration for describing how an event recurs, if at all. */ + enum { rNone = 0, rMinutely = 0x001, rHourly = 0x0002, rDaily = 0x0003, + rWeekly = 0x0004, rMonthlyPos = 0x0005, rMonthlyDay = 0x0006, + rYearlyMonth = 0x0007, rYearlyDay = 0x0008, rYearlyPos = 0x0009 }; + + /** Enumeration for specifying what date yearly recurrences of February 29th occur + * in non-leap years. */ + enum Feb29Type { + rMar1, // recur on March 1st (default) + rFeb28, // recur on February 28th + rFeb29 // only recur on February 29th, i.e. don't recur in non-leap years + }; + + /** structure for Recurs rMonthlyPos */ + struct rMonthPos { + QBitArray rDays; + short rPos; + bool negative; + }; + + Recurrence(Incidence *parent, int compatVersion = 0); + Recurrence(const Recurrence&, Incidence *parent); + ~Recurrence(); + + bool operator==( const Recurrence& ) const; + bool operator!=( const Recurrence& r ) const { return !operator==(r); } + + Incidence *parent() { return mParent; } + + /** Return the start of the recurrence */ + QDateTime recurStart() const { return mRecurStart; } + /** Returns the number of exception dates for the recurrence */ + int recurExDatesCount() const { return mRecurExDatesCount; } + /** Set start of recurrence, as a date and time. */ + void setRecurStart(const QDateTime &start); + /** Set start of recurrence, as a date with no time. + * Recurrence types which are sub-daily (e.g. rHourly) always have a time; + * the time is set to 00:00:00 in these cases. */ + void setRecurStart(const QDate &start); + /** Set whether the recurrence has no time, just a date. + * Recurrence types which are sub-daily (e.g. rHourly) always have a time + * and cannot be set to float. + * N.B. This property is derived by default from the parent incidence, + * or according to whether a time is specified in setRecurStart(). */ + void setFloats(bool f); + /** + Returns whether the recurrence has no time, just a date. + */ + bool doesFloat() const { + return mFloats; + } + + /** Set if recurrence is read-only or can be changed. */ + void setRecurReadOnly(bool readOnly) { mRecurReadOnly = readOnly; } + bool recurReadOnly() const + { + return mRecurReadOnly; + } + + + /** Set number of exception dates. */ + void setRecurExDatesCount(int count) { if (count >= 0) mRecurExDatesCount = count; } + /** Set the calendar file version for backwards compatibility. + * @var version is the KOrganizer/libkcal version, e.g. 220 for KDE 2.2.0. + * Specify version = 0 to cancel compatibility mode. + */ + void setCompatVersion(int version = 0); + + /** Returns the event's recurrence status. See the enumeration at the top + * of this file for possible values. */ + ushort doesRecur() const; + /** Returns true if the date specified is one on which the event will + * recur. */ + bool recursOnPure(const QDate &qd) const; + /** Returns true if the date/time specified is one at which the event will + * recur. Times are rounded down to the nearest minute to determine the result. */ + bool recursAtPure(const QDateTime &) const; + /** Turns off recurrence for the event. */ + void unsetRecurs(); + + /** Returns the date of the next recurrence, after the specified date. + * @var preDate the date after which to find the recurrence. + * @var last if non-null, *last is set to true if the next recurrence is the + * last recurrence, else false. + * Reply = date of next recurrence, or invalid date if none. + */ + QDate getNextDate(const QDate& preDate, bool* last = 0) const; + /** Returns the date and time of the next recurrence, after the specified date/time. + * If the recurrence has no time, the next date after the specified date is returned. + * @var preDate the date/time after which to find the recurrence. + * @var last if non-null, *last is set to true if the next recurrence is the + * last recurrence, else false. + * Reply = date/time of next recurrence, or invalid date if none. + */ + QDateTime getNextDateTime(const QDateTime& preDateTime, bool* last = 0) const; + /** Returns the date of the last previous recurrence, before the specified date. + * @var afterDate the date before which to find the recurrence. + * @var last if non-null, *last is set to true if the previous recurrence is the + * last recurrence, else false. + * Reply = date of previous recurrence, or invalid date if none. + */ + QDate getPreviousDate(const QDate& afterDate, bool* last = 0) const; + /** Returns the date and time of the last previous recurrence, before the specified date/time. + * If a time later than 00:00:00 is specified and the recurrence has no time, 00:00:00 on + * the specified date is returned if that date recurs. + * @var afterDate the date/time before which to find the recurrence. + * @var last if non-null, *last is set to true if the previous recurrence is the + * last recurrence, else false. + * Reply = date/time of previous recurrence, or invalid date if none. + */ + QDateTime getPreviousDateTime(const QDateTime& afterDateTime, bool* last = 0) const; + + /** Returns frequency of recurrence, in terms of the recurrence time period type. */ + int frequency() const; + /** Returns the total number of recurrences, including the initial occurrence. */ + int duration() const; + /** Sets the total number of times the event is to occur, including both the + * first and last. */ + void setDuration(int duration); + /** Returns the number of recurrences up to and including the date specified. */ + int durationTo(const QDate &) const; + /** Returns the number of recurrences up to and including the date/time specified. */ + int durationTo(const QDateTime &) const; + + /** Returns the date of the last recurrence. + * An invalid date is returned if the recurrence has no end. + * Note: for some recurrence types, endDate() can involve significant calculation. + */ + QDate endDate() const; + /** Returns the date and time of the last recurrence. + * An invalid date is returned if the recurrence has no end. + * Note: for some recurrence types, endDateTime() can involve significant calculation. + */ + QDateTime endDateTime() const; + /** Returns a string representing the recurrence end date in the format + according to the user's locale settings. */ + QString endDateStr(bool shortfmt=true) const; + + /** Sets an event to recur minutely. + * @var _rFreq the frequency to recur, e.g. 2 is every other minute + * @var duration the number of times the event is to occur, or -1 to recur indefinitely. + */ + void setMinutely(int _rFreq, int duration); + /** Sets an event to recur minutely. + * @var _rFreq the frequency to recur, e.g. 2 is every other minute + * @var endDateTime the ending date/time after which to stop recurring + */ + void setMinutely(int _rFreq, const QDateTime &endDateTime); + + /** Sets an event to recur hourly. + * @var _rFreq the frequency to recur, e.g. 2 is every other hour + * @var duration the number of times the event is to occur, or -1 to recur indefinitely. + */ + void setHourly(int _rFreq, int duration); + /** Sets an event to recur hourly. + * @var _rFreq the frequency to recur, e.g. 2 is every other hour + * @var endDateTime the ending date/time after which to stop recurring + */ + void setHourly(int _rFreq, const QDateTime &endDateTime); + + /** Sets an event to recur daily. + * @var _rFreq the frequency to recur, e.g. 2 is every other day + * @var duration the number of times the event is to occur, or -1 to recur indefinitely. + */ + void setDaily(int _rFreq, int duration); + /** Sets an event to recur daily. + * @var _rFreq the frequency to recur, e.g. 2 is every other day + * @var endDate the ending date after which to stop recurring + */ + void setDaily(int _rFreq, const QDate &endDate); + + /** Sets an event to recur weekly. + * @var _rFreq the frequency to recur, e.g. every other week etc. + * @var _rDays a 7 bit array indicating which days on which to recur (bit 0 = Monday). + * @var duration the number of times the event is to occur, or -1 to recur indefinitely. + * @var weekStart the first day of the week (Monday=1 .. Sunday=7, default is Monday). + */ + void setWeekly(int _rFreq, const QBitArray &_rDays, int duration, int weekStart = 1); + /** Sets an event to recur weekly. + * @var _rFreq the frequency to recur, e.g. every other week etc. + * @var _rDays a 7 bit array indicating which days on which to recur (bit 0 = Monday). + * @var endDate the date on which to stop recurring. + * @var weekStart the first day of the week (Monday=1 .. Sunday=7, default is Monday). + */ + void setWeekly(int _rFreq, const QBitArray &_rDays, const QDate &endDate, int weekStart = 1); + /** Returns the first day of the week. Monday=1 .. Sunday=7. */ + int weekStart() const { return rWeekStart; } + /** Returns week day mask (bit 0 = Monday). */ + const QBitArray &days() const; + + /** Sets an event to recur monthly. + * @var type rMonthlyPos or rMonthlyDay + * @var _rFreq the frequency to recur, e.g. 3 for every third month. + * @var duration the number of times the event is to occur, or -1 to recur indefinitely. + */ + void setMonthly(short type, int _rFreq, int duration); + /** same as above, but with ending date not number of recurrences */ + void setMonthly(short type, int _rFreq, const QDate &endDate); + /** Adds a position to the recursMonthlyPos recurrence rule, if it is + * set. + * @var _rPos the position in the month for the recurrence, with valid + * values being 1-5 (5 weeks max in a month). + * @var _rDays the days for the position to recur on (bit 0 = Monday). + * Example: _rPos = 2, and bits 0 and 2 are set in _rDays: + * the rule is to repeat every 2nd Monday and Wednesday in the month. + */ + void addMonthlyPos(short _rPos, const QBitArray &_rDays); + /** Adds a position the the recursMonthlyDay list. + * @var _rDay the date in the month to recur. + */ + void addMonthlyDay(short _rDay); + /** Returns list of day positions in months. */ + const QPtrList<rMonthPos> &monthPositions() const; + /** Returns list of day numbers of a month. */ + const QPtrList<int> &monthDays() const; + + /** Sets an event to recur yearly. + * @var type rYearlyMonth, rYearlyPos or rYearlyDay + * @var freq the frequency to recur, e.g. 3 for every third year. + * @var duration the number of times the event is to occur, or -1 to recur indefinitely. + */ + void setYearly(int type, int freq, int duration); + /** Sets an event to recur yearly ending at \a endDate. */ + void setYearly(int type, int freq, const QDate &endDate); + /** Sets an event to recur yearly on specified dates. + * The dates must be specified by calling addYearlyNum(). + * @var type the way recurrences of February 29th are to be handled in non-leap years. + * @var freq the frequency to recur, e.g. 3 for every third year. + * @var duration the number of times the event is to occur, or -1 to recur indefinitely. + */ + void setYearlyByDate(Feb29Type type, int freq, int duration); + /** Sets an event to recur yearly ending at \a endDate. */ + void setYearlyByDate(Feb29Type type, int freq, const QDate &endDate); + /** Adds position of day or month in year. + * N.B. for recursYearlyPos, addYearlyMonthPos() must also be called + * to add positions within the month. */ + void addYearlyNum(short _rNum); + /** Adds a position to the recursYearlyPos recurrence rule, if it is set. + * N.B. addYearlyNum() must also be called to add recurrence months. + * Parameters are the same as for addMonthlyPos(). + */ + void addYearlyMonthPos(short _rPos, const QBitArray &_rDays); + /** Returns positions of days or months in year. */ + const QPtrList<int> &yearNums() const; + /** Returns list of day positions in months, for a recursYearlyPos recurrence rule. */ + const QPtrList<rMonthPos> &yearMonthPositions() const; + /** Returns how yearly recurrences of February 29th are handled. */ + Feb29Type feb29YearlyType() const { return mFeb29YearlyType; } + /** Sets the default method for handling yearly recurrences of February 29th. */ + static void setFeb29YearlyTypeDefault(Feb29Type t) { mFeb29YearlyDefaultType = t; } + /** Returns the default method for handling yearly recurrences of February 29th. */ + static Feb29Type setFeb29YearlyTypeDefault() { return mFeb29YearlyDefaultType; } + + /** + Debug output. + */ + void dump() const; + QString recurrenceText() const; + + protected: + enum PeriodFunc { END_DATE_AND_COUNT, COUNT_TO_DATE, NEXT_AFTER_DATE }; + struct MonthlyData; friend struct MonthlyData; + struct YearlyMonthData; friend struct YearlyMonthData; + struct YearlyPosData; friend struct YearlyPosData; + struct YearlyDayData; friend struct YearlyDayData; + + bool recursSecondly(const QDate &, int secondFreq) const; + bool recursMinutelyAt(const QDateTime &dt, int minuteFreq) const; + bool recursDaily(const QDate &) const; + bool recursWeekly(const QDate &) const; + bool recursMonthly(const QDate &) const; + bool recursYearlyByMonth(const QDate &) const; + bool recursYearlyByPos(const QDate &) const; + bool recursYearlyByDay(const QDate &) const; + + QDate getNextDateNoTime(const QDate& preDate, bool* last) const; + QDate getPreviousDateNoTime(const QDate& afterDate, bool* last) const; + + void addMonthlyPos_(short _rPos, const QBitArray &_rDays); + void setDailySub(short type, int freq, int duration); + void setYearly_(short type, Feb29Type, int freq, int duration); + int recurCalc(PeriodFunc, QDate &enddate) const; + int recurCalc(PeriodFunc, QDateTime &endtime) const; + int secondlyCalc(PeriodFunc, QDateTime& endtime, int freq) const; + int dailyCalc(PeriodFunc, QDate &enddate) const; + int weeklyCalc(PeriodFunc, QDate &enddate) const; + int weeklyCalcEndDate(QDate& enddate, int daysPerWeek) const; + int weeklyCalcToDate(const QDate& enddate, int daysPerWeek) const; + int weeklyCalcNextAfter(QDate& enddate, int daysPerWeek) const; + int monthlyCalc(PeriodFunc, QDate &enddate) const; + int monthlyCalcEndDate(QDate& enddate, MonthlyData&) const; + int monthlyCalcToDate(const QDate& enddate, MonthlyData&) const; + int monthlyCalcNextAfter(QDate& enddate, MonthlyData&) const; + int yearlyMonthCalc(PeriodFunc, QDate &enddate) const; + int yearlyMonthCalcEndDate(QDate& enddate, YearlyMonthData&) const; + int yearlyMonthCalcToDate(const QDate& enddate, YearlyMonthData&) const; + int yearlyMonthCalcNextAfter(QDate& enddate, YearlyMonthData&) const; + int yearlyPosCalc(PeriodFunc, QDate &enddate) const; + int yearlyPosCalcEndDate(QDate& enddate, YearlyPosData&) const; + int yearlyPosCalcToDate(const QDate& enddate, YearlyPosData&) const; + int yearlyPosCalcNextAfter(QDate& enddate, YearlyPosData&) const; + int yearlyDayCalc(PeriodFunc, QDate &enddate) const; + int yearlyDayCalcEndDate(QDate& enddate, YearlyDayData&) const; + int yearlyDayCalcToDate(const QDate& enddate, YearlyDayData&) const; + int yearlyDayCalcNextAfter(QDate& enddate, YearlyDayData&) const; + + int countMonthlyPosDays() const; + void getMonthlyPosDays(QValueList<int>&, int daysInMonth, + int startDayOfWeek) const; + bool getMonthlyDayDays(QValueList<int>&, int daysInMonth) const; + bool getYearlyMonthMonths(int day, QValueList<int>&, + QValueList<int> &leaplist) const; + + int getFirstDayInWeek(int startDay, bool useWeekStart = true) const; + int getLastDayInWeek(int endDay, bool useWeekStart = true) const; + QDate getFirstDateInMonth(const QDate& earliestDate) const; + QDate getLastDateInMonth(const QDate& latestDate) const; + QDate getFirstDateInYear(const QDate& earliestDate) const; + QDate getLastDateInYear(const QDate& latestDate) const; + + private: + // Prohibit copying + Recurrence(const Recurrence&); + Recurrence &operator=(const Recurrence&); + + short recurs; // should be one of the enums. + + int rWeekStart; // day which starts the week, Monday=1 .. Sunday=7 + QBitArray rDays; // array of days during week it recurs + + QPtrList<rMonthPos> rMonthPositions; // list of positions during a month + // on which an event recurs + + QPtrList<int> rMonthDays; // list of days during a month on + // which the event recurs + + QPtrList<int> rYearNums; // either months/days to recur on for rYearly, + // sorted in numerical order + + int rFreq; // frequency of period + + // one of the following must be specified + int rDuration; // num times to recur (inc. first occurrence), -1 = infinite + QDateTime rEndDateTime; // date/time at which to end recurrence + + QDateTime mRecurStart; // date/time of first recurrence + bool mFloats; // the recurrence has no time, just a date + bool mRecurReadOnly; + int mRecurExDatesCount; // number of recurrences (in addition to rDuration) which are excluded + Feb29Type mFeb29YearlyType; // how to handle yearly recurrences of February 29th + static Feb29Type mFeb29YearlyDefaultType; // default value for mFeb29YearlyType + + // Backwards compatibility for KDE < 3.1. + int mCompatVersion; // calendar file version for backwards compatibility + short mCompatRecurs; // original 'recurs' in old calendar format, or rNone + int mCompatDuration; // original 'rDuration' in old calendar format, or 0 + + Incidence *mParent; +}; + +} + +#endif diff --git a/libkcal/resourcecalendar.h b/libkcal/resourcecalendar.h new file mode 100644 index 0000000..26b3831 --- a/dev/null +++ b/libkcal/resourcecalendar.h @@ -0,0 +1,16 @@ +#ifndef MICRO_KCAL_RESOURCECALENDAR_H +#define MICRO_KCAL_RESOURCECALENDAR_H + +namespace KCal { + +class ResourceCalendar +{ +}; + +class CalendarResourceManager +{ +}; + +} + +#endif diff --git a/libkcal/scheduler.cpp b/libkcal/scheduler.cpp new file mode 100644 index 0000000..253d8b7 --- a/dev/null +++ b/libkcal/scheduler.cpp @@ -0,0 +1,355 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdir.h> +#include <qfile.h> +#include <qtextstream.h> + +#include <klocale.h> +#include <kdebug.h> +#include <kstandarddirs.h> + +#include "event.h" +#include "todo.h" +#include "freebusy.h" +#include "icalformat.h" +#include "calendar.h" + +#include "scheduler.h" + +using namespace KCal; + +ScheduleMessage::ScheduleMessage(IncidenceBase *incidence,int method,ScheduleMessage::Status status) +{ + mIncidence = incidence; + mMethod = method; + mStatus = status; +} + +QString ScheduleMessage::statusName(ScheduleMessage::Status status) +{ + switch (status) { + case PublishNew: + return i18n("Publish"); + case Obsolete: + return i18n("Obsolete"); + case RequestNew: + return i18n("New Request"); + case RequestUpdate: + return i18n("Updated Request"); + default: + return i18n("Unknown Status: %1").arg(QString::number(status)); + } +} + +Scheduler::Scheduler(Calendar *calendar) +{ + mCalendar = calendar; + mFormat = new ICalFormat(); +} + +Scheduler::~Scheduler() +{ + delete mFormat; +} + +bool Scheduler::acceptTransaction(IncidenceBase *incidence,Method method,ScheduleMessage::Status status) +{ + kdDebug() << "Scheduler::acceptTransaction " << endl; + switch (method) { + case Publish: + return acceptPublish(incidence, status, method); + case Request: + return acceptRequest(incidence, status); + case Add: + return acceptAdd(incidence, status); + case Cancel: + return acceptCancel(incidence, status); + case Declinecounter: + return acceptDeclineCounter(incidence, status); + case Reply: + return acceptReply(incidence, status, method); + case Refresh: + return acceptRefresh(incidence, status); + case Counter: + return acceptCounter(incidence, status); + default: + deleteTransaction(incidence); + return false; + } + deleteTransaction(incidence); + return false; +} + +QString Scheduler::methodName(Method method) +{ + switch (method) { + case Publish: + return QString::fromLatin1("Publish"); + case Request: + return QString::fromLatin1("Request"); + case Refresh: + return QString::fromLatin1("Refresh"); + case Cancel: + return QString::fromLatin1("Cancel"); + case Add: + return QString::fromLatin1("Add"); + case Reply: + return QString::fromLatin1("Reply"); + case Counter: + return QString::fromLatin1("Counter"); + case Declinecounter: + return QString::fromLatin1("Decline Counter"); + default: + return QString::fromLatin1("Unknown"); + } +} + +QString Scheduler::translatedMethodName(Method method) +{ + switch (method) { + case Publish: + return i18n("Publish"); + case Request: + return i18n("Request"); + case Refresh: + return i18n("Refresh"); + case Cancel: + return i18n("Cancel"); + case Add: + return i18n("Add"); + case Reply: + return i18n("Reply"); + case Counter: + return i18n("counter proposal","Counter"); + case Declinecounter: + return i18n("decline counter proposal","Decline Counter"); + default: + return i18n("Unknown"); + } +} + +bool Scheduler::deleteTransaction(IncidenceBase *) +{ + return true; +} + +bool Scheduler::acceptPublish(IncidenceBase *incidence,ScheduleMessage::Status status, Method method) +{ + if(incidence->type()=="FreeBusy") { + return acceptFreeBusy(incidence, method); + } + switch (status) { + case ScheduleMessage::Unknown: + case ScheduleMessage::PublishNew: + if (!mCalendar->event(incidence->uid())) { + Incidence *inc = static_cast<Incidence *>(incidence); + mCalendar->addIncidence(inc); + deleteTransaction(incidence); + } + return true; + case ScheduleMessage::Obsolete: + return true; + default: + deleteTransaction(incidence); + return false; + } + deleteTransaction(incidence); + return false; +} + +bool Scheduler::acceptRequest(IncidenceBase *incidence,ScheduleMessage::Status status) +{ + Incidence *inc = static_cast<Incidence *>(incidence); + if (inc->type()=="FreeBusy") { + // reply to this request is handled in korganizer's incomingdialog + return true; + } else { + Event *even = mCalendar->event(incidence->uid()); + if (even) { + if ( even->revision()<=inc->revision() ) { + if ( even->revision()==inc->revision() && + even->lastModified()>inc->lastModified()) { + deleteTransaction(incidence); + return false; + } + mCalendar->deleteEvent(even); + } else { + deleteTransaction(incidence); + return false; + } + } else { + Todo *todo = mCalendar->todo(incidence->uid()); + if (todo) { + if ( todo->revision()<=inc->revision() ) { + if ( todo->revision()==inc->revision() && + todo->lastModified()>inc->lastModified()) { + deleteTransaction(incidence); + return false; + } + mCalendar->deleteTodo(todo); + } else { + deleteTransaction(incidence); + return false; + } + } + } + } + mCalendar->addIncidence(inc); + deleteTransaction(incidence); + return true; +} + +bool Scheduler::acceptAdd(IncidenceBase *incidence,ScheduleMessage::Status status) +{ + deleteTransaction(incidence); + return false; +} + +bool Scheduler::acceptCancel(IncidenceBase *incidence,ScheduleMessage::Status status) +{ + bool ret = false; + Event *even = mCalendar->event(incidence->uid()); + if (even) { + mCalendar->deleteEvent(even); + ret = true; + } else { + Todo *todo = mCalendar->todo(incidence->uid()); + if (todo) { + mCalendar->deleteTodo(todo); + ret = true; + } + } + deleteTransaction(incidence); + return ret; +} + +bool Scheduler::acceptDeclineCounter(IncidenceBase *incidence,ScheduleMessage::Status status) +{ + deleteTransaction(incidence); + return false; +} + +//bool Scheduler::acceptFreeBusy(Incidence *incidence,ScheduleMessage::Status status) +//{ +// deleteTransaction(incidence); +// return false; +//} + +bool Scheduler::acceptReply(IncidenceBase *incidence,ScheduleMessage::Status status, Method method) +{ + if(incidence->type()=="FreeBusy") { + return acceptFreeBusy(incidence, method); + } + bool ret = false; + Event *ev = mCalendar->event(incidence->uid()); + Todo *to = mCalendar->todo(incidence->uid()); + if (ev || to) { + //get matching attendee in calendar + kdDebug(5800) << "Scheduler::acceptTransaction match found!" << endl; + QPtrList<Attendee> attendeesIn = incidence->attendees(); + QPtrList<Attendee> attendeesEv; + if (ev) attendeesEv = ev->attendees(); + if (to) attendeesEv = to->attendees(); + Attendee *attIn; + Attendee *attEv; + for ( attIn = attendeesIn.first(); attIn; attIn = attendeesIn.next() ) { + for ( attEv = attendeesEv.first(); attEv; attEv = attendeesEv.next() ) { + if (attIn->email()==attEv->email()) { + //update attendee-info + kdDebug(5800) << "Scheduler::acceptTransaction update attendee" << endl; + attEv->setStatus(attIn->status()); + attEv->setRSVP(false); + // better to not update the sequence number with replys + //if (ev) ev->setRevision(ev->revision()+1); + //if (to) to->setRevision(to->revision()+1); + ret = true; + } + } + } + } + if (ret) deleteTransaction(incidence); + return ret; +} + +bool Scheduler::acceptRefresh(IncidenceBase *incidence,ScheduleMessage::Status status) +{ + // handled in korganizer's IncomingDialog + deleteTransaction(incidence); + return false; +} + +bool Scheduler::acceptCounter(IncidenceBase *incidence,ScheduleMessage::Status status) +{ + deleteTransaction(incidence); + return false; +} + +bool Scheduler::acceptFreeBusy(IncidenceBase *incidence, Method method) +{ + FreeBusy *freebusy = static_cast<FreeBusy *>(incidence); + + QString freeBusyDirName = locateLocal("appdata","freebusy"); + kdDebug() << "acceptFreeBusy:: freeBusyDirName: " << freeBusyDirName << endl; + + QString from; + if(method == Scheduler::Publish) { + from = freebusy->organizer(); + } + if((method == Scheduler::Reply) && (freebusy->attendeeCount() == 1)) { + Attendee *attendee = freebusy->attendees().first(); + from = attendee->email(); + } + + QDir freeBusyDir(freeBusyDirName); + if (!freeBusyDir.exists()) { + kdDebug() << "Directory " << freeBusyDirName << " does not exist!" << endl; + kdDebug() << "Creating directory: " << freeBusyDirName << endl; + + if(!freeBusyDir.mkdir(freeBusyDirName, TRUE)) { + kdDebug() << "Could not create directory: " << freeBusyDirName << endl; + return false; + } + } + + QString filename(freeBusyDirName); + filename += "/"; + filename += from; + filename += ".ifb"; + QFile f(filename); + + kdDebug() << "acceptFreeBusy: filename" << filename << endl; + + freebusy->clearAttendees(); + freebusy->setOrganizer(from); + + QString messageText = mFormat->createScheduleMessage(freebusy, Publish); + + if (!f.open(IO_ReadWrite)) { + kdDebug() << "acceptFreeBusy: Can't open:" << filename << " for writing" << endl; + return false; + } + QTextStream t(&f); + t << messageText; + f.close(); + + deleteTransaction(incidence); + return true; +} diff --git a/libkcal/scheduler.h b/libkcal/scheduler.h new file mode 100644 index 0000000..a9f43b9 --- a/dev/null +++ b/libkcal/scheduler.h @@ -0,0 +1,133 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef SCHEDULER_H +#define SCHEDULER_H + +// iTIP transactions base class + +#include <qstring.h> +#include <qptrlist.h> + +namespace KCal { + +class IncidenceBase; +class Event; +class Calendar; +class ICalFormat; + +/** + This class provides an encapsulation of a scheduling message. It associates an + incidence with a method and status information. This class is used by the + Scheduler class. + + @short A Scheduling message +*/ +class ScheduleMessage { + public: + /** Message status. */ + enum Status { PublishNew, Obsolete, RequestNew, RequestUpdate, Unknown }; + + /** + Create a scheduling message with method as defined in Scheduler::Method + and a status. + */ + ScheduleMessage(IncidenceBase *,int method,Status status); + ~ScheduleMessage() {}; + + /** Return event associated with this message. */ + IncidenceBase *event() { return mIncidence; } + /** Return iTIP method associated with this message. */ + int method() { return mMethod; } + /** Return status of this message. */ + Status status() { return mStatus; } + /** Return error message if there is any. */ + QString error() { return mError; } + + /** Return a human-readable name for an ical message status. */ + static QString statusName(Status status); + + private: + IncidenceBase *mIncidence; + int mMethod; + Status mStatus; + QString mError; +}; + +/** + This class provides an encapsulation of iTIP transactions. It is an abstract + base class for inheritance by implementations of the iTIP scheme like iMIP or + iRIP. +*/ +class Scheduler { + public: + /** iTIP methods. */ + enum Method { Publish,Request,Refresh,Cancel,Add,Reply,Counter, + Declinecounter,NoMethod }; + + /** Create scheduler for calendar specified as argument. */ + Scheduler(Calendar *calendar); + virtual ~Scheduler(); + + /** iTIP publish action */ + virtual bool publish (IncidenceBase *incidence,const QString &recipients) = 0; + /** Perform iTIP transaction on incidence. The method is specified as the + method argumanet and can be any valid iTIP method. */ + virtual bool performTransaction(IncidenceBase *incidence,Method method) = 0; + /** Perform iTIP transaction on incidence to specified recipient(s). The + method is specified as the method argumanet and can be any valid iTIP + method. */ + virtual bool performTransaction(IncidenceBase *incidence,Method method,const QString &recipients) = 0; + /** Retrieve incoming iTIP transactions */ + virtual QPtrList<ScheduleMessage> retrieveTransactions() = 0; + + /** + Accept transaction. The incidence argument specifies the iCal compoennt + on which the transaction acts. The status is the result of processing a + iTIP message with the current calendar and specifies the action to be + taken for this incidence. + */ + bool acceptTransaction(IncidenceBase *,Method method,ScheduleMessage::Status status); + + /** Return a machine-readable name for a iTIP method. */ + static QString methodName(Method); + /** Return a translated and human-readable name for a iTIP method. */ + static QString translatedMethodName(Method); + + virtual bool deleteTransaction(IncidenceBase *incidence); + + protected: + + bool acceptPublish(IncidenceBase *,ScheduleMessage::Status status, Method method); + bool acceptRequest(IncidenceBase *,ScheduleMessage::Status status); + bool acceptAdd(IncidenceBase *,ScheduleMessage::Status status); + bool acceptCancel(IncidenceBase *,ScheduleMessage::Status status); + bool acceptDeclineCounter(IncidenceBase *,ScheduleMessage::Status status); + bool acceptReply(IncidenceBase *,ScheduleMessage::Status status, Method method); + bool acceptRefresh(IncidenceBase *,ScheduleMessage::Status status); + bool acceptCounter(IncidenceBase *,ScheduleMessage::Status status); + bool acceptFreeBusy(IncidenceBase *,Method method); + + Calendar *mCalendar; + ICalFormat *mFormat; +}; + +} + +#endif // SCHEDULER_H diff --git a/libkcal/sharpformat.cpp b/libkcal/sharpformat.cpp new file mode 100644 index 0000000..f83f72e --- a/dev/null +++ b/libkcal/sharpformat.cpp @@ -0,0 +1,1007 @@ +/* + This file is part of libkcal. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdatetime.h> +#include <qstring.h> +#include <qapplication.h> +#include <qptrlist.h> +#include <qregexp.h> +#include <qmessagebox.h> +#include <qclipboard.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qtextcodec.h> +#include <qxml.h> +#include <qlabel.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> + +#include "calendar.h" +#include "alarm.h" +#include "recurrence.h" +#include "calendarlocal.h" + +#include "sharpformat.h" + +using namespace KCal; + +//CARDID,CATEGORY,DSRP,PLCE,MEM1,TIM1,TIM2,ADAY,ARON,ARMN,ARSD,RTYP,RFRQ,RPOS,RDYS,REND,REDT,ALSD,ALED,MDAY +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + +//ARSD silentalarm = 0 +// 11 RTYP 225 no /0 dialy/ 1 weekly/ 3 month by date/ 2 month by day(pos)/ yearly +// 12 RFRQ +// 13 RPOS pos = 4. monday in month +// 14 RDYS days: 1 mon/ 2 tue .. 64 sun +// 15 REND 0 = no end/ 1 = end +// 16 REDT rec end dt +//ALSD +//ALED +//MDAY + +class SharpParser : public QObject +{ + public: + SharpParser( Calendar *calendar ) : mCalendar( calendar ) { + oldCategories = 0; + } + + bool startElement( Calendar *existingCalendar, const QStringList & attList, QString qName ) + { + int i = 1; + bool skip = true; + int max = attList.count() -2; + while ( i < max ) { + if ( !attList[i].isEmpty() ) { + skip = false; + break; + } + ++i ; + } + if ( skip ) + return false; + ulong cSum = SharpFormat::getCsum(attList ); + + if ( qName == "Event" ) { + Event *event; + event = existingCalendar->event( attList[0].toInt() ); + if ( event ) + event = (Event*)event->clone(); + else + event = new Event; + event->setZaurusId( attList[0].toInt() ); + event->setZaurusUid( cSum ); + event->setZaurusStat( -2 ); + + event->setSummary( attList[2] ); + event->setLocation( attList[3] ); + event->setDescription( attList[4] ); + if ( attList[7] == "1" ) { + event->setDtStart( QDateTime(fromString( attList[17]+"000000", false ).date(),QTime(0,0,0 ) )); + event->setDtEnd( QDateTime(fromString( attList[18]+"000000", false ).date(),QTime(0,0,0 ))); + event->setFloats( true ); + } else { + event->setFloats( false ); + event->setDtStart( fromString( attList[5] ) ); + event->setDtEnd( fromString( attList[6] )); + } + + QString rtype = attList[11]; + if ( rtype != "255" ) { + // qDebug("recurs "); + QDate startDate = event->dtStart().date(); + + QString freqStr = attList[12]; + int freq = freqStr.toInt(); + + QString hasEndDateStr = attList[15] ; + bool hasEndDate = hasEndDateStr == "1"; + + QString endDateStr = attList[16]; + QDate endDate = fromString( endDateStr ).date(); + + QString weekDaysStr = attList[14]; + uint weekDaysNum = weekDaysStr.toInt(); + + QBitArray weekDays( 7 ); + int i; + int bb = 1; + for( i = 1; i <= 7; ++i ) { + weekDays.setBit( i - 1, ( bb & weekDaysNum )); + bb = 2 << (i-1); + //qDebug(" %d bit %d ",i-1,weekDays.at(i-1) ); + } + // qDebug("next "); + QString posStr = attList[13]; + int pos = posStr.toInt(); + Recurrence *r = event->recurrence(); + + if ( rtype == "0" ) { + if ( hasEndDate ) r->setDaily( freq, endDate ); + else r->setDaily( freq, -1 ); + } else if ( rtype == "1" ) { + if ( hasEndDate ) r->setWeekly( freq, weekDays, endDate ); + else r->setWeekly( freq, weekDays, -1 ); + } else if ( rtype == "3" ) { + if ( hasEndDate ) + r->setMonthly( Recurrence::rMonthlyDay, freq, endDate ); + else + r->setMonthly( Recurrence::rMonthlyDay, freq, -1 ); + r->addMonthlyDay( startDate.day() ); + } else if ( rtype == "2" ) { + if ( hasEndDate ) + r->setMonthly( Recurrence::rMonthlyPos, freq, endDate ); + else + r->setMonthly( Recurrence::rMonthlyPos, freq, -1 ); + QBitArray days( 7 ); + days.fill( false ); + days.setBit( startDate.dayOfWeek() - 1 ); + r->addMonthlyPos( pos, days ); + } else if ( rtype == "4" ) { + if ( hasEndDate ) + r->setYearly( Recurrence::rYearlyMonth, freq, endDate ); + else + r->setYearly( Recurrence::rYearlyMonth, freq, -1 ); + r->addYearlyNum( startDate.month() ); + } + } + + QString categoryList = attList[1] ; + event->setCategories( lookupCategories( categoryList ) ); + + // strange 0 semms to mean: alarm enabled + if ( attList[8] == "0" ) { + Alarm *alarm; + if ( event->alarms().count() > 0 ) + alarm = event->alarms().first(); + else { + alarm = new Alarm( event ); + event->addAlarm( alarm ); + } + alarm->setType( Alarm::Audio ); + alarm->setEnabled( true ); + int alarmOffset = attList[9].toInt(); + alarm->setStartOffset( alarmOffset * -60 ); + } + + mCalendar->addEvent( event); + } else if ( qName == "Todo" ) { + Todo *todo; + + todo = existingCalendar->todo( attList[0].toInt() ); + if (todo ) + todo = (Todo*)todo->clone(); + else + todo = new Todo; + +//CARDID,CATEGORY,ETDY,LTDY,FNDY,MARK,PRTY,TITL,MEM1 +// 0 1 2 3 4 5 6 7 8 +//1,,,,,1,4,Loch zumachen,"" +//3,Privat,20040317T000000,20040318T000000,20040319T000000,0,5,Call bbb,"notes123 bbb gggg ""bb "" " +//2,"Familie,Freunde,Holiday",20040318T000000,20040324T000000,20040317T000000,1,2,tod2,notes + + todo->setZaurusId( attList[0].toInt() ); + todo->setZaurusUid( cSum ); + todo->setZaurusStat( -2 ); + + todo->setSummary( attList[7] ); + todo->setDescription( attList[8]); + + int priority = attList[6].toInt(); + if ( priority == 0 ) priority = 3; + todo->setPriority( priority ); + + QString categoryList = attList[1]; + todo->setCategories( lookupCategories( categoryList ) ); + + + + QString hasDateStr = attList[3]; // due + if ( !hasDateStr.isEmpty() ) { + if ( hasDateStr.right(6) == "000000" ) { + todo->setDtDue( QDateTime(fromString( hasDateStr, false ).date(), QTime(0,0,0 )) ); + todo->setFloats( true ); + } + else { + todo->setDtDue( fromString( hasDateStr ) ); + todo->setFloats( false ); + } + + todo->setHasDueDate( true ); + } + hasDateStr = attList[2];//start + if ( !hasDateStr.isEmpty() ) { + + todo->setDtStart( fromString( hasDateStr ) ); + todo->setHasStartDate( true); + } else + todo->setHasStartDate( false ); + hasDateStr = attList[4];//completed + if ( !hasDateStr.isEmpty() ) { + todo->setCompleted(fromString( hasDateStr ) ); + } + QString completedStr = attList[5]; + if ( completedStr == "0" ) + todo->setCompleted( true ); + else + todo->setCompleted( false ); + mCalendar->addTodo( todo ); + + } else if ( qName == "Category" ) { + /* + QString id = attributes.value( "id" ); + QString name = attributes.value( "name" ); + setCategory( id, name ); + */ + } + //qDebug("end "); + return true; + } + + + void setCategoriesList ( QStringList * c ) + { + oldCategories = c; + } + + QDateTime fromString ( QString s, bool useTz = true ) { + QDateTime dt; + int y,m,t,h,min,sec; + y = s.mid(0,4).toInt(); + m = s.mid(4,2).toInt(); + t = s.mid(6,2).toInt(); + h = s.mid(9,2).toInt(); + min = s.mid(11,2).toInt(); + sec = s.mid(13,2).toInt(); + dt = QDateTime(QDate(y,m,t), QTime(h,min,sec)); + int offset = KGlobal::locale()->localTimeOffset( dt ); + if ( useTz ) + dt = dt.addSecs ( offset*60); + return dt; + + } + protected: + QDateTime toDateTime( const QString &value ) + { + QDateTime dt; + dt.setTime_t( value.toUInt() ); + + return dt; + } + + QStringList lookupCategories( const QString &categoryList ) + { + QStringList categoryIds = QStringList::split( ";", categoryList ); + QStringList categories; + QStringList::ConstIterator it; + for( it = categoryIds.begin(); it != categoryIds.end(); ++it ) { + QString cate = category( *it ); + if ( oldCategories ) { + if ( ! oldCategories->contains( cate ) ) + oldCategories->append( cate ); + } + categories.append(cate ); + } + return categories; + } + + private: + Calendar *mCalendar; + QStringList * oldCategories; + static QString category( const QString &id ) + { + QMap<QString,QString>::ConstIterator it = mCategoriesMap.find( id ); + if ( it == mCategoriesMap.end() ) return id; + else return *it; + } + + static void setCategory( const QString &id, const QString &name ) + { + mCategoriesMap.insert( id, name ); + } + + static QMap<QString,QString> mCategoriesMap; +}; + +QMap<QString,QString> SharpParser::mCategoriesMap; + +SharpFormat::SharpFormat() +{ + mCategories = 0; +} + +SharpFormat::~SharpFormat() +{ +} +ulong SharpFormat::getCsum( const QStringList & attList) +{ + int max = attList.count() -1; + ulong cSum = 0; + int j,k,i; + int add; + for ( i = 1; i < max ; ++i ) { + QString s = attList[i]; + if ( ! s.isEmpty() ){ + j = s.length(); + for ( k = 0; k < j; ++k ) { + int mul = k +1; + add = s[k].unicode (); + if ( k < 16 ) + mul = mul * mul; + add = add * mul *i*i*i; + cSum += add; + } + } + } + return cSum; + +} +#include <stdlib.h> +#define DEBUGMODE false +bool SharpFormat::load( Calendar *calendar, Calendar *existngCal ) +{ + + + bool debug = DEBUGMODE; + //debug = true; + QString text; + QString codec = "utf8"; + QLabel status ( i18n("Reading events ..."), 0 ); + + int w = status.sizeHint().width()+20 ; + if ( w < 200 ) w = 200; + int h = status.sizeHint().height()+20 ; + int dw = QApplication::desktop()->width(); + int dh = QApplication::desktop()->height(); + status.setCaption(i18n("Reading DTM Data") ); + status.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); + status.show(); + status.raise(); + qApp->processEvents(); + QString fileName; + if ( ! debug ) { + fileName = "/tmp/kopitempout"; + QString command ="db2file datebook -r -c "+ codec + " > " + fileName; + system ( command.latin1() ); + } else { + fileName = "/tmp/events.txt"; + + } + QFile file( fileName ); + if (!file.open( IO_ReadOnly ) ) { + return false; + + } + QTextStream ts( &file ); + ts.setCodec( QTextCodec::codecForName("utf8") ); + text = ts.read(); + file.close(); + status.setText( i18n("Processing events ...") ); + status.raise(); + qApp->processEvents(); + fromString2Cal( calendar, existngCal, text, "Event" ); + status.setText( i18n("Reading todos ...") ); + qApp->processEvents(); + if ( ! debug ) { + fileName = "/tmp/kopitempout"; + QString command = "db2file todo -r -c " + codec+ " > " + fileName; + system ( command.latin1() ); + } else { + fileName = "/tmp/todo.txt"; + } + file.setName( fileName ); + if (!file.open( IO_ReadOnly ) ) { + return false; + + } + ts.setDevice( &file ); + text = ts.read(); + file.close(); + + status.setText( i18n("Processing todos ...") ); + status.raise(); + qApp->processEvents(); + fromString2Cal( calendar, existngCal, text, "Todo" ); + return true; +} +int SharpFormat::getNumFromRecord( QString answer, Incidence* inc ) +{ + int retval = -1; + QStringList templist; + QString tempString; + int start = 0; + int len = answer.length(); + int end = answer.find ("\n",start)+1; + bool ok = true; + start = end; + int ccc = 0; + while ( start > 0 ) { + templist.clear(); + ok = true; + int loopCount = 0; + while ( ok ) { + ++loopCount; + if ( loopCount > 25 ) { + qDebug("KO: Error in while loop"); + ok = false; + start = 0; + break; + } + if ( ok ) + tempString = getPart( answer, ok, start ); + if ( start >= len || start == 0 ) { + start = 0; + ok = false; + } + if ( tempString.right(1) =="\n" ) + tempString = tempString.left( tempString.length()-1); + + templist.append( tempString ); + } + ++ccc; + if ( ccc == 2 && loopCount < 25 ) { + start = 0; + bool ok; + int newnum = templist[0].toInt( &ok ); + if ( ok && newnum > 0) { + retval = newnum; + inc->setZaurusId( newnum ); + inc->setZaurusUid( getCsum( templist ) ); + inc->setZaurusStat( -4 ); + } + } + } + //qDebug("getNumFromRecord returning : %d ", retval); + return retval; +} +bool SharpFormat::save( Calendar *calendar) +{ + + QLabel status ( i18n("Processing/adding events ..."), 0 ); + int w = status.sizeHint().width()+20 ; + if ( w < 200 ) w = 200; + int h = status.sizeHint().height()+20 ; + int dw = QApplication::desktop()->width(); + int dh = QApplication::desktop()->height(); + status.setCaption(i18n("Writing DTM Data") ); + status.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); + status.show(); + status.raise(); + qApp->processEvents(); + bool debug = DEBUGMODE; + QString codec = "utf8"; + QString answer; + QString ePrefix = "CARDID,CATEGORY,DSRP,PLCE,MEM1,TIM1,TIM2,ADAY,ARON,ARMN,ARSD,RTYP,RFRQ,RPOS,RDYS,REND,REDT,ALSD,ALED,MDAY\n"; + QString tPrefix = "CARDID,CATEGORY,ETDY,LTDY,FNDY,MARK,PRTY,TITL,MEM1\n"; + QString command; + QPtrList<Event> er = calendar->rawEvents(); + Event* ev = er.first(); + QString fileName = "/tmp/kopitempout"; + int i = 0; + QString changeString = ePrefix; + QString deleteString = ePrefix; + bool deleteEnt = false; + bool changeEnt = false; + QString message = i18n("Processing event # "); + int procCount = 0; + while ( ev ) { + //qDebug("i %d ", ++i); + if ( ev->zaurusStat() != -2 ) { + status.setText ( message + QString::number ( ++procCount ) ); + qApp->processEvents(); + QString eString = getEventString( ev ); + if ( ev->zaurusStat() == -3 ) { // delete + // deleting empty strings does not work. + // we write first and x and then delete the record with the x + eString = eString.replace( QRegExp(",\"\""),",\"x\"" ); + changeString += eString + "\n"; + deleteString += eString + "\n"; + deleteEnt = true; + changeEnt = true; + } + else if ( ev->zaurusId() == -1 ) { // add new + command = "(echo \"" + ePrefix + eString + "\" ) | db2file datebook -w -g -c " + codec+ " > "+ fileName; + system ( command.utf8() ); + QFile file( fileName ); + if (!file.open( IO_ReadOnly ) ) { + return false; + + } + QTextStream ts( &file ); + ts.setCodec( QTextCodec::codecForName("utf8") ); + answer = ts.read(); + file.close(); + //qDebug("answer \n%s ", answer.latin1()); + getNumFromRecord( answer, ev ) ; + + } + else { // change existing + //qDebug("canging %d %d",ev->zaurusStat() ,ev->zaurusId() ); + //command = "(echo \"" + ePrefix + eString + "\" ) | db2file datebook -w -g -c " + codec+ " > "+ fileName; + changeString += eString + "\n"; + changeEnt = true; + + } + } + ev = er.next(); + } + status.setText ( i18n("Changing events ...") ); + qApp->processEvents(); + //qDebug("changing... "); + if ( changeEnt ) { + QFile file( fileName ); + if (!file.open( IO_WriteOnly ) ) { + return false; + + } + QTextStream ts( &file ); + ts.setCodec( QTextCodec::codecForName("utf8") ); + ts << changeString ; + file.close(); + command = "db2file datebook -w -g -c " + codec+ " < "+ fileName; + system ( command.latin1() ); + //qDebug("command %s file :\n%s ", command.latin1(), changeString.latin1()); + + } + status.setText ( i18n("Deleting events ...") ); + qApp->processEvents(); + //qDebug("deleting... "); + if ( deleteEnt ) { + QFile file( fileName ); + if (!file.open( IO_WriteOnly ) ) { + return false; + + } + QTextStream ts( &file ); + ts.setCodec( QTextCodec::codecForName("utf8") ); + ts << deleteString; + file.close(); + command = "db2file datebook -d -c " + codec+ " < "+ fileName; + system ( command.latin1() ); + // qDebug("command %s file :\n%s ", command.latin1(), deleteString.latin1()); + } + + + changeString = tPrefix; + deleteString = tPrefix; + status.setText ( i18n("Processing todos ...") ); + qApp->processEvents(); + QPtrList<Todo> tl = calendar->rawTodos(); + Todo* to = tl.first(); + i = 0; + message = i18n("Processing todo # "); + procCount = 0; + while ( to ) { + if ( to->zaurusStat() != -2 ) { + status.setText ( message + QString::number ( ++procCount ) ); + qApp->processEvents(); + QString eString = getTodoString( to ); + if ( to->zaurusStat() == -3 ) { // delete + // deleting empty strings does not work. + // we write first and x and then delete the record with the x + eString = eString.replace( QRegExp(",\"\""),",\"x\"" ); + changeString += eString + "\n"; + deleteString += eString + "\n"; + deleteEnt = true; + changeEnt = true; + } + else if ( to->zaurusId() == -1 ) { // add new + command = "(echo \"" + tPrefix + eString + "\" ) | db2file todo -w -g -c " + codec+ " > "+ fileName; + system ( command.utf8() ); + QFile file( fileName ); + if (!file.open( IO_ReadOnly ) ) { + return false; + + } + QTextStream ts( &file ); + ts.setCodec( QTextCodec::codecForName("utf8") ); + answer = ts.read(); + file.close(); + //qDebug("answer \n%s ", answer.latin1()); + getNumFromRecord( answer, to ) ; + + } + else { // change existing + //qDebug("canging %d %d",to->zaurusStat() ,to->zaurusId() ); + //command = "(echo \"" + ePrefix + eString + "\" ) | db2file datebook -w -g -c " + codec+ " > "+ fileName; + changeString += eString + "\n"; + changeEnt = true; + + } + } + + to = tl.next(); + } + status.setText ( i18n("Changing todos ...") ); + qApp->processEvents(); + //qDebug("changing... "); + if ( changeEnt ) { + QFile file( fileName ); + if (!file.open( IO_WriteOnly ) ) { + return false; + + } + QTextStream ts( &file ); + ts.setCodec( QTextCodec::codecForName("utf8") ); + ts << changeString ; + file.close(); + command = "db2file todo -w -g -c " + codec+ " < "+ fileName; + system ( command.latin1() ); + //qDebug("command %s file :\n%s ", command.latin1(), changeString.latin1()); + + } + status.setText ( i18n("Deleting todos ...") ); + qApp->processEvents(); + //qDebug("deleting... "); + if ( deleteEnt ) { + QFile file( fileName ); + if (!file.open( IO_WriteOnly ) ) { + return false; + + } + QTextStream ts( &file ); + ts.setCodec( QTextCodec::codecForName("utf8") ); + ts << deleteString; + file.close(); + command = "db2file todo -d -c " + codec+ " < "+ fileName; + system ( command.latin1() ); + // qDebug("command %s file :\n%s ", command.latin1(), deleteString.latin1()); + } + + return true; +} +QString SharpFormat::dtToString( const QDateTime& dti, bool useTZ ) +{ + QString datestr; + QString timestr; + int offset = KGlobal::locale()->localTimeOffset( dti ); + QDateTime dt; + if (useTZ) + dt = dti.addSecs ( -(offset*60)); + else + dt = dti; + if(dt.date().isValid()){ + const QDate& date = dt.date(); + datestr.sprintf("%04d%02d%02d", + date.year(), date.month(), date.day()); + } + if(dt.time().isValid()){ + const QTime& time = dt.time(); + timestr.sprintf("T%02d%02d%02d", + time.hour(), time.minute(), time.second()); + } + return datestr + timestr; +} +QString SharpFormat::getEventString( Event* event ) +{ + QStringList list; + list.append( QString::number(event->zaurusId() ) ); + list.append( event->categories().join(",") ); + if ( !event->summary().isEmpty() ) + list.append( event->summary() ); + else + list.append("" ); + if ( !event->location().isEmpty() ) + list.append( event->location() ); + else + list.append("" ); + if ( !event->description().isEmpty() ) + list.append( event->description() ); + else + list.append( "" ); + if ( event->doesFloat () ) { + list.append( dtToString( QDateTime(event->dtStart().date(), QTime(0,0,0)), false )); + list.append( dtToString( QDateTime(event->dtEnd().date(),QTime(23,59,59)), false )); //6 + list.append( "1" ); + + } + else { + list.append( dtToString( event->dtStart()) ); + list.append( dtToString( event->dtEnd()) ); //6 + list.append( "0" ); + } + bool noAlarm = true; + if ( event->alarms().count() > 0 ) { + Alarm * al = event->alarms().first(); + if ( al->enabled() ) { + noAlarm = false; + list.append( "0" ); // yes, 0 == alarm + list.append( QString::number( al->startOffset().asSeconds()/(-60) ) ); + if ( al->type() == Alarm::Audio ) + list.append( "1" ); // type audio + else + list.append( "0" ); // type silent + } + } + if ( noAlarm ) { + list.append( "1" ); // yes, 1 == no alarm + list.append( "0" ); // no alarm offset + list.append( "1" ); // type + } + // next is: 11 + // next is: 11-16 are recurrence + Recurrence* rec = event->recurrence(); + + bool writeEndDate = false; + switch ( rec->doesRecur() ) + { + case Recurrence::rDaily: // 0 + list.append( "0" ); + list.append( QString::number( rec->frequency() ));//12 + list.append( "0" ); + list.append( "0" ); + writeEndDate = true; + break; + case Recurrence::rWeekly:// 1 + list.append( "1" ); + list.append( QString::number( rec->frequency()) );//12 + list.append( "0" ); + { + int days = 0; + QBitArray weekDays = rec->days(); + int i; + for( i = 1; i <= 7; ++i ) { + if ( weekDays[i-1] ) { + days += 1 << (i-1); + } + } + list.append( QString::number( days ) ); + } + //pending weekdays + writeEndDate = true; + + break; + case Recurrence::rMonthlyPos:// 2 + list.append( "2" ); + list.append( QString::number( rec->frequency()) );//12 + + writeEndDate = true; + { + int count = 1; + QPtrList<Recurrence::rMonthPos> rmp; + rmp = rec->monthPositions(); + if ( rmp.first()->negative ) + count = 5 - rmp.first()->rPos - 1; + else + count = rmp.first()->rPos - 1; + list.append( QString::number( count ) ); + + } + + list.append( "0" ); + break; + case Recurrence::rMonthlyDay:// 3 + list.append( "3" ); + list.append( QString::number( rec->frequency()) );//12 + list.append( "0" ); + list.append( "0" ); + writeEndDate = true; + break; + case Recurrence::rYearlyMonth://4 + list.append( "4" ); + list.append( QString::number( rec->frequency()) );//12 + list.append( "0" ); + list.append( "0" ); + writeEndDate = true; + break; + + default: + list.append( "255" ); + list.append( QString() ); + list.append( "0" ); + list.append( QString() ); + list.append( "0" ); + list.append( "20991231T000000" ); + break; + } + if ( writeEndDate ) { + + if ( rec->endDate().isValid() ) { // 15 + 16 + list.append( "1" ); + list.append( dtToString( rec->endDate()) ); + } else { + list.append( "0" ); + list.append( "20991231T000000" ); + } + + } + if ( event->doesFloat () ) { + list.append( dtToString( event->dtStart(), false ).left( 8 )); + list.append( dtToString( event->dtEnd(), false ).left( 8 )); //6 + + } + else { + list.append( QString() ); + list.append( QString() ); + + } + if (event->dtStart().date() == event->dtEnd().date() ) + list.append( "0" ); + else + list.append( "1" ); + + + for(QStringList::Iterator it=list.begin(); + it!=list.end(); ++it){ + QString& s = (*it); + s.replace(QRegExp("\""), "\"\""); + if(s.contains(QRegExp("[,\"\r\n]")) || s.stripWhiteSpace() != s){ + s.prepend('\"'); + s.append('\"'); + } else if(s.isEmpty() && !s.isNull()){ + s = "\"\""; + } + } + return list.join(","); + + +} +QString SharpFormat::getTodoString( Todo* todo ) +{ + QStringList list; + list.append( QString::number( todo->zaurusId() ) ); + list.append( todo->categories().join(",") ); + + if ( todo->hasStartDate() ) { + list.append( dtToString( todo->dtStart()) ); + } else + list.append( QString() ); + + if ( todo->hasDueDate() ) { + QTime tim; + if ( todo->doesFloat()) { + list.append( dtToString( QDateTime(todo->dtDue().date(),QTime( 0,0,0 )), false)) ; + } else { + list.append( dtToString(todo->dtDue() ) ); + } + } else + list.append( QString() ); + + if ( todo->isCompleted() ) { + list.append( dtToString( todo->completed()) ); + list.append( "0" ); // yes 0 == completed + } else { + list.append( dtToString( todo->completed()) ); + list.append( "1" ); + } + list.append( QString::number( todo->priority() )); + if( ! todo->summary().isEmpty() ) + list.append( todo->summary() ); + else + list.append( "" ); + if (! todo->description().isEmpty() ) + list.append( todo->description() ); + else + list.append( "" ); + for(QStringList::Iterator it=list.begin(); + it!=list.end(); ++it){ + QString& s = (*it); + s.replace(QRegExp("\""), "\"\""); + if(s.contains(QRegExp("[,\"\r\n]")) || s.stripWhiteSpace() != s){ + s.prepend('\"'); + s.append('\"'); + } else if(s.isEmpty() && !s.isNull()){ + s = "\"\""; + } + } + return list.join(","); +} +QString SharpFormat::getPart( const QString & text, bool &ok, int &start ) +{ + //qDebug("start %d ", start); + + QString retval =""; + if ( text.at(start) == '"' ) { + if ( text.mid( start,2) == "\"\"" && !( text.mid( start+2,1) == "\"")) { + start = start +2; + if ( text.mid( start,1) == "," ) { + start += 1; + } + retval = ""; + if ( text.mid( start,1) == "\n" ) { + start += 1; + ok = false; + } + return retval; + } + int hk = start+1; + hk = text.find ('"',hk); + while ( text.at(hk+1) == '"' ) + hk = text.find ('"',hk+2); + retval = text.mid( start+1, hk-start-1); + start = hk+1; + retval.replace( QRegExp("\"\""), "\""); + if ( text.mid( start,1) == "," ) { + start += 1; + } + if ( text.mid( start,1) == "\n" ) { + start += 1; + ok = false; + } + //qDebug("retval***%s*** ",retval.latin1() ); + return retval; + + } else { + int nl = text.find ("\n",start); + int kom = text.find (',',start); + if ( kom < nl ) { + // qDebug("kom < nl %d ", kom); + retval = text.mid(start, kom-start); + start = kom+1; + return retval; + } else { + if ( nl == kom ) { + // qDebug(" nl == kom "); + start = 0; + ok = false; + return "0"; + } + // qDebug(" nl < kom ", nl); + retval = text.mid( start, nl-start); + ok = false; + start = nl+1; + return retval; + } + } +} +bool SharpFormat::fromString( Calendar *calendar, const QString & text) +{ + return false; +} +bool SharpFormat::fromString2Cal( Calendar *calendar,Calendar *existingCalendar, const QString & text, const QString & type) +{ + // qDebug("test %s ", text.latin1()); + QStringList templist; + QString tempString; + int start = 0; + int len = text.length(); + int end = text.find ("\n",start)+1; + bool ok = true; + start = end; + SharpParser handler( calendar ); + handler.setCategoriesList( mCategories ); + while ( start > 0 ) { + templist.clear(); + ok = true; + while ( ok ) { + tempString = getPart( text, ok, start ); + if ( start >= len || start == 0 ) { + start = 0; + ok = false; + } + if ( tempString.right(1) =="\n" ) + tempString = tempString.left( tempString.length()-1); + //if ( ok ) + templist.append( tempString ); + //qDebug("%d ---%s---", templist.count(),tempString.latin1() ); + } + handler.startElement( existingCalendar, templist, type ); + } + + return false; +} + +QString SharpFormat::toString( Calendar * ) +{ + return QString::null; +} diff --git a/libkcal/sharpformat.h b/libkcal/sharpformat.h new file mode 100644 index 0000000..0b13862 --- a/dev/null +++ b/libkcal/sharpformat.h @@ -0,0 +1,61 @@ +/* + This file is part of libkcal. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef SHARPFORMAT_H +#define SHARPAFORMAT_H + +#include <qstring.h> + +#include "scheduler.h" + +#include "calformat.h" + +namespace KCal { + +/** + This class implements the calendar format used by Sharp. +*/ +class SharpFormat : public QObject { + public: + /** Create new iCalendar format. */ + SharpFormat(); + virtual ~SharpFormat(); + + bool load( Calendar * ,Calendar *); + bool save( Calendar * ); + void setCategoriesList ( QStringList * cat ){ mCategories = cat; } + bool fromString2Cal( Calendar *, Calendar *, const QString & , const QString & ); + bool fromString( Calendar *, const QString & ); + QString toString( Calendar * ); + static ulong getCsum( const QStringList & ); + + private: + QString getEventString( Event* ); + QString getTodoString( Todo* ); + QString dtToString( const QDateTime& dt, bool useTZ = true ); + + QStringList *mCategories; + int getNumFromRecord( QString answer,Incidence* inc ) ; + QString getPart( const QString & text, bool &ok, int &start ); +}; + +} + +#endif diff --git a/libkcal/todo.cpp b/libkcal/todo.cpp new file mode 100644 index 0000000..0c1e3e4 --- a/dev/null +++ b/libkcal/todo.cpp @@ -0,0 +1,316 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +#include "todo.h" + +using namespace KCal; + +Todo::Todo(): Incidence() +{ +// mStatus = TENTATIVE; + + mHasDueDate = false; + setHasStartDate( false ); + mCompleted = getEvenTime(QDateTime::currentDateTime()); + mHasCompletedDate = false; + mPercentComplete = 0; +} + +Todo::Todo(const Todo &t) : Incidence(t) +{ + mDtDue = t.mDtDue; + mHasDueDate = t.mHasDueDate; + mCompleted = t.mCompleted; + mHasCompletedDate = t.mHasCompletedDate; + mPercentComplete = t.mPercentComplete; +} + +Todo::~Todo() +{ + +} + +Incidence *Todo::clone() +{ + return new Todo(*this); +} + + +bool KCal::operator==( const Todo& t1, const Todo& t2 ) +{ + + bool ret = operator==( (const Incidence&)t1, (const Incidence&)t2 ); + if ( ! ret ) + return false; + if ( t1.hasDueDate() == t2.hasDueDate() ) { + if ( t1.hasDueDate() ) { + if ( t1.doesFloat() == t2.doesFloat() ) { + if ( t1.doesFloat() ) { + if ( t1.dtDue().date() != t2.dtDue().date() ) + return false; + } else + if ( t1.dtDue() != t2.dtDue() ) + return false; + } else + return false;// float != + } + + } else + return false; + if ( t1.percentComplete() != t2.percentComplete() ) + return false; + if ( t1.isCompleted() ) { + if ( t1.hasCompletedDate() == t2.hasCompletedDate() ) { + if ( t1.hasCompletedDate() ) { + if ( t1.completed() != t2.completed() ) + return false; + } + + } else + return false; + } + return true; + +} + +void Todo::setDtDue(const QDateTime &dtDue) +{ + //int diffsecs = mDtDue.secsTo(dtDue); + + /*if (mReadOnly) return; + const QPtrList<Alarm>& alarms = alarms(); + for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next()) { + if (alarm->enabled()) { + alarm->setTime(alarm->time().addSecs(diffsecs)); + } + }*/ + mDtDue = getEvenTime(dtDue); + + //kdDebug(5800) << "setDtDue says date is " << mDtDue.toString() << endl; + + /*const QPtrList<Alarm>& alarms = alarms(); + for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next()) + alarm->setAlarmStart(mDtDue);*/ + + updated(); +} + +QDateTime Todo::dtDue() const +{ + return mDtDue; +} + +QString Todo::dtDueTimeStr() const +{ + return KGlobal::locale()->formatTime(mDtDue.time()); +} + +QString Todo::dtDueDateStr(bool shortfmt) const +{ + return KGlobal::locale()->formatDate(mDtDue.date(),shortfmt); +} + +QString Todo::dtDueStr(bool shortfmt) const +{ + return KGlobal::locale()->formatDateTime(mDtDue, shortfmt); +} + +bool Todo::hasDueDate() const +{ + return mHasDueDate; +} + +void Todo::setHasDueDate(bool f) +{ + if (mReadOnly) return; + mHasDueDate = f; + updated(); +} + + +#if 0 +void Todo::setStatus(const QString &statStr) +{ + if (mReadOnly) return; + QString ss(statStr.upper()); + + if (ss == "X-ACTION") + mStatus = NEEDS_ACTION; + else if (ss == "NEEDS ACTION") + mStatus = NEEDS_ACTION; + else if (ss == "ACCEPTED") + mStatus = ACCEPTED; + else if (ss == "SENT") + mStatus = SENT; + else if (ss == "TENTATIVE") + mStatus = TENTATIVE; + else if (ss == "CONFIRMED") + mStatus = CONFIRMED; + else if (ss == "DECLINED") + mStatus = DECLINED; + else if (ss == "COMPLETED") + mStatus = COMPLETED; + else if (ss == "DELEGATED") + mStatus = DELEGATED; + + updated(); +} + +void Todo::setStatus(int status) +{ + if (mReadOnly) return; + mStatus = status; + updated(); +} + +int Todo::status() const +{ + return mStatus; +} + +QString Todo::statusStr() const +{ + switch(mStatus) { + case NEEDS_ACTION: + return QString("NEEDS ACTION"); + break; + case ACCEPTED: + return QString("ACCEPTED"); + break; + case SENT: + return QString("SENT"); + break; + case TENTATIVE: + return QString("TENTATIVE"); + break; + case CONFIRMED: + return QString("CONFIRMED"); + break; + case DECLINED: + return QString("DECLINED"); + break; + case COMPLETED: + return QString("COMPLETED"); + break; + case DELEGATED: + return QString("DELEGATED"); + break; + } + return QString(""); +} +#endif + +bool Todo::isCompleted() const +{ + if (mPercentComplete == 100) return true; + else return false; +} + +void Todo::setCompleted(bool completed) +{ + if (completed) mPercentComplete = 100; + else mPercentComplete = 0; + updated(); +} + +QDateTime Todo::completed() const +{ + return mCompleted; +} + +QString Todo::completedStr() const +{ + return KGlobal::locale()->formatDateTime(mCompleted); +} + +void Todo::setCompleted(const QDateTime &completed) +{ + mHasCompletedDate = true; + mPercentComplete = 100; + mCompleted = getEvenTime(completed); + updated(); +} + +bool Todo::hasCompletedDate() const +{ + return mHasCompletedDate; +} + +int Todo::percentComplete() const +{ + return mPercentComplete; +} + +void Todo::setPercentComplete(int v) +{ + mPercentComplete = v; + updated(); +} +QDateTime Todo::getNextAlarmDateTime( bool * ok, int * offset ) const +{ + if ( isCompleted() || ! hasDueDate() || cancelled() ) { + *ok = false; + return QDateTime (); + } + QDateTime incidenceStart; + incidenceStart = dtDue(); + bool enabled = false; + Alarm* alarm; + int off; + QDateTime alarmStart = QDateTime::currentDateTime().addDays( 3650 );; + // if ( QDateTime::currentDateTime() > incidenceStart ){ +// *ok = false; +// return incidenceStart; +// } + for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) { + if (alarm->enabled()) { + if ( alarm->hasTime () ) { + if ( alarm->time() < alarmStart ) { + alarmStart = alarm->time(); + enabled = true; + off = alarmStart.secsTo( incidenceStart ); + } + + } else { + int secs = alarm->startOffset().asSeconds(); + if ( incidenceStart.addSecs( secs ) < alarmStart ) { + alarmStart = incidenceStart.addSecs( secs ); + enabled = true; + off = -secs; + } + } + } + } + if ( enabled ) { + if ( alarmStart > QDateTime::currentDateTime() ) { + *ok = true; + * offset = off; + return alarmStart; + } + } + *ok = false; + return QDateTime (); + +} + diff --git a/libkcal/todo.h b/libkcal/todo.h new file mode 100644 index 0000000..9aa92f8 --- a/dev/null +++ b/libkcal/todo.h @@ -0,0 +1,121 @@ +/* + This file is part of libkcal. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef TODO_H +#define TODO_H +// +// Todo component, representing a VTODO object +// + +#include "incidence.h" + +namespace KCal { + +/** + This class provides a Todo in the sense of RFC2445. +*/ +class Todo : public Incidence +{ + public: + Todo(); + Todo(const Todo &); + ~Todo(); + typedef ListBase<Todo> List; + QCString type() const { return "Todo"; } + + /** Return an exact copy of this todo. */ + Incidence *clone(); + QDateTime getNextAlarmDateTime( bool * ok, int * offset ) const; + + /** for setting the todo's due date/time with a QDateTime. */ + void setDtDue(const QDateTime &dtDue); + /** returns an event's Due date/time as a QDateTime. */ + QDateTime dtDue() const; + /** returns an event's due time as a string formatted according to the + users locale settings */ + QString dtDueTimeStr() const; + /** returns an event's due date as a string formatted according to the + users locale settings */ + QString dtDueDateStr(bool shortfmt=true) const; + /** returns an event's due date and time as a string formatted according + to the users locale settings */ + QString dtDueStr(bool shortfmt=true) const; + + /** returns TRUE or FALSE depending on whether the todo has a due date */ + bool hasDueDate() const; + /** sets the event's hasDueDate value. */ + void setHasDueDate(bool f); + + + /** sets the event's status to the string specified. The string + * must be a recognized value for the status field, i.e. a string + * equivalent of the possible status enumerations previously described. */ +// void setStatus(const QString &statStr); + /** sets the event's status to the value specified. See the enumeration + * above for possible values. */ +// void setStatus(int); + /** return the event's status. */ +// int status() const; + /** return the event's status in string format. */ +// QString statusStr() const; + + /** return, if this todo is completed */ + bool isCompleted() const; + /** set completed state of this todo */ + void setCompleted(bool); + + /** + Return how many percent of the task are completed. Returns a value + between 0 and 100. + */ + int percentComplete() const; + /** + Set how many percent of the task are completed. Valid values are in the + range from 0 to 100. + */ + void setPercentComplete(int); + + /** return date and time when todo was completed */ + QDateTime completed() const; + QString completedStr() const; + /** set date and time of completion */ + void setCompleted(const QDateTime &completed); + + /** Return true, if todo has a date associated with completion */ + bool hasCompletedDate() const; + + private: + bool accept(Visitor &v) { return v.visit(this); } + + QDateTime mDtDue; // due date of todo + + bool mHasDueDate; // if todo has associated due date + +// int mStatus; // confirmed/delegated/tentative/etc + + QDateTime mCompleted; + bool mHasCompletedDate; + + int mPercentComplete; +}; + + bool operator==( const Todo&, const Todo& ); +} + +#endif diff --git a/libkcal/vcaldrag.cpp b/libkcal/vcaldrag.cpp new file mode 100644 index 0000000..f01f332 --- a/dev/null +++ b/libkcal/vcaldrag.cpp @@ -0,0 +1,54 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "vcaldrag.h" + +#include "vcalformat.h" + +using namespace KCal; + +VCalDrag::VCalDrag( Calendar *cal, QWidget *parent, const char *name ) + : QStoredDrag( "text/x-vCalendar", parent, name ) +{ + VCalFormat format; + setEncodedData( format.toString( cal ).utf8() ); +} + +bool VCalDrag::canDecode( QMimeSource *me ) +{ + return me->provides( "text/x-vCalendar" ); +} + +bool VCalDrag::decode( QMimeSource *de, Calendar *cal ) +{ + bool success = false; + + QByteArray payload = de->encodedData( "text/x-vCalendar" ); + if ( payload.size() ) { + QString txt = QString::fromUtf8( payload.data() ); + + VCalFormat format; + success = format.fromString( cal, txt ); + } + + return success; +} + diff --git a/libkcal/vcaldrag.h b/libkcal/vcaldrag.h new file mode 100644 index 0000000..3048124 --- a/dev/null +++ b/libkcal/vcaldrag.h @@ -0,0 +1,47 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef VCALDRAG_H +#define VCALDRAG_H + +#include <qdragobject.h> + + +namespace KCal { + +class Calendar; + +/** vCalendar drag&drop class. */ +class VCalDrag : public QStoredDrag { + public: + /** Create a drag&drop object for vCalendar component \a vcal. */ + VCalDrag( Calendar *vcal, QWidget *parent = 0, const char *name = 0 ); + ~VCalDrag() {}; + + /** Return, if drag&drop object can be decode to vCalendar. */ + static bool canDecode( QMimeSource * ); + /** Decode drag&drop object to vCalendar component \a vcal. */ + static bool decode( QMimeSource *e, Calendar *cal ); +}; + +} + +#endif diff --git a/libkcal/vcalformat.cpp b/libkcal/vcalformat.cpp new file mode 100644 index 0000000..59030d5 --- a/dev/null +++ b/libkcal/vcalformat.cpp @@ -0,0 +1,1678 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brwon + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qapplication.h> +#include <qdatetime.h> +#include <qstring.h> +#include <qptrlist.h> +#include <qregexp.h> +#include <qclipboard.h> +#include <qdialog.h> +#include <qfile.h> + +#include <kdebug.h> +#include <kmessagebox.h> +#include <kiconloader.h> +#include <klocale.h> + +#include "vcc.h" +#include "vobject.h" + +#include "vcaldrag.h" +#include "calendar.h" + +#include "vcalformat.h" + +using namespace KCal; + +VCalFormat::VCalFormat() +{ +} + +VCalFormat::~VCalFormat() +{ +} + +bool VCalFormat::load(Calendar *calendar, const QString &fileName) +{ + mCalendar = calendar; + + clearException(); + + kdDebug(5800) << "VCalFormat::load() " << fileName << endl; + + VObject *vcal = 0; + + // this is not necessarily only 1 vcal. Could be many vcals, or include + // a vcard... + vcal = Parse_MIME_FromFileName(const_cast<char *>(QFile::encodeName(fileName).data())); + + if (!vcal) { + setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); + return FALSE; + } + + // any other top-level calendar stuff should be added/initialized here + + // put all vobjects into their proper places + populate(vcal); + + // clean up from vcal API stuff + cleanVObjects(vcal); + cleanStrTbl(); + + return true; +} + + +bool VCalFormat::save(Calendar *calendar, const QString &fileName) +{ + mCalendar = calendar; + + QString tmpStr; + VObject *vcal, *vo; + + kdDebug(5800) << "VCalFormat::save(): " << fileName << endl; + + vcal = newVObject(VCCalProp); + + // addPropValue(vcal,VCLocationProp, "0.0"); + addPropValue(vcal,VCProdIdProp, productId()); + tmpStr = mCalendar->getTimeZoneStr(); + //qDebug("mCalendar->getTimeZoneStr() %s",tmpStr.latin1() ); + addPropValue(vcal,VCTimeZoneProp, tmpStr.local8Bit()); + addPropValue(vcal,VCVersionProp, _VCAL_VERSION); + + // TODO STUFF + QPtrList<Todo> todoList = mCalendar->rawTodos(); + QPtrListIterator<Todo> qlt(todoList); + for (; qlt.current(); ++qlt) { + vo = eventToVTodo(qlt.current()); + addVObjectProp(vcal, vo); + } + + // EVENT STUFF + QPtrList<Event> events = mCalendar->rawEvents(); + Event *ev; + for(ev=events.first();ev;ev=events.next()) { + vo = eventToVEvent(ev); + addVObjectProp(vcal, vo); + } + + writeVObjectToFile(QFile::encodeName(fileName).data() ,vcal); + cleanVObjects(vcal); + cleanStrTbl(); + + if (QFile::exists(fileName)) { + kdDebug(5800) << "No error" << endl; + return true; + } else { + kdDebug(5800) << "Error" << endl; + return false; // error + } +} + +bool VCalFormat::fromString( Calendar *calendar, const QString &text ) +{ + // TODO: Factor out VCalFormat::fromString() + + QCString data = text.utf8(); + + if ( !data.size() ) return false; + + VObject *vcal = Parse_MIME( data.data(), data.size()); + if ( !vcal ) return false; + + VObjectIterator i; + VObject *curvo; + initPropIterator( &i, vcal ); + + // we only take the first object. TODO: parse all incidences. + do { + curvo = nextVObject( &i ); + } while ( strcmp( vObjectName( curvo ), VCEventProp ) && + strcmp( vObjectName( curvo ), VCTodoProp ) ); + + if ( strcmp( vObjectName( curvo ), VCEventProp ) == 0 ) { + Event *event = VEventToEvent( curvo ); + calendar->addEvent( event ); + } else { + kdDebug(5800) << "VCalFormat::fromString(): Unknown object type." << endl; + deleteVObject( vcal ); + return false; + } + + deleteVObject( vcal ); + + return true; +} + +QString VCalFormat::toString( Calendar *calendar ) +{ + // TODO: Factor out VCalFormat::asString() + + VObject *vcal = newVObject(VCCalProp); + + addPropValue( vcal, VCProdIdProp, CalFormat::productId() ); + QString tmpStr = mCalendar->getTimeZoneStr(); + addPropValue( vcal, VCTimeZoneProp, tmpStr.local8Bit() ); + addPropValue( vcal, VCVersionProp, _VCAL_VERSION ); + + // TODO: Use all data. + QPtrList<Event> events = calendar->events(); + Event *event = events.first(); + if ( !event ) return QString::null; + + VObject *vevent = eventToVEvent( event ); + + addVObjectProp( vcal, vevent ); + + char *buf = writeMemVObject( 0, 0, vcal ); + + QString result( buf ); + + cleanVObject( vcal ); + + return result; +} + +VObject *VCalFormat::eventToVTodo(const Todo *anEvent) +{ + VObject *vtodo; + QString tmpStr; + QStringList tmpStrList; + + vtodo = newVObject(VCTodoProp); + + // due date + if (anEvent->hasDueDate()) { + tmpStr = qDateTimeToISO(anEvent->dtDue(), + !anEvent->doesFloat()); + addPropValue(vtodo, VCDueProp, tmpStr.local8Bit()); + } + + // start date + if (anEvent->hasStartDate()) { + tmpStr = qDateTimeToISO(anEvent->dtStart(), + !anEvent->doesFloat()); + addPropValue(vtodo, VCDTstartProp, tmpStr.local8Bit()); + } + + // creation date + tmpStr = qDateTimeToISO(anEvent->created()); + addPropValue(vtodo, VCDCreatedProp, tmpStr.local8Bit()); + + // unique id + addPropValue(vtodo, VCUniqueStringProp, + anEvent->uid().local8Bit()); + + // revision + tmpStr.sprintf("%i", anEvent->revision()); + addPropValue(vtodo, VCSequenceProp, tmpStr.local8Bit()); + + // last modification date + tmpStr = qDateTimeToISO(anEvent->lastModified()); + addPropValue(vtodo, VCLastModifiedProp, tmpStr.local8Bit()); + + // organizer stuff + tmpStr = "MAILTO:" + anEvent->organizer(); + addPropValue(vtodo, ICOrganizerProp, tmpStr.local8Bit()); + + // attendees + if (anEvent->attendeeCount() != 0) { + QPtrList<Attendee> al = anEvent->attendees(); + QPtrListIterator<Attendee> ai(al); + Attendee *curAttendee; + + for (; ai.current(); ++ai) { + curAttendee = ai.current(); + if (!curAttendee->email().isEmpty() && + !curAttendee->name().isEmpty()) + tmpStr = "MAILTO:" + curAttendee->name() + " <" + + curAttendee->email() + ">"; + else if (curAttendee->name().isEmpty()) + tmpStr = "MAILTO: " + curAttendee->email(); + else if (curAttendee->email().isEmpty()) + tmpStr = "MAILTO: " + curAttendee->name(); + else if (curAttendee->name().isEmpty() && + curAttendee->email().isEmpty()) + kdDebug(5800) << "warning! this Event has an attendee w/o name or email!" << endl; + VObject *aProp = addPropValue(vtodo, VCAttendeeProp, tmpStr.local8Bit()); + addPropValue(aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE"); + addPropValue(aProp, VCStatusProp, writeStatus(curAttendee->status())); + } + } + + // description BL: + if (!anEvent->description().isEmpty()) { + VObject *d = addPropValue(vtodo, VCDescriptionProp, + anEvent->description().local8Bit()); + if (anEvent->description().find('\n') != -1) + addProp(d, VCQuotedPrintableProp); + } + + // summary + if (!anEvent->summary().isEmpty()) + addPropValue(vtodo, VCSummaryProp, anEvent->summary().local8Bit()); + + if (!anEvent->location().isEmpty()) + addPropValue(vtodo, VCLocationProp, anEvent->location().local8Bit()); + + // completed + // status + // backward compatibility, KOrganizer used to interpret only these two values + addPropValue(vtodo, VCStatusProp, anEvent->isCompleted() ? "COMPLETED" : + "NEEDS_ACTION"); + // completion date + if (anEvent->hasCompletedDate()) { + tmpStr = qDateTimeToISO(anEvent->completed()); + addPropValue(vtodo, VCCompletedProp, tmpStr.local8Bit()); + } + + // priority + tmpStr.sprintf("%i",anEvent->priority()); + addPropValue(vtodo, VCPriorityProp, tmpStr.local8Bit()); + + // related event + if (anEvent->relatedTo()) { + addPropValue(vtodo, VCRelatedToProp, + anEvent->relatedTo()->uid().local8Bit()); + } + + // categories + tmpStrList = anEvent->categories(); + tmpStr = ""; + QString catStr; + for ( QStringList::Iterator it = tmpStrList.begin(); + it != tmpStrList.end(); + ++it ) { + catStr = *it; + if (catStr[0] == ' ') + tmpStr += catStr.mid(1); + else + tmpStr += catStr; + // this must be a ';' character as the vCalendar specification requires! + // vcc.y has been hacked to translate the ';' to a ',' when the vcal is + // read in. + tmpStr += ";"; + } + if (!tmpStr.isEmpty()) { + tmpStr.truncate(tmpStr.length()-1); + addPropValue(vtodo, VCCategoriesProp, tmpStr.local8Bit()); + } + + // alarm stuff + kdDebug(5800) << "vcalformat::eventToVTodo was called" << endl; + QPtrList<Alarm> alarms = anEvent->alarms(); + Alarm* alarm; + for (alarm = alarms.first(); alarm; alarm = alarms.next()) { + if (alarm->enabled()) { + VObject *a = addProp(vtodo, VCDAlarmProp); + tmpStr = qDateTimeToISO(alarm->time()); + addPropValue(a, VCRunTimeProp, tmpStr.local8Bit()); + addPropValue(a, VCRepeatCountProp, "1"); + addPropValue(a, VCDisplayStringProp, "beep!"); + if (alarm->type() == Alarm::Audio) { + a = addProp(vtodo, VCAAlarmProp); + addPropValue(a, VCRunTimeProp, tmpStr.local8Bit()); + addPropValue(a, VCRepeatCountProp, "1"); + addPropValue(a, VCAudioContentProp, QFile::encodeName(alarm->audioFile())); + } + else if (alarm->type() == Alarm::Procedure) { + a = addProp(vtodo, VCPAlarmProp); + addPropValue(a, VCRunTimeProp, tmpStr.local8Bit()); + addPropValue(a, VCRepeatCountProp, "1"); + addPropValue(a, VCProcedureNameProp, QFile::encodeName(alarm->programFile())); + } + } + } + + if (anEvent->pilotId()) { + // pilot sync stuff + tmpStr.sprintf("%i",anEvent->pilotId()); + addPropValue(vtodo, KPilotIdProp, tmpStr.local8Bit()); + tmpStr.sprintf("%i",anEvent->syncStatus()); + addPropValue(vtodo, KPilotStatusProp, tmpStr.local8Bit()); + } + + return vtodo; +} + +VObject* VCalFormat::eventToVEvent(const Event *anEvent) +{ + VObject *vevent; + QString tmpStr; + QStringList tmpStrList; + + vevent = newVObject(VCEventProp); + + // start and end time + tmpStr = qDateTimeToISO(anEvent->dtStart(), + !anEvent->doesFloat()); + addPropValue(vevent, VCDTstartProp, tmpStr.local8Bit()); + + // events that have time associated but take up no time should + // not have both DTSTART and DTEND. + if (anEvent->dtStart() != anEvent->dtEnd()) { + tmpStr = qDateTimeToISO(anEvent->dtEnd(), + !anEvent->doesFloat()); + addPropValue(vevent, VCDTendProp, tmpStr.local8Bit()); + } + + // creation date + tmpStr = qDateTimeToISO(anEvent->created()); + addPropValue(vevent, VCDCreatedProp, tmpStr.local8Bit()); + + // unique id + addPropValue(vevent, VCUniqueStringProp, + anEvent->uid().local8Bit()); + + // revision + tmpStr.sprintf("%i", anEvent->revision()); + addPropValue(vevent, VCSequenceProp, tmpStr.local8Bit()); + + // last modification date + tmpStr = qDateTimeToISO(anEvent->lastModified()); + addPropValue(vevent, VCLastModifiedProp, tmpStr.local8Bit()); + + // attendee and organizer stuff + tmpStr = "MAILTO:" + anEvent->organizer(); + addPropValue(vevent, ICOrganizerProp, tmpStr.local8Bit()); + + if (anEvent->attendeeCount() != 0) { + QPtrList<Attendee> al = anEvent->attendees(); + QPtrListIterator<Attendee> ai(al); + Attendee *curAttendee; + + // TODO: Put this functionality into Attendee class + for (; ai.current(); ++ai) { + curAttendee = ai.current(); + if (!curAttendee->email().isEmpty() && + !curAttendee->name().isEmpty()) + tmpStr = "MAILTO:" + curAttendee->name() + " <" + + curAttendee->email() + ">"; + else if (curAttendee->name().isEmpty()) + tmpStr = "MAILTO: " + curAttendee->email(); + else if (curAttendee->email().isEmpty()) + tmpStr = "MAILTO: " + curAttendee->name(); + else if (curAttendee->name().isEmpty() && + curAttendee->email().isEmpty()) + kdDebug(5800) << "warning! this Event has an attendee w/o name or email!" << endl; + VObject *aProp = addPropValue(vevent, VCAttendeeProp, tmpStr.local8Bit()); + addPropValue(aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE");; + addPropValue(aProp, VCStatusProp, writeStatus(curAttendee->status())); + } + } + + // recurrence rule stuff + if (anEvent->recurrence()->doesRecur()) { + // some more variables + QPtrList<Recurrence::rMonthPos> tmpPositions; + QPtrList<int> tmpDays; + int *tmpDay; + Recurrence::rMonthPos *tmpPos; + QString tmpStr2; + int i; + + switch(anEvent->recurrence()->doesRecur()) { + case Recurrence::rDaily: + tmpStr.sprintf("D%i ",anEvent->recurrence()->frequency()); +// if (anEvent->rDuration > 0) +// tmpStr += "#"; + break; + case Recurrence::rWeekly: + tmpStr.sprintf("W%i ",anEvent->recurrence()->frequency()); + for (i = 0; i < 7; i++) { + if (anEvent->recurrence()->days().testBit(i)) + tmpStr += dayFromNum(i); + } + break; + case Recurrence::rMonthlyPos: + tmpStr.sprintf("MP%i ", anEvent->recurrence()->frequency()); + // write out all rMonthPos's + tmpPositions = anEvent->recurrence()->monthPositions(); + for (tmpPos = tmpPositions.first(); + tmpPos; + tmpPos = tmpPositions.next()) { + + tmpStr2.sprintf("%i", tmpPos->rPos); + if (tmpPos->negative) + tmpStr2 += "- "; + else + tmpStr2 += "+ "; + tmpStr += tmpStr2; + for (i = 0; i < 7; i++) { + if (tmpPos->rDays.testBit(i)) + tmpStr += dayFromNum(i); + } + } // loop for all rMonthPos's + break; + case Recurrence::rMonthlyDay: + tmpStr.sprintf("MD%i ", anEvent->recurrence()->frequency()); + // write out all rMonthDays; + tmpDays = anEvent->recurrence()->monthDays(); + for (tmpDay = tmpDays.first(); + tmpDay; + tmpDay = tmpDays.next()) { + tmpStr2.sprintf("%i ", *tmpDay); + tmpStr += tmpStr2; + } + break; + case Recurrence::rYearlyMonth: + tmpStr.sprintf("YM%i ", anEvent->recurrence()->frequency()); + // write out all the rYearNums; + tmpDays = anEvent->recurrence()->yearNums(); + for (tmpDay = tmpDays.first(); + tmpDay; + tmpDay = tmpDays.next()) { + tmpStr2.sprintf("%i ", *tmpDay); + tmpStr += tmpStr2; + } + break; + case Recurrence::rYearlyDay: + tmpStr.sprintf("YD%i ", anEvent->recurrence()->frequency()); + // write out all the rYearNums; + tmpDays = anEvent->recurrence()->yearNums(); + for (tmpDay = tmpDays.first(); + tmpDay; + tmpDay = tmpDays.next()) { + tmpStr2.sprintf("%i ", *tmpDay); + tmpStr += tmpStr2; + } + break; + default: + kdDebug(5800) << "ERROR, it should never get here in eventToVEvent!" << endl; + break; + } // switch + + if (anEvent->recurrence()->duration() > 0) { + tmpStr2.sprintf("#%i",anEvent->recurrence()->duration()); + tmpStr += tmpStr2; + } else if (anEvent->recurrence()->duration() == -1) { + tmpStr += "#0"; // defined as repeat forever + } else { + tmpStr += qDateTimeToISO(anEvent->recurrence()->endDate(), FALSE); + } + addPropValue(vevent,VCRRuleProp, tmpStr.local8Bit()); + + } // event repeats + + // exceptions to recurrence + DateList dateList = anEvent->exDates(); + DateList::ConstIterator it; + QString tmpStr2; + + for (it = dateList.begin(); it != dateList.end(); ++it) { + tmpStr = qDateToISO(*it) + ";"; + tmpStr2 += tmpStr; + } + if (!tmpStr2.isEmpty()) { + tmpStr2.truncate(tmpStr2.length()-1); + addPropValue(vevent, VCExDateProp, tmpStr2.local8Bit()); + } + + // description + if (!anEvent->description().isEmpty()) { + VObject *d = addPropValue(vevent, VCDescriptionProp, + anEvent->description().local8Bit()); + if (anEvent->description().find('\n') != -1) + addProp(d, VCQuotedPrintableProp); + } + + // summary + if (!anEvent->summary().isEmpty()) + addPropValue(vevent, VCSummaryProp, anEvent->summary().local8Bit()); + + if (!anEvent->location().isEmpty()) + addPropValue(vevent, VCLocationProp, anEvent->location().local8Bit()); + + // status +// TODO: define Event status +// addPropValue(vevent, VCStatusProp, anEvent->statusStr().local8Bit()); + + // secrecy + const char *text = 0; + switch (anEvent->secrecy()) { + case Incidence::SecrecyPublic: + text = "PUBLIC"; + break; + case Incidence::SecrecyPrivate: + text = "PRIVATE"; + break; + case Incidence::SecrecyConfidential: + text = "CONFIDENTIAL"; + break; + } + if (text) { + addPropValue(vevent, VCClassProp, text); + } + + // categories + tmpStrList = anEvent->categories(); + tmpStr = ""; + QString catStr; + for ( QStringList::Iterator it = tmpStrList.begin(); + it != tmpStrList.end(); + ++it ) { + catStr = *it; + if (catStr[0] == ' ') + tmpStr += catStr.mid(1); + else + tmpStr += catStr; + // this must be a ';' character as the vCalendar specification requires! + // vcc.y has been hacked to translate the ';' to a ',' when the vcal is + // read in. + tmpStr += ";"; + } + if (!tmpStr.isEmpty()) { + tmpStr.truncate(tmpStr.length()-1); + addPropValue(vevent, VCCategoriesProp, tmpStr.local8Bit()); + } + + // attachments + // TODO: handle binary attachments! + QPtrList<Attachment> attachments = anEvent->attachments(); + for ( Attachment *at = attachments.first(); at; at = attachments.next() ) + addPropValue(vevent, VCAttachProp, at->uri().local8Bit()); + + // resources + tmpStrList = anEvent->resources(); + tmpStr = tmpStrList.join(";"); + if (!tmpStr.isEmpty()) + addPropValue(vevent, VCResourcesProp, tmpStr.local8Bit()); + + // alarm stuff + QPtrList<Alarm> alarms = anEvent->alarms(); + Alarm* alarm; + for (alarm = alarms.first(); alarm; alarm = alarms.next()) { + if (alarm->enabled()) { + VObject *a = addProp(vevent, VCDAlarmProp); + tmpStr = qDateTimeToISO(alarm->time()); + addPropValue(a, VCRunTimeProp, tmpStr.local8Bit()); + addPropValue(a, VCRepeatCountProp, "1"); + addPropValue(a, VCDisplayStringProp, "beep!"); + if (alarm->type() == Alarm::Audio) { + a = addProp(vevent, VCAAlarmProp); + addPropValue(a, VCRunTimeProp, tmpStr.local8Bit()); + addPropValue(a, VCRepeatCountProp, "1"); + addPropValue(a, VCAudioContentProp, QFile::encodeName(alarm->audioFile())); + } + if (alarm->type() == Alarm::Procedure) { + a = addProp(vevent, VCPAlarmProp); + addPropValue(a, VCRunTimeProp, tmpStr.local8Bit()); + addPropValue(a, VCRepeatCountProp, "1"); + addPropValue(a, VCProcedureNameProp, QFile::encodeName(alarm->programFile())); + } + } + } + + // priority + tmpStr.sprintf("%i",anEvent->priority()); + addPropValue(vevent, VCPriorityProp, tmpStr.local8Bit()); + + // transparency + tmpStr.sprintf("%i",anEvent->transparency()); + addPropValue(vevent, VCTranspProp, tmpStr.local8Bit()); + + // related event + if (anEvent->relatedTo()) { + addPropValue(vevent, VCRelatedToProp, + anEvent->relatedTo()->uid().local8Bit()); + } + + if (anEvent->pilotId()) { + // pilot sync stuff + tmpStr.sprintf("%i",anEvent->pilotId()); + addPropValue(vevent, KPilotIdProp, tmpStr.local8Bit()); + tmpStr.sprintf("%i",anEvent->syncStatus()); + addPropValue(vevent, KPilotStatusProp, tmpStr.local8Bit()); + } + + return vevent; +} + +Todo *VCalFormat::VTodoToEvent(VObject *vtodo) +{ + VObject *vo; + VObjectIterator voi; + char *s; + + Todo *anEvent = new Todo; + + // creation date + if ((vo = isAPropertyOf(vtodo, VCDCreatedProp)) != 0) { + anEvent->setCreated(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + + // unique id + vo = isAPropertyOf(vtodo, VCUniqueStringProp); + // while the UID property is preferred, it is not required. We'll use the + // default Event UID if none is given. + if (vo) { + anEvent->setUid(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + } + + // last modification date + if ((vo = isAPropertyOf(vtodo, VCLastModifiedProp)) != 0) { + anEvent->setLastModified(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + else + anEvent->setLastModified(QDateTime(QDate::currentDate(), + QTime::currentTime())); + + // organizer + // if our extension property for the event's ORGANIZER exists, add it. + if ((vo = isAPropertyOf(vtodo, ICOrganizerProp)) != 0) { + anEvent->setOrganizer(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + } else { + anEvent->setOrganizer(mCalendar->getEmail()); + } + + // attendees. + initPropIterator(&voi, vtodo); + while (moreIteration(&voi)) { + vo = nextVObject(&voi); + if (strcmp(vObjectName(vo), VCAttendeeProp) == 0) { + Attendee *a; + VObject *vp; + s = fakeCString(vObjectUStringZValue(vo)); + QString tmpStr = QString::fromLocal8Bit(s); + deleteStr(s); + tmpStr = tmpStr.simplifyWhiteSpace(); + int emailPos1, emailPos2; + if ((emailPos1 = tmpStr.find('<')) > 0) { + // both email address and name + emailPos2 = tmpStr.findRev('>'); + a = new Attendee(tmpStr.left(emailPos1 - 1), + tmpStr.mid(emailPos1 + 1, + emailPos2 - (emailPos1 + 1))); + } else if (tmpStr.find('@') > 0) { + // just an email address + a = new Attendee(0, tmpStr); + } else { + // just a name + QString email = tmpStr.replace( QRegExp(" "), "." ); + a = new Attendee(tmpStr,email); + } + + // is there an RSVP property? + if ((vp = isAPropertyOf(vo, VCRSVPProp)) != 0) + a->setRSVP(vObjectStringZValue(vp)); + // is there a status property? + if ((vp = isAPropertyOf(vo, VCStatusProp)) != 0) + a->setStatus(readStatus(vObjectStringZValue(vp))); + // add the attendee + anEvent->addAttendee(a); + } + } + + // description for todo + if ((vo = isAPropertyOf(vtodo, VCDescriptionProp)) != 0) { + s = fakeCString(vObjectUStringZValue(vo)); + anEvent->setDescription(QString::fromLocal8Bit(s)); + deleteStr(s); + } + + // summary + if ((vo = isAPropertyOf(vtodo, VCSummaryProp))) { + s = fakeCString(vObjectUStringZValue(vo)); + anEvent->setSummary(QString::fromLocal8Bit(s)); + deleteStr(s); + } + if ((vo = isAPropertyOf(vtodo, VCLocationProp))) { + s = fakeCString(vObjectUStringZValue(vo)); + anEvent->setLocation(QString::fromLocal8Bit(s)); + deleteStr(s); + } + + + // completed + // was: status + if ((vo = isAPropertyOf(vtodo, VCStatusProp)) != 0) { + s = fakeCString(vObjectUStringZValue(vo)); + if (strcmp(s,"COMPLETED") == 0) { + anEvent->setCompleted(true); + } else { + anEvent->setCompleted(false); + } + deleteStr(s); + } + else + anEvent->setCompleted(false); + + // completion date + if ((vo = isAPropertyOf(vtodo, VCCompletedProp)) != 0) { + anEvent->setCompleted(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + + // priority + if ((vo = isAPropertyOf(vtodo, VCPriorityProp))) { + anEvent->setPriority(atoi(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + + // due date + if ((vo = isAPropertyOf(vtodo, VCDueProp)) != 0) { + anEvent->setDtDue(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + anEvent->setHasDueDate(true); + } else { + anEvent->setHasDueDate(false); + } + + // start time + if ((vo = isAPropertyOf(vtodo, VCDTstartProp)) != 0) { + anEvent->setDtStart(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo)))); + // kdDebug(5800) << "s is " << // s << ", ISO is " << ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))).toString() << endl; + deleteStr(s); + anEvent->setHasStartDate(true); + } else { + anEvent->setHasStartDate(false); + } + + /* alarm stuff */ + //kdDebug(5800) << "vcalformat::VTodoToEvent called" << endl; + if ((vo = isAPropertyOf(vtodo, VCDAlarmProp))) { + Alarm* alarm = anEvent->newAlarm(); + VObject *a; + if ((a = isAPropertyOf(vo, VCRunTimeProp))) { + alarm->setTime(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(a)))); + deleteStr(s); + } + alarm->setEnabled(true); + if ((vo = isAPropertyOf(vtodo, VCPAlarmProp))) { + if ((a = isAPropertyOf(vo, VCProcedureNameProp))) { + s = fakeCString(vObjectUStringZValue(a)); + alarm->setProcedureAlarm(QFile::decodeName(s)); + deleteStr(s); + } + } + if ((vo = isAPropertyOf(vtodo, VCAAlarmProp))) { + if ((a = isAPropertyOf(vo, VCAudioContentProp))) { + s = fakeCString(vObjectUStringZValue(a)); + alarm->setAudioAlarm(QFile::decodeName(s)); + deleteStr(s); + } + } + } + + // related todo + if ((vo = isAPropertyOf(vtodo, VCRelatedToProp)) != 0) { + anEvent->setRelatedToUid(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + mTodosRelate.append(anEvent); + } + + // categories + QStringList tmpStrList; + int index1 = 0; + int index2 = 0; + if ((vo = isAPropertyOf(vtodo, VCCategoriesProp)) != 0) { + s = fakeCString(vObjectUStringZValue(vo)); + QString categories = QString::fromLocal8Bit(s); + deleteStr(s); + //const char* category; + QString category; + while ((index2 = categories.find(',', index1)) != -1) { + //category = (const char *) categories.mid(index1, (index2 - index1)); + category = categories.mid(index1, (index2 - index1)); + tmpStrList.append(category); + index1 = index2+1; + } + // get last category + category = categories.mid(index1, (categories.length()-index1)); + tmpStrList.append(category); + anEvent->setCategories(tmpStrList); + } + + /* PILOT SYNC STUFF */ + if ((vo = isAPropertyOf(vtodo, KPilotIdProp))) { + anEvent->setPilotId(atoi(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + else + anEvent->setPilotId(0); + + if ((vo = isAPropertyOf(vtodo, KPilotStatusProp))) { + anEvent->setSyncStatus(atoi(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + else + anEvent->setSyncStatus(Event::SYNCMOD); + + return anEvent; +} + +Event* VCalFormat::VEventToEvent(VObject *vevent) +{ + VObject *vo; + VObjectIterator voi; + char *s; + + Event *anEvent = new Event; + + // creation date + if ((vo = isAPropertyOf(vevent, VCDCreatedProp)) != 0) { + anEvent->setCreated(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + + // unique id + vo = isAPropertyOf(vevent, VCUniqueStringProp); + // while the UID property is preferred, it is not required. We'll use the + // default Event UID if none is given. + if (vo) { + anEvent->setUid(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + } + + // revision + // again NSCAL doesn't give us much to work with, so we improvise... + if ((vo = isAPropertyOf(vevent, VCSequenceProp)) != 0) { + anEvent->setRevision(atoi(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + else + anEvent->setRevision(0); + + // last modification date + if ((vo = isAPropertyOf(vevent, VCLastModifiedProp)) != 0) { + anEvent->setLastModified(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + else + anEvent->setLastModified(QDateTime(QDate::currentDate(), + QTime::currentTime())); + + // organizer + // if our extension property for the event's ORGANIZER exists, add it. + if ((vo = isAPropertyOf(vevent, ICOrganizerProp)) != 0) { + anEvent->setOrganizer(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + } else { + anEvent->setOrganizer(mCalendar->getEmail()); + } + + // deal with attendees. + initPropIterator(&voi, vevent); + while (moreIteration(&voi)) { + vo = nextVObject(&voi); + if (strcmp(vObjectName(vo), VCAttendeeProp) == 0) { + Attendee *a; + VObject *vp; + s = fakeCString(vObjectUStringZValue(vo)); + QString tmpStr = QString::fromLocal8Bit(s); + deleteStr(s); + tmpStr = tmpStr.simplifyWhiteSpace(); + int emailPos1, emailPos2; + if ((emailPos1 = tmpStr.find('<')) > 0) { + // both email address and name + emailPos2 = tmpStr.findRev('>'); + a = new Attendee(tmpStr.left(emailPos1 - 1), + tmpStr.mid(emailPos1 + 1, + emailPos2 - (emailPos1 + 1))); + } else if (tmpStr.find('@') > 0) { + // just an email address + a = new Attendee(0, tmpStr); + } else { + // just a name + QString email = tmpStr.replace( QRegExp(" "), "." ); + a = new Attendee(tmpStr,email); + } + + // is there an RSVP property? + if ((vp = isAPropertyOf(vo, VCRSVPProp)) != 0) + a->setRSVP(vObjectStringZValue(vp)); + // is there a status property? + if ((vp = isAPropertyOf(vo, VCStatusProp)) != 0) + a->setStatus(readStatus(vObjectStringZValue(vp))); + // add the attendee + anEvent->addAttendee(a); + } + } + + // This isn't strictly true. An event that doesn't have a start time + // or an end time doesn't "float", it has an anchor in time but it doesn't + // "take up" any time. + /*if ((isAPropertyOf(vevent, VCDTstartProp) == 0) || + (isAPropertyOf(vevent, VCDTendProp) == 0)) { + anEvent->setFloats(TRUE); + } else { + }*/ + + anEvent->setFloats(FALSE); + + // start time + if ((vo = isAPropertyOf(vevent, VCDTstartProp)) != 0) { + anEvent->setDtStart(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo)))); + // kdDebug(5800) << "s is " << // s << ", ISO is " << ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))).toString() << endl; + deleteStr(s); + if (anEvent->dtStart().time().isNull()) + anEvent->setFloats(TRUE); + } + + // stop time + if ((vo = isAPropertyOf(vevent, VCDTendProp)) != 0) { + anEvent->setDtEnd(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + if (anEvent->dtEnd().time().isNull()) + anEvent->setFloats(TRUE); + } + + // at this point, there should be at least a start or end time. + // fix up for events that take up no time but have a time associated + if (!(vo = isAPropertyOf(vevent, VCDTstartProp))) + anEvent->setDtStart(anEvent->dtEnd()); + if (!(vo = isAPropertyOf(vevent, VCDTendProp))) + anEvent->setDtEnd(anEvent->dtStart()); + + /////////////////////////////////////////////////////////////////////////// + + // repeat stuff + if ((vo = isAPropertyOf(vevent, VCRRuleProp)) != 0) { + QString tmpStr = (s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + tmpStr.simplifyWhiteSpace(); + tmpStr = tmpStr.upper(); + + /********************************* DAILY ******************************/ + if (tmpStr.left(1) == "D") { + int index = tmpStr.find(' '); + int rFreq = tmpStr.mid(1, (index-1)).toInt(); + index = tmpStr.findRev(' ') + 1; // advance to last field + if (tmpStr.mid(index,1) == "#") index++; + if (tmpStr.find('T', index) != -1) { + QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date(); + anEvent->recurrence()->setDaily(rFreq, rEndDate); + } else { + int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt(); + if (rDuration == 0) // VEvents set this to 0 forever, we use -1 + anEvent->recurrence()->setDaily(rFreq, -1); + else + anEvent->recurrence()->setDaily(rFreq, rDuration); + } + } + /********************************* WEEKLY ******************************/ + else if (tmpStr.left(1) == "W") { + int index = tmpStr.find(' '); + int last = tmpStr.findRev(' ') + 1; + int rFreq = tmpStr.mid(1, (index-1)).toInt(); + index += 1; // advance to beginning of stuff after freq + QBitArray qba(7); + QString dayStr; + if( index == last ) { + // e.g. W1 #0 + qba.setBit(anEvent->dtStart().date().dayOfWeek() - 1); + } + else { + // e.g. W1 SU #0 + while (index < last) { + dayStr = tmpStr.mid(index, 3); + int dayNum = numFromDay(dayStr); + qba.setBit(dayNum); + index += 3; // advance to next day, or possibly "#" + } + } + index = last; if (tmpStr.mid(index,1) == "#") index++; + if (tmpStr.find('T', index) != -1) { + QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date(); + anEvent->recurrence()->setWeekly(rFreq, qba, rEndDate); + } else { + int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt(); + if (rDuration == 0) + anEvent->recurrence()->setWeekly(rFreq, qba, -1); + else + anEvent->recurrence()->setWeekly(rFreq, qba, rDuration); + } + } + /**************************** MONTHLY-BY-POS ***************************/ + else if (tmpStr.left(2) == "MP") { + int index = tmpStr.find(' '); + int last = tmpStr.findRev(' ') + 1; + int rFreq = tmpStr.mid(2, (index-1)).toInt(); + index += 1; // advance to beginning of stuff after freq + QBitArray qba(7); + short tmpPos; + if( index == last ) { + // e.g. MP1 #0 + tmpPos = anEvent->dtStart().date().day()/7 + 1; + if( tmpPos == 5 ) + tmpPos = -1; + qba.setBit(anEvent->dtStart().date().dayOfWeek() - 1); + anEvent->recurrence()->addMonthlyPos(tmpPos, qba); + } + else { + // e.g. MP1 1+ SU #0 + while (index < last) { + tmpPos = tmpStr.mid(index,1).toShort(); + index += 1; + if (tmpStr.mid(index,1) == "-") + // convert tmpPos to negative + tmpPos = 0 - tmpPos; + index += 2; // advance to day(s) + while (numFromDay(tmpStr.mid(index,3)) >= 0) { + int dayNum = numFromDay(tmpStr.mid(index,3)); + qba.setBit(dayNum); + index += 3; // advance to next day, or possibly pos or "#" + } + anEvent->recurrence()->addMonthlyPos(tmpPos, qba); + qba.detach(); + qba.fill(FALSE); // clear out + } // while != "#" + } + index = last; if (tmpStr.mid(index,1) == "#") index++; + if (tmpStr.find('T', index) != -1) { + QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length() - + index))).date(); + anEvent->recurrence()->setMonthly(Recurrence::rMonthlyPos, rFreq, rEndDate); + } else { + int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt(); + if (rDuration == 0) + anEvent->recurrence()->setMonthly(Recurrence::rMonthlyPos, rFreq, -1); + else + anEvent->recurrence()->setMonthly(Recurrence::rMonthlyPos, rFreq, rDuration); + } + } + + /**************************** MONTHLY-BY-DAY ***************************/ + else if (tmpStr.left(2) == "MD") { + int index = tmpStr.find(' '); + int last = tmpStr.findRev(' ') + 1; + int rFreq = tmpStr.mid(2, (index-1)).toInt(); + index += 1; + short tmpDay; + if( index == last ) { + // e.g. MD1 #0 + tmpDay = anEvent->dtStart().date().day(); + anEvent->recurrence()->addMonthlyDay(tmpDay); + } + else { + // e.g. MD1 3 #0 + while (index < last) { + int index2 = tmpStr.find(' ', index); + tmpDay = tmpStr.mid(index, (index2-index)).toShort(); + index = index2-1; + if (tmpStr.mid(index, 1) == "-") + tmpDay = 0 - tmpDay; + index += 2; // advance the index; + anEvent->recurrence()->addMonthlyDay(tmpDay); + } // while != # + } + index = last; if (tmpStr.mid(index,1) == "#") index++; + if (tmpStr.find('T', index) != -1) { + QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date(); + anEvent->recurrence()->setMonthly(Recurrence::rMonthlyDay, rFreq, rEndDate); + } else { + int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt(); + if (rDuration == 0) + anEvent->recurrence()->setMonthly(Recurrence::rMonthlyDay, rFreq, -1); + else + anEvent->recurrence()->setMonthly(Recurrence::rMonthlyDay, rFreq, rDuration); + } + } + + /*********************** YEARLY-BY-MONTH *******************************/ + else if (tmpStr.left(2) == "YM") { + int index = tmpStr.find(' '); + int last = tmpStr.findRev(' ') + 1; + int rFreq = tmpStr.mid(2, (index-1)).toInt(); + index += 1; + short tmpMonth; + if( index == last ) { + // e.g. YM1 #0 + tmpMonth = anEvent->dtStart().date().month(); + anEvent->recurrence()->addYearlyNum(tmpMonth); + } + else { + // e.g. YM1 3 #0 + while (index < last) { + int index2 = tmpStr.find(' ', index); + tmpMonth = tmpStr.mid(index, (index2-index)).toShort(); + index = index2+1; + anEvent->recurrence()->addYearlyNum(tmpMonth); + } // while != # + } + index = last; if (tmpStr.mid(index,1) == "#") index++; + if (tmpStr.find('T', index) != -1) { + QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date(); + anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, rEndDate); + } else { + int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt(); + if (rDuration == 0) + anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, -1); + else + anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, rDuration); + } + } + + /*********************** YEARLY-BY-DAY *********************************/ + else if (tmpStr.left(2) == "YD") { + int index = tmpStr.find(' '); + int last = tmpStr.findRev(' ') + 1; + int rFreq = tmpStr.mid(2, (index-1)).toInt(); + index += 1; + short tmpDay; + if( index == last ) { + // e.g. YD1 #0 + tmpDay = anEvent->dtStart().date().dayOfYear(); + anEvent->recurrence()->addYearlyNum(tmpDay); + } + else { + // e.g. YD1 123 #0 + while (index < last) { + int index2 = tmpStr.find(' ', index); + tmpDay = tmpStr.mid(index, (index2-index)).toShort(); + index = index2+1; + anEvent->recurrence()->addYearlyNum(tmpDay); + } // while != # + } + index = last; if (tmpStr.mid(index,1) == "#") index++; + if (tmpStr.find('T', index) != -1) { + QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date(); + anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, rEndDate); + } else { + int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt(); + if (rDuration == 0) + anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, -1); + else + anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, rDuration); + } + } else { + kdDebug(5800) << "we don't understand this type of recurrence!" << endl; + } // if + } // repeats + + + // recurrence exceptions + if ((vo = isAPropertyOf(vevent, VCExDateProp)) != 0) { + s = fakeCString(vObjectUStringZValue(vo)); + QStringList exDates = QStringList::split(",",s); + QStringList::ConstIterator it; + for(it = exDates.begin(); it != exDates.end(); ++it ) { + anEvent->addExDate(ISOToQDate(*it)); + } + deleteStr(s); + } + + // summary + if ((vo = isAPropertyOf(vevent, VCSummaryProp))) { + s = fakeCString(vObjectUStringZValue(vo)); + anEvent->setSummary(QString::fromLocal8Bit(s)); + deleteStr(s); + } + if ((vo = isAPropertyOf(vevent, VCLocationProp))) { + s = fakeCString(vObjectUStringZValue(vo)); + anEvent->setLocation(QString::fromLocal8Bit(s)); + deleteStr(s); + } + + // description + if ((vo = isAPropertyOf(vevent, VCDescriptionProp)) != 0) { + s = fakeCString(vObjectUStringZValue(vo)); + if (!anEvent->description().isEmpty()) { + anEvent->setDescription(anEvent->description() + "\n" + + QString::fromLocal8Bit(s)); + } else { + anEvent->setDescription(QString::fromLocal8Bit(s)); + } + deleteStr(s); + } + + // some stupid vCal exporters ignore the standard and use Description + // instead of Summary for the default field. Correct for this. + if (anEvent->summary().isEmpty() && + !(anEvent->description().isEmpty())) { + QString tmpStr = anEvent->description().simplifyWhiteSpace(); + anEvent->setDescription(""); + anEvent->setSummary(tmpStr); + } + +#if 0 + // status + if ((vo = isAPropertyOf(vevent, VCStatusProp)) != 0) { + QString tmpStr(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); +// TODO: Define Event status +// anEvent->setStatus(tmpStr); + } + else +// anEvent->setStatus("NEEDS ACTION"); +#endif + + // secrecy + int secrecy = Incidence::SecrecyPublic; + if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) { + s = fakeCString(vObjectUStringZValue(vo)); + if (strcmp(s,"PRIVATE") == 0) { + secrecy = Incidence::SecrecyPrivate; + } else if (strcmp(s,"CONFIDENTIAL") == 0) { + secrecy = Incidence::SecrecyConfidential; + } + deleteStr(s); + } + anEvent->setSecrecy(secrecy); + + // categories + QStringList tmpStrList; + int index1 = 0; + int index2 = 0; + if ((vo = isAPropertyOf(vevent, VCCategoriesProp)) != 0) { + s = fakeCString(vObjectUStringZValue(vo)); + QString categories = QString::fromLocal8Bit(s); + deleteStr(s); + //const char* category; + QString category; + while ((index2 = categories.find(',', index1)) != -1) { + //category = (const char *) categories.mid(index1, (index2 - index1)); + category = categories.mid(index1, (index2 - index1)); + tmpStrList.append(category); + index1 = index2+1; + } + // get last category + category = categories.mid(index1, (categories.length()-index1)); + tmpStrList.append(category); + anEvent->setCategories(tmpStrList); + } + + // attachments + tmpStrList.clear(); + initPropIterator(&voi, vevent); + while (moreIteration(&voi)) { + vo = nextVObject(&voi); + if (strcmp(vObjectName(vo), VCAttachProp) == 0) { + s = fakeCString(vObjectUStringZValue(vo)); + anEvent->addAttachment(new Attachment(QString(s))); + deleteStr(s); + } + } + + // resources + if ((vo = isAPropertyOf(vevent, VCResourcesProp)) != 0) { + QString resources = (s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + tmpStrList.clear(); + index1 = 0; + index2 = 0; + QString resource; + while ((index2 = resources.find(';', index1)) != -1) { + resource = resources.mid(index1, (index2 - index1)); + tmpStrList.append(resource); + index1 = index2; + } + anEvent->setResources(tmpStrList); + } + + /* alarm stuff */ + if ((vo = isAPropertyOf(vevent, VCDAlarmProp))) { + Alarm* alarm = anEvent->newAlarm(); + VObject *a; + if ((a = isAPropertyOf(vo, VCRunTimeProp))) { + alarm->setTime(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(a)))); + deleteStr(s); + } + alarm->setEnabled(true); + if ((vo = isAPropertyOf(vevent, VCPAlarmProp))) { + if ((a = isAPropertyOf(vo, VCProcedureNameProp))) { + s = fakeCString(vObjectUStringZValue(a)); + alarm->setProcedureAlarm(QFile::decodeName(s)); + deleteStr(s); + } + } + if ((vo = isAPropertyOf(vevent, VCAAlarmProp))) { + if ((a = isAPropertyOf(vo, VCAudioContentProp))) { + s = fakeCString(vObjectUStringZValue(a)); + alarm->setAudioAlarm(QFile::decodeName(s)); + deleteStr(s); + } + } + } + + // priority + if ((vo = isAPropertyOf(vevent, VCPriorityProp))) { + anEvent->setPriority(atoi(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + + // transparency + if ((vo = isAPropertyOf(vevent, VCTranspProp)) != 0) { + int i = atoi(s = fakeCString(vObjectUStringZValue(vo))); + anEvent->setTransparency( i == 1 ? Event::Transparent : Event::Opaque ); + deleteStr(s); + } + + // related event + if ((vo = isAPropertyOf(vevent, VCRelatedToProp)) != 0) { + anEvent->setRelatedToUid(s = fakeCString(vObjectUStringZValue(vo))); + deleteStr(s); + mEventsRelate.append(anEvent); + } + + /* PILOT SYNC STUFF */ + if ((vo = isAPropertyOf(vevent, KPilotIdProp))) { + anEvent->setPilotId(atoi(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + else + anEvent->setPilotId(0); + + if ((vo = isAPropertyOf(vevent, KPilotStatusProp))) { + anEvent->setSyncStatus(atoi(s = fakeCString(vObjectUStringZValue(vo)))); + deleteStr(s); + } + else + anEvent->setSyncStatus(Event::SYNCMOD); + + return anEvent; +} + + +QString VCalFormat::qDateToISO(const QDate &qd) +{ + QString tmpStr; + + ASSERT(qd.isValid()); + + tmpStr.sprintf("%.2d%.2d%.2d", + qd.year(), qd.month(), qd.day()); + return tmpStr; + +} + +QString VCalFormat::qDateTimeToISO(const QDateTime &qdt, bool zulu) +{ + QString tmpStr; + + ASSERT(qdt.date().isValid()); + ASSERT(qdt.time().isValid()); + if (zulu) { + QDateTime tmpDT(qdt); + tmpDT = tmpDT.addSecs(60*(-mCalendar->getTimeZone())); // correct to GMT. + tmpStr.sprintf("%.2d%.2d%.2dT%.2d%.2d%.2dZ", + tmpDT.date().year(), tmpDT.date().month(), + tmpDT.date().day(), tmpDT.time().hour(), + tmpDT.time().minute(), tmpDT.time().second()); + } else { + tmpStr.sprintf("%.2d%.2d%.2dT%.2d%.2d%.2d", + qdt.date().year(), qdt.date().month(), + qdt.date().day(), qdt.time().hour(), + qdt.time().minute(), qdt.time().second()); + } + return tmpStr; +} + +QDateTime VCalFormat::ISOToQDateTime(const QString & dtStr) +{ + QDate tmpDate; + QTime tmpTime; + QString tmpStr; + int year, month, day, hour, minute, second; + + tmpStr = dtStr; + year = tmpStr.left(4).toInt(); + month = tmpStr.mid(4,2).toInt(); + day = tmpStr.mid(6,2).toInt(); + hour = tmpStr.mid(9,2).toInt(); + minute = tmpStr.mid(11,2).toInt(); + second = tmpStr.mid(13,2).toInt(); + tmpDate.setYMD(year, month, day); + tmpTime.setHMS(hour, minute, second); + + ASSERT(tmpDate.isValid()); + ASSERT(tmpTime.isValid()); + QDateTime tmpDT(tmpDate, tmpTime); + // correct for GMT if string is in Zulu format + if (dtStr.at(dtStr.length()-1) == 'Z') + tmpDT = tmpDT.addSecs(60*mCalendar->getTimeZone()); + return tmpDT; +} + +QDate VCalFormat::ISOToQDate(const QString &dateStr) +{ + int year, month, day; + + year = dateStr.left(4).toInt(); + month = dateStr.mid(4,2).toInt(); + day = dateStr.mid(6,2).toInt(); + + return(QDate(year, month, day)); +} + +// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc. +// and break it down from it's tree-like format into the dictionary format +// that is used internally in the VCalFormat. +void VCalFormat::populate(VObject *vcal) +{ + // this function will populate the caldict dictionary and other event + // lists. It turns vevents into Events and then inserts them. + + VObjectIterator i; + VObject *curVO, *curVOProp; + Event *anEvent; + + if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) { + char *methodType = 0; + methodType = fakeCString(vObjectUStringZValue(curVO)); + kdDebug() << "This calendar is an iTIP transaction of type '" + << methodType << "'" << endl; + delete methodType; + } + + // warn the user that we might have trouble reading non-known calendar. + if ((curVO = isAPropertyOf(vcal, VCProdIdProp)) != 0) { + char *s = fakeCString(vObjectUStringZValue(curVO)); + if (strcmp(productId().local8Bit(), s) != 0) + kdDebug() << "This vCalendar file was not created by KOrganizer " + "or any other product we support. Loading anyway..." << endl; + mLoadedProductId = s; + deleteStr(s); + } + + // warn the user we might have trouble reading this unknown version. + if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) { + char *s = fakeCString(vObjectUStringZValue(curVO)); + if (strcmp(_VCAL_VERSION, s) != 0) + kdDebug() << "This vCalendar file has version " << s + << "We only support " << _VCAL_VERSION << endl; + deleteStr(s); + } + + // set the time zone + if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) { + char *s = fakeCString(vObjectUStringZValue(curVO)); + mCalendar->setTimeZone(s); + deleteStr(s); + } + + + // Store all events with a relatedTo property in a list for post-processing + mEventsRelate.clear(); + mTodosRelate.clear(); + + initPropIterator(&i, vcal); + + // go through all the vobjects in the vcal + while (moreIteration(&i)) { + curVO = nextVObject(&i); + + /************************************************************************/ + + // now, check to see that the object is an event or todo. + if (strcmp(vObjectName(curVO), VCEventProp) == 0) { + + if ((curVOProp = isAPropertyOf(curVO, KPilotStatusProp)) != 0) { + char *s; + s = fakeCString(vObjectUStringZValue(curVOProp)); + // check to see if event was deleted by the kpilot conduit + if (atoi(s) == Event::SYNCDEL) { + deleteStr(s); + kdDebug(5800) << "skipping pilot-deleted event" << endl; + goto SKIP; + } + deleteStr(s); + } + + // this code checks to see if we are trying to read in an event + // that we already find to be in the calendar. If we find this + // to be the case, we skip the event. + if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) { + char *s = fakeCString(vObjectUStringZValue(curVOProp)); + QString tmpStr(s); + deleteStr(s); + + if (mCalendar->event(tmpStr)) { + goto SKIP; + } + if (mCalendar->todo(tmpStr)) { + goto SKIP; + } + } + + if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) && + (!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) { + kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl; + goto SKIP; + } + + anEvent = VEventToEvent(curVO); + // we now use addEvent instead of insertEvent so that the + // signal/slot get connected. + if (anEvent) { + if ( !anEvent->dtStart().isValid() || !anEvent->dtEnd().isValid() ) { + kdDebug() << "VCalFormat::populate(): Event has invalid dates." + << endl; + } else { + mCalendar->addEvent(anEvent); + } + } else { + // some sort of error must have occurred while in translation. + goto SKIP; + } + } else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) { + Todo *aTodo = VTodoToEvent(curVO); + mCalendar->addTodo(aTodo); + } else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) || + (strcmp(vObjectName(curVO), VCProdIdProp) == 0) || + (strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) { + // do nothing, we know these properties and we want to skip them. + // we have either already processed them or are ignoring them. + ; + } else { + kdDebug(5800) << "Ignoring unknown vObject \"" << vObjectName(curVO) << "\"" << endl; + } + SKIP: + ; + } // while + + // Post-Process list of events with relations, put Event objects in relation + Event *ev; + for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) { + ev->setRelatedTo(mCalendar->event(ev->relatedToUid())); + } + Todo *todo; + for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) { + todo->setRelatedTo(mCalendar->todo(todo->relatedToUid())); + } +} + +const char *VCalFormat::dayFromNum(int day) +{ + const char *days[7] = { "MO ", "TU ", "WE ", "TH ", "FR ", "SA ", "SU " }; + + return days[day]; +} + +int VCalFormat::numFromDay(const QString &day) +{ + if (day == "MO ") return 0; + if (day == "TU ") return 1; + if (day == "WE ") return 2; + if (day == "TH ") return 3; + if (day == "FR ") return 4; + if (day == "SA ") return 5; + if (day == "SU ") return 6; + + return -1; // something bad happened. :) +} + +Attendee::PartStat VCalFormat::readStatus(const char *s) const +{ + QString statStr = s; + statStr = statStr.upper(); + Attendee::PartStat status; + + if (statStr == "X-ACTION") + status = Attendee::NeedsAction; + else if (statStr == "NEEDS ACTION") + status = Attendee::NeedsAction; + else if (statStr== "ACCEPTED") + status = Attendee::Accepted; + else if (statStr== "SENT") + status = Attendee::NeedsAction; + else if (statStr== "TENTATIVE") + status = Attendee::Tentative; + else if (statStr== "CONFIRMED") + status = Attendee::Accepted; + else if (statStr== "DECLINED") + status = Attendee::Declined; + else if (statStr== "COMPLETED") + status = Attendee::Completed; + else if (statStr== "DELEGATED") + status = Attendee::Delegated; + else { + kdDebug(5800) << "error setting attendee mStatus, unknown mStatus!" << endl; + status = Attendee::NeedsAction; + } + + return status; +} + +QCString VCalFormat::writeStatus(Attendee::PartStat status) const +{ + switch(status) { + default: + case Attendee::NeedsAction: + return "NEEDS ACTION"; + break; + case Attendee::Accepted: + return "ACCEPTED"; + break; + case Attendee::Declined: + return "DECLINED"; + break; + case Attendee::Tentative: + return "TENTATIVE"; + break; + case Attendee::Delegated: + return "DELEGATED"; + break; + case Attendee::Completed: + return "COMPLETED"; + break; + case Attendee::InProcess: + return "NEEDS ACTION"; + break; + } +} diff --git a/libkcal/vcalformat.h b/libkcal/vcalformat.h new file mode 100644 index 0000000..d4cecbc --- a/dev/null +++ b/libkcal/vcalformat.h @@ -0,0 +1,108 @@ +/* + This file is part of libkcal. + Copyright (c) 1998 Preston Brown + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _VCALFORMAT_H +#define _VCALFORMAT_H + +#include "calformat.h" + +#define _VCAL_VERSION "1.0" + +class VObject; + +namespace KCal { + +/** + This class implements the vCalendar format. It provides methods for + loading/saving/converting vCalendar format data into the internal KOrganizer + representation as Calendar and Events. + + @short vCalendar format implementation +*/ +class VCalFormat : public CalFormat { + public: + VCalFormat(); + virtual ~VCalFormat(); + + /** loads a calendar on disk in vCalendar format into the current calendar. + * any information already present is lost. Returns TRUE if successful, + * else returns FALSE. + * @param fileName the name of the calendar on disk. + */ + bool load(Calendar *,const QString &fileName); + /** writes out the calendar to disk in vCalendar format. Returns true if + * successful and false on error. + * @param fileName the name of the file + */ + bool save(Calendar *,const QString &fileName); + + /** + Parse string and populate calendar with that information. + */ + bool fromString( Calendar *, const QString & ); + /** + Return calendar information as string. + */ + QString toString( Calendar * ); + + protected: + /** translates a VObject of the TODO type into a Event */ + Todo *VTodoToEvent(VObject *vtodo); + /** translates a VObject into a Event and returns a pointer to it. */ + Event *VEventToEvent(VObject *vevent); + /** translate a Event into a VTodo-type VObject and return pointer */ + VObject *eventToVTodo(const Todo *anEvent); + /** translate a Event into a VObject and returns a pointer to it. */ + VObject* eventToVEvent(const Event *anEvent); + + /** takes a QDate and returns a string in the format YYYYMMDDTHHMMSS */ + QString qDateToISO(const QDate &); + /** takes a QDateTime and returns a string in format YYYYMMDDTHHMMSS */ + QString qDateTimeToISO(const QDateTime &, bool zulu=TRUE); + /** takes a string in the format YYYYMMDDTHHMMSS and returns a + * valid QDateTime. */ + QDateTime ISOToQDateTime(const QString & dtStr); + /** takes a string in the format YYYYMMDD and returns a + * valid QDate. */ + QDate ISOToQDate(const QString & dtStr); + /** takes a vCalendar tree of VObjects, and puts all of them that have + * the "event" property into the dictionary, todos in the todo-list, etc. */ + void populate(VObject *vcal); + + /** takes a number 0 - 6 and returns the two letter string of that day, + * i.e. MO, TU, WE, etc. */ + const char *dayFromNum(int day); + /** the reverse of the above function. */ + int numFromDay(const QString &day); + + Attendee::PartStat readStatus(const char *s) const; + QCString writeStatus(Attendee::PartStat status) const; + + private: + Calendar *mCalendar; + + QPtrList<Event> mEventsRelate; // events with relations + QPtrList<Todo> mTodosRelate; // todos with relations +}; + +} + +#endif diff --git a/libkcal/versit/port.h b/libkcal/versit/port.h new file mode 100644 index 0000000..afc16dd --- a/dev/null +++ b/libkcal/versit/port.h @@ -0,0 +1,75 @@ +/*************************************************************************** +(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. + +For purposes of this license notice, the term Licensors shall mean, +collectively, Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. +The term Licensor shall mean any of the Licensors. + +Subject to acceptance of the following conditions, permission is hereby +granted by Licensors without the need for written agreement and without +license or royalty fees, to use, copy, modify and distribute this +software for any purpose. + +The above copyright notice and the following four paragraphs must be +reproduced in all copies of this software and any software including +this software. + +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE +ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR +MODIFICATIONS. + +IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, +INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT +OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +The software is provided with RESTRICTED RIGHTS. Use, duplication, or +disclosure by the government are subject to restrictions set forth in +DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. + +***************************************************************************/ + +#ifndef __PORT_H__ +#define __PORT_H__ 1 + +#if defined(__CPLUSPLUS__) || defined(__cplusplus) +extern "C" { +#endif + +#define vCardClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCard" +#define vCalendarClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCalendar" + +/* The above strings vCardClipboardFormat and vCalendarClipboardFormat +are globally unique IDs which can be used to generate clipboard format +ID's as per the requirements of a specific platform. For example, in +Windows they are used as the parameter in a call to RegisterClipboardFormat. +For example: + + CLIPFORMAT foo = RegisterClipboardFormat(vCardClipboardFormat); + +*/ + +#define vCardMimeType "text/x-vCard" +#define vCalendarMimeType "text/x-vCalendar" + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#define Parse_Debug(t) + +#if defined(__CPLUSPLUS__) || defined(__cplusplus) +} +#endif + +#endif /* __PORT_H__ */ diff --git a/libkcal/versit/vcc.c b/libkcal/versit/vcc.c new file mode 100644 index 0000000..350cac3 --- a/dev/null +++ b/libkcal/versit/vcc.c @@ -0,0 +1,2162 @@ + +/* A Bison parser, made from ./vcc.y + by GNU Bison version 1.28 */ + +#define YYBISON 1 /* Identify Bison output. */ + +#ifdef _WIN32_ +#define strcasecmp _stricmp +#endif + +#define EQ 257 +#define COLON 258 +#define DOT 259 +#define SEMICOLON 260 +#define SPACE 261 +#define HTAB 262 +#define LINESEP 263 +#define NEWLINE 264 +#define BEGIN_VCARD 265 +#define END_VCARD 266 +#define BEGIN_VCAL 267 +#define END_VCAL 268 +#define BEGIN_VEVENT 269 +#define END_VEVENT 270 +#define BEGIN_VTODO 271 +#define END_VTODO 272 +#define ID 273 +#define STRING 274 + +#line 1 "./vcc.y" + + +/*************************************************************************** +(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. + +For purposes of this license notice, the term Licensors shall mean, +collectively, Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. +The term Licensor shall mean any of the Licensors. + +Subject to acceptance of the following conditions, permission is hereby +granted by Licensors without the need for written agreement and without +license or royalty fees, to use, copy, modify and distribute this +software for any purpose. + +The above copyright notice and the following four paragraphs must be +reproduced in all copies of this software and any software including +this software. + +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE +ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR +MODIFICATIONS. + +IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, +INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT +OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +The software is provided with RESTRICTED RIGHTS. Use, duplication, or +disclosure by the government are subject to restrictions set forth in +DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. + +***************************************************************************/ + +/* + * src: vcc.c + * doc: Parser for vCard and vCalendar. Note that this code is + * generated by a yacc parser generator. Generally it should not + * be edited by hand. The real source is vcc.y. The #line directives + * can be commented out here to make it easier to trace through + * in a debugger. However, if a bug is found it should + * be fixed in vcc.y and this file regenerated. + */ + + +/* debugging utilities */ +#if __DEBUG +#define DBG_(x) printf x +#else +#define DBG_(x) +#endif + +/**** External Functions ****/ + +/* assign local name to parser variables and functions so that + we can use more than one yacc based parser. +*/ + +#define yyparse mime_parse +#define yylex mime_lex +#define yyerror mime_error +#define yychar mime_char +/* #define p_yyval p_mime_val */ +#undef yyval +#define yyval mime_yyval +/* #define p_yylval p_mime_lval */ +#undef yylval +#define yylval mime_yylval +#define yydebug mime_debug +#define yynerrs mime_nerrs +#define yyerrflag mime_errflag +#define yyss mime_ss +#define yyssp mime_ssp +#define yyvs mime_vs +#define yyvsp mime_vsp +#define yylhs mime_lhs +#define yylen mime_len +#define yydefred mime_defred +#define yydgoto mime_dgoto +#define yysindex mime_sindex +#define yyrindex mime_rindex +#define yygindex mime_gindex +#define yytable mime_table +#define yycheck mime_check +#define yyname mime_name +#define yyrule mime_rule +#undef YYPREFIX +#define YYPREFIX "mime_" + + +#ifndef _NO_LINE_FOLDING +#define _SUPPORT_LINE_FOLDING 1 +#endif + +#include <string.h> +#ifndef __FreeBSD__ +#include <malloc.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include "vcc.h" + +/* The following is a hack that I hope will get things compiling + * on SunOS 4.1.x systems + */ +#ifndef SEEK_SET +#define SEEK_SET 0 /* Seek from beginning of file. */ +#define SEEK_CUR 1 /* Seek from current position. */ +#define SEEK_END 2 /* Seek from end of file. */ +#endif + +/**** Types, Constants ****/ + +#define YYDEBUG 0 /* 1 to compile in some debugging code */ +#define MAXTOKEN 256 /* maximum token (line) length */ +#define YYSTACKSIZE 1000 /* ~unref ? */ +#define MAXLEVEL 10 /* max # of nested objects parseable */ + /* (includes outermost) */ + + +/**** Global Variables ****/ +int mime_lineNum, mime_numErrors; /* yyerror() can use these */ +static VObject* vObjList; +static VObject *curProp; +static VObject *curObj; +static VObject* ObjStack[MAXLEVEL]; +static int ObjStackTop; + + +/* A helpful utility for the rest of the app. */ +#if __CPLUSPLUS__ +extern "C" { +#endif + + /* static void Parse_Debug(const char *s);*/ + static void yyerror(char *s); + +#if __CPLUSPLUS__ + }; +#endif + +int yyparse(); +static int yylex(); +enum LexMode { + L_NORMAL, + L_VCARD, + L_VCAL, + L_VEVENT, + L_VTODO, + L_VALUES, + L_BASE64, + L_QUOTED_PRINTABLE + }; + +/**** Private Forward Declarations ****/ +static int pushVObject(const char *prop); +static VObject* popVObject(); +char* lexDataFromBase64(); +static void lexPopMode(int top); +static int lexWithinMode(enum LexMode mode); +static void lexPushMode(enum LexMode mode); +static void enterProps(const char *s); +static void enterAttr(const char *s1, const char *s2); +/* static void enterValues(const char *value); */ +static void appendValue(const char *value); +static void mime_error_(char *s); + + +#line 181 "./vcc.y" +typedef union { + char *str; + VObject *vobj; + } YYSTYPE; +#include <stdio.h> + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 62 +#define YYFLAG -32768 +#define YYNTBASE 21 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 274 ? yytranslate[x] : 51) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 3, 7, 9, 11, 13, 14, 19, 20, + 24, 27, 29, 30, 36, 38, 39, 43, 45, 48, + 50, 53, 55, 59, 61, 62, 67, 69, 71, 72, + 73, 78, 79, 83, 86, 88, 90, 92, 94, 95, + 100, 101, 105, 106, 111, 112 +}; + +static const short yyrhs[] = { 22, + 0, 0, 24, 23, 22, 0, 24, 0, 25, 0, + 40, 0, 0, 11, 26, 28, 12, 0, 0, 11, + 27, 12, 0, 29, 28, 0, 29, 0, 0, 31, + 4, 30, 37, 9, 0, 1, 0, 0, 36, 32, + 33, 0, 36, 0, 34, 33, 0, 34, 0, 6, + 35, 0, 36, 0, 36, 3, 36, 0, 19, 0, + 0, 39, 6, 38, 37, 0, 39, 0, 20, 0, + 0, 0, 13, 41, 43, 14, 0, 0, 13, 42, + 14, 0, 44, 43, 0, 44, 0, 45, 0, 48, + 0, 28, 0, 0, 15, 46, 28, 16, 0, 0, + 15, 47, 16, 0, 0, 17, 49, 28, 18, 0, + 0, 17, 50, 18, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 209, 212, 215, 215, 219, 220, 223, 229, 234, 240, + 246, 247, 250, 254, 260, 263, 268, 268, 274, 275, + 278, 281, 285, 292, 295, 296, 296, 300, 301, 305, + 309, 311, 314, 317, 318, 321, 323, 324, 327, 334, + 339, 345, 351, 358, 363, 369 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","EQ","COLON", +"DOT","SEMICOLON","SPACE","HTAB","LINESEP","NEWLINE","BEGIN_VCARD","END_VCARD", +"BEGIN_VCAL","END_VCAL","BEGIN_VEVENT","END_VEVENT","BEGIN_VTODO","END_VTODO", +"ID","STRING","mime","vobjects","@1","vobject","vcard","@2","@3","items","item", +"@4","prop","@5","attr_params","attr_param","attr","name","values","@6","value", +"vcal","@7","@8","calitems","calitem","eventitem","@9","@10","todoitem","@11", +"@12", NULL +}; +#endif + +static const short yyr1[] = { 0, + 21, 23, 22, 22, 24, 24, 26, 25, 27, 25, + 28, 28, 30, 29, 29, 32, 31, 31, 33, 33, + 34, 35, 35, 36, 38, 37, 37, 39, 39, 41, + 40, 42, 40, 43, 43, 44, 44, 44, 46, 45, + 47, 45, 49, 48, 50, 48 +}; + +static const short yyr2[] = { 0, + 1, 0, 3, 1, 1, 1, 0, 4, 0, 3, + 2, 1, 0, 5, 1, 0, 3, 1, 2, 1, + 2, 1, 3, 1, 0, 4, 1, 1, 0, 0, + 4, 0, 3, 2, 1, 1, 1, 1, 0, 4, + 0, 3, 0, 4, 0, 3 +}; + +static const short yydefact[] = { 0, + 7, 30, 1, 2, 5, 6, 0, 0, 0, 0, + 0, 15, 24, 0, 0, 0, 16, 10, 39, 43, + 38, 0, 0, 36, 37, 33, 3, 8, 11, 13, + 0, 0, 0, 0, 0, 31, 34, 29, 0, 17, + 20, 0, 42, 0, 46, 28, 0, 27, 21, 22, + 19, 40, 44, 14, 25, 0, 29, 23, 26, 0, + 0, 0 +}; + +static const short yydefgoto[] = { 60, + 3, 11, 4, 5, 7, 8, 21, 15, 38, 16, + 31, 40, 41, 49, 17, 47, 57, 48, 6, 9, + 10, 22, 23, 24, 32, 33, 25, 34, 35 +}; + +static const short yypact[] = { -9, + -6, -5,-32768, 7,-32768,-32768, 2, -1, 19, 15, + -9,-32768,-32768, 1, 0, 26, 27,-32768, 16, 17, +-32768, 23, 9,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + 33, 2, 24, 2, 25,-32768,-32768, 13, 22,-32768, + 33, 28,-32768, 29,-32768,-32768, 36, 40,-32768, 39, +-32768,-32768,-32768,-32768,-32768, 22, 13,-32768,-32768, 48, + 49,-32768 +}; + +static const short yypgoto[] = {-32768, + 41,-32768,-32768,-32768,-32768,-32768, -7,-32768,-32768,-32768, +-32768, 10,-32768,-32768, -34, -4,-32768,-32768,-32768,-32768, +-32768, 31,-32768,-32768,-32768,-32768,-32768,-32768,-32768 +}; + + +#define YYLAST 54 + + +static const short yytable[] = { 14, + 12, 1, 12, 2, 50, -9, -4, 29, -32, 12, + 18, -12, 28, -12, -12, -12, -12, -12, 13, 12, + 13, 58, -35, 19, 42, 20, 44, 13, 26, 30, + -18, -41, 46, 19, -45, 20, 36, 13, 39, 43, + 13, 56, 45, 52, 54, 55, 53, 61, 62, 0, + 51, 27, 59, 37 +}; + +static const short yycheck[] = { 7, + 1, 11, 1, 13, 39, 12, 0, 15, 14, 1, + 12, 12, 12, 14, 15, 16, 17, 18, 19, 1, + 19, 56, 14, 15, 32, 17, 34, 19, 14, 4, + 4, 16, 20, 15, 18, 17, 14, 19, 6, 16, + 19, 3, 18, 16, 9, 6, 18, 0, 0, -1, + 41, 11, 57, 23 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/bison.simple" +/* This file comes from bison-1.28. */ + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ +#ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA +#include <alloca.h> +#else /* not sparc */ +/* We think this test detects Watcom and Microsoft C. */ +/* This used to test MSDOS, but that is a bad idea + since that symbol is in the user namespace. */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; + instead, just don't use alloca. */ +#include <malloc.h> +#endif +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +/* I don't know what this was needed for, but it pollutes the namespace. + So I turned it off. rms, 2 May 1997. */ +/* #include <malloc.h> */ + #pragma alloca +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, + and on HPUX 10. Eventually we can turn this on. */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#endif /* __hpux */ +#endif +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ + +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc +#endif + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Define __yy_memcpy. Note that the size argument + should be passed with type unsigned int, because that is what the non-GCC + definitions require. With GCC, __builtin_memcpy takes an arg + of type size_t, but it can handle unsigned int. */ + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + unsigned int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, unsigned int count) +{ + register char *t = to; + register char *f = from; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 217 "/usr/share/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#if defined (__GNUC__) && ! defined (__cplusplus) +#ifdef YYPARSE_PARAM +int yyparse (void *); +#else +int yyparse (void); +#endif +#endif + +int +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + int yyfree_stacks = 0; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; +#ifndef YYSTACK_USE_ALLOCA + yyfree_stacks = 1; +#endif + yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, + size * (unsigned int) sizeof (*yyssp)); + yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, + size * (unsigned int) sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, + size * (unsigned int) sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 2: +#line 213 "./vcc.y" +{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; ; + break;} +case 4: +#line 216 "./vcc.y" +{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; ; + break;} +case 7: +#line 225 "./vcc.y" +{ + lexPushMode(L_VCARD); + if (!pushVObject(VCCardProp)) YYERROR; + ; + break;} +case 8: +#line 230 "./vcc.y" +{ + lexPopMode(0); + yyval.vobj = popVObject(); + ; + break;} +case 9: +#line 235 "./vcc.y" +{ + lexPushMode(L_VCARD); + if (!pushVObject(VCCardProp)) YYERROR; + ; + break;} +case 10: +#line 240 "./vcc.y" +{ + lexPopMode(0); + yyval.vobj = popVObject(); + ; + break;} +case 13: +#line 251 "./vcc.y" +{ + lexPushMode(L_VALUES); + ; + break;} +case 14: +#line 255 "./vcc.y" +{ + if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE)) + lexPopMode(0); + lexPopMode(0); + ; + break;} +case 16: +#line 264 "./vcc.y" +{ + enterProps(yyvsp[0].str); + ; + break;} +case 18: +#line 269 "./vcc.y" +{ + enterProps(yyvsp[0].str); + ; + break;} +case 22: +#line 282 "./vcc.y" +{ + enterAttr(yyvsp[0].str,0); + ; + break;} +case 23: +#line 286 "./vcc.y" +{ + enterAttr(yyvsp[-2].str,yyvsp[0].str); + + ; + break;} +case 25: +#line 295 "./vcc.y" +{ appendValue(yyvsp[-1].str); ; + break;} +case 27: +#line 297 "./vcc.y" +{ appendValue(yyvsp[0].str); ; + break;} +case 29: +#line 302 "./vcc.y" +{ yyval.str = 0; ; + break;} +case 30: +#line 307 "./vcc.y" +{ if (!pushVObject(VCCalProp)) YYERROR; ; + break;} +case 31: +#line 310 "./vcc.y" +{ yyval.vobj = popVObject(); ; + break;} +case 32: +#line 312 "./vcc.y" +{ if (!pushVObject(VCCalProp)) YYERROR; ; + break;} +case 33: +#line 314 "./vcc.y" +{ yyval.vobj = popVObject(); ; + break;} +case 39: +#line 329 "./vcc.y" +{ + lexPushMode(L_VEVENT); + if (!pushVObject(VCEventProp)) YYERROR; + ; + break;} +case 40: +#line 335 "./vcc.y" +{ + lexPopMode(0); + popVObject(); + ; + break;} +case 41: +#line 340 "./vcc.y" +{ + lexPushMode(L_VEVENT); + if (!pushVObject(VCEventProp)) YYERROR; + ; + break;} +case 42: +#line 345 "./vcc.y" +{ + lexPopMode(0); + popVObject(); + ; + break;} +case 43: +#line 353 "./vcc.y" +{ + lexPushMode(L_VTODO); + if (!pushVObject(VCTodoProp)) YYERROR; + ; + break;} +case 44: +#line 359 "./vcc.y" +{ + lexPopMode(0); + popVObject(); + ; + break;} +case 45: +#line 364 "./vcc.y" +{ + lexPushMode(L_VTODO); + if (!pushVObject(VCTodoProp)) YYERROR; + ; + break;} +case 46: +#line 369 "./vcc.y" +{ + lexPopMode(0); + popVObject(); + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 543 "/usr/share/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + yyacceptlab: + /* YYACCEPT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 0; + + yyabortlab: + /* YYABORT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 1; +} +#line 375 "./vcc.y" + +/****************************************************************************/ +static int pushVObject(const char *prop) + { + VObject *newObj; + if (ObjStackTop == MAXLEVEL) + return FALSE; + + ObjStack[++ObjStackTop] = curObj; + + if (curObj) { + newObj = addProp(curObj,prop); + curObj = newObj; + } + else + curObj = newVObject(prop); + + return TRUE; + } + + +/****************************************************************************/ +/* This pops the recently built vCard off the stack and returns it. */ +static VObject* popVObject() + { + VObject *oldObj; + if (ObjStackTop < 0) { + yyerror("pop on empty Object Stack\n"); + return 0; + } + oldObj = curObj; + curObj = ObjStack[ObjStackTop--]; + + return oldObj; + } + + +/* static void enterValues(const char *value) */ +/* { */ +/* if (fieldedProp && *fieldedProp) { */ +/* if (value) { */ +/* addPropValue(curProp,*fieldedProp,value); */ +/* } */ + /* else this field is empty, advance to next field */ +/* fieldedProp++; */ +/* } */ +/* else { */ +/* if (value) { */ +/* setVObjectUStringZValue_(curProp,fakeUnicode(value,0)); */ +/* } */ +/* } */ +/* deleteStr(value); */ +/* } */ + +static void appendValue(const char *value) +{ + char *p1, *p2; + wchar_t *p3; + int i; + + if (fieldedProp && *fieldedProp) { + if (value) { + addPropValue(curProp, *fieldedProp, value); + } + /* else this field is empty, advance to next field */ + fieldedProp++; + } else { + if (value) { + if (vObjectUStringZValue(curProp)) { + p1 = fakeCString(vObjectUStringZValue(curProp)); + p2 = malloc(sizeof(char *) * (strlen(p1)+strlen(value)+1)); + strcpy(p2, p1); + deleteStr(p1); + + i = strlen(p2); + p2[i] = ','; + p2[i+1] = '\0'; + p2 = strcat(p2, value); + p3 = (wchar_t *) vObjectUStringZValue(curProp); + free(p3); + setVObjectUStringZValue_(curProp,fakeUnicode(p2,0)); + deleteStr(p2); + } else { + setVObjectUStringZValue_(curProp,fakeUnicode(value,0)); + } + } + } + deleteStr(value); +} + + +static void enterProps(const char *s) + { + curProp = addGroup(curObj,s); + deleteStr(s); + } + +static void enterAttr(const char *s1, const char *s2) + { + const char *p1=0L, *p2=0L; + p1 = lookupProp_(s1); + if (s2) { + VObject *a; + p2 = lookupProp_(s2); + a = addProp(curProp,p1); + setVObjectStringZValue(a,p2); + } + else + addProp(curProp,p1); + if (strcasecmp(p1,VCBase64Prop) == 0 || (s2 && strcasecmp(p2,VCBase64Prop)==0)) + lexPushMode(L_BASE64); + else if (strcasecmp(p1,VCQuotedPrintableProp) == 0 + || (s2 && strcasecmp(p2,VCQuotedPrintableProp)==0)) + lexPushMode(L_QUOTED_PRINTABLE); + deleteStr(s1); deleteStr(s2); + } + + +#define MAX_LEX_LOOKAHEAD_0 32 +#define MAX_LEX_LOOKAHEAD 64 +#define MAX_LEX_MODE_STACK_SIZE 10 +#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop]) + +struct LexBuf { + /* input */ + FILE *inputFile; + char *inputString; + unsigned long curPos; + unsigned long inputLen; + /* lookahead buffer */ + /* -- lookahead buffer is short instead of char so that EOF + / can be represented correctly. + */ + unsigned long len; + short buf[MAX_LEX_LOOKAHEAD]; + unsigned long getPtr; + /* context stack */ + unsigned long lexModeStackTop; + enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE]; + /* token buffer */ + unsigned long maxToken; + char *strs; + unsigned long strsLen; + } lexBuf; + +static void lexPushMode(enum LexMode mode) + { + if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1)) + yyerror("lexical context stack overflow"); + else { + lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode; + } + } + +static void lexPopMode(int top) + { + /* special case of pop for ease of error recovery -- this + version will never underflow */ + if (top) + lexBuf.lexModeStackTop = 0; + else + if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--; + } + +static int lexWithinMode(enum LexMode mode) { + unsigned long i; + for (i=0;i<lexBuf.lexModeStackTop;i++) + if (mode == lexBuf.lexModeStack[i]) return 1; + return 0; + } + +static int lexGetc_() + { + /* get next char from input, no buffering. */ + if (lexBuf.curPos == lexBuf.inputLen) + return EOF; + else if (lexBuf.inputString) + return *(lexBuf.inputString + lexBuf.curPos++); + else { + if (!feof(lexBuf.inputFile)) + return fgetc(lexBuf.inputFile); + else + return EOF; + } + } + +static int lexGeta() + { + ++lexBuf.len; + return (lexBuf.buf[lexBuf.getPtr] = lexGetc_()); + } + +static int lexGeta_(int i) + { + ++lexBuf.len; + return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_()); + } + +static void lexSkipLookahead() { + if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { + /* don't skip EOF. */ + lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; + lexBuf.len--; + } + } + +static int lexLookahead() { + int c = (lexBuf.len)? + lexBuf.buf[lexBuf.getPtr]: + lexGeta(); + /* do the \r\n -> \n or \r -> \n translation here */ + if (c == '\r') { + int a = (lexBuf.len>1)? + lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]: + lexGeta_(1); + if (a == '\n') { + lexSkipLookahead(); + } + lexBuf.buf[lexBuf.getPtr] = c = '\n'; + } + else if (c == '\n') { + int a; + if (lexBuf.len > 1) + a = lexBuf.buf[lexBuf.getPtr]; + else + a = lexGeta_(1); + if (a == '\r') { + lexSkipLookahead(); + } + lexBuf.buf[lexBuf.getPtr] = '\n'; + } + return c; + } + +static int lexGetc() { + int c = lexLookahead(); + if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { + /* EOF will remain in lookahead buffer */ + lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; + lexBuf.len--; + } + return c; + } + +static void lexSkipLookaheadWord() { + if (lexBuf.strsLen <= lexBuf.len) { + lexBuf.len -= lexBuf.strsLen; + lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD; + } + } + +static void lexClearToken() + { + lexBuf.strsLen = 0; + } + +static void lexAppendc(int c) + { + /* not sure if I am doing this right to fix purify report -- PGB */ + lexBuf.strs = (char *) realloc(lexBuf.strs, (size_t) lexBuf.strsLen + 1); + lexBuf.strs[lexBuf.strsLen] = c; + /* append up to zero termination */ + if (c == 0) return; + lexBuf.strsLen++; + if (lexBuf.strsLen > lexBuf.maxToken) { + /* double the token string size */ + lexBuf.maxToken <<= 1; + lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken); + } + } + +static char* lexStr() { + return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1); + } + +static void lexSkipWhite() { + int c = lexLookahead(); + while (c == ' ' || c == '\t') { + lexSkipLookahead(); + c = lexLookahead(); + } + } + +static char* lexGetWord() { + int c; + lexSkipWhite(); + lexClearToken(); + c = lexLookahead(); + /* some "words" have a space in them, like "NEEDS ACTION". + this may be an oversight of the spec, but it is true nevertheless. + while (c != EOF && !strchr("\t\n ;:=",c)) { */ + while (c != EOF && !strchr("\n;:=",c)) { + lexAppendc(c); + lexSkipLookahead(); + c = lexLookahead(); + } + lexAppendc(0); + return lexStr(); + } + +void lexPushLookahead(char *s, int len) { + int putptr; + if (len == 0) len = strlen(s); + putptr = (int)lexBuf.getPtr - len; + /* this function assumes that length of word to push back + / is not greater than MAX_LEX_LOOKAHEAD. + */ + if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; + lexBuf.getPtr = putptr; + while (*s) { + lexBuf.buf[putptr] = *s++; + putptr = (putptr + 1) % MAX_LEX_LOOKAHEAD; + } + lexBuf.len += len; + } + +static void lexPushLookaheadc(int c) { + int putptr; + /* can't putback EOF, because it never leaves lookahead buffer */ + if (c == EOF) return; + putptr = (int)lexBuf.getPtr - 1; + if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; + lexBuf.getPtr = putptr; + lexBuf.buf[putptr] = c; + lexBuf.len += 1; + } + +static char* lexLookaheadWord() { + /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0 + / and thing bigger than that will stop the lookahead and return 0; + / leading white spaces are not recoverable. + */ + int c; + int len = 0; + int curgetptr = 0; + lexSkipWhite(); + lexClearToken(); + curgetptr = (int)lexBuf.getPtr; /* remember! */ + while (len < (MAX_LEX_LOOKAHEAD_0)) { + c = lexGetc(); + len++; + if (c == EOF || strchr("\t\n ;:=", c)) { + lexAppendc(0); + /* restore lookahead buf. */ + lexBuf.len += len; + lexBuf.getPtr = curgetptr; + return lexStr(); + } + else + lexAppendc(c); + } + lexBuf.len += len; /* char that has been moved to lookahead buffer */ + lexBuf.getPtr = curgetptr; + return 0; + } + +#ifdef _SUPPORT_LINE_FOLDING +static void handleMoreRFC822LineBreak(int c) { + /* suport RFC 822 line break in cases like + * ADR: foo; + * morefoo; + * more foo; + */ + if (c == ';') { + int a; + lexSkipLookahead(); + /* skip white spaces */ + a = lexLookahead(); + while (a == ' ' || a == '\t') { + lexSkipLookahead(); + a = lexLookahead(); + } + if (a == '\n') { + lexSkipLookahead(); + a = lexLookahead(); + if (a == ' ' || a == '\t') { + /* continuation, throw away all the \n and spaces read so + * far + */ + lexSkipWhite(); + lexPushLookaheadc(';'); + } + else { + lexPushLookaheadc('\n'); + lexPushLookaheadc(';'); + } + } + else { + lexPushLookaheadc(';'); + } + } + } + +static char* lexGet1Value() { + int c; + lexSkipWhite(); + c = lexLookahead(); + lexClearToken(); + while (c != EOF && c != ';') { + if (c == '\n') { + int a; + lexSkipLookahead(); + a = lexLookahead(); + if (a == ' ' || a == '\t') { + lexAppendc(' '); + lexSkipLookahead(); + } + else { + lexPushLookaheadc('\n'); + break; + } + } + else { + lexAppendc(c); + lexSkipLookahead(); + } + c = lexLookahead(); + } + lexAppendc(0); + handleMoreRFC822LineBreak(c); + return c==EOF?0:lexStr(); + } +#endif + +char* lexGetStrUntil(char *termset) { + int c = lexLookahead(); + lexClearToken(); + while (c != EOF && !strchr(termset,c)) { + lexAppendc(c); + lexSkipLookahead(); + c = lexLookahead(); + } + lexAppendc(0); + return c==EOF?0:lexStr(); + } + +static int match_begin_name(int end) { + char *n = lexLookaheadWord(); + int token = ID; + if (n) { + if (!strcasecmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD; + else if (!strcasecmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL; + else if (!strcasecmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT; + else if (!strcasecmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO; + deleteStr(n); + return token; + } + return 0; + } + + +void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile) + { + /* initialize lex mode stack */ + lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL; + + /* iniatialize lex buffer. */ + lexBuf.inputString = (char*) inputstring; + lexBuf.inputLen = inputlen; + lexBuf.curPos = 0; + lexBuf.inputFile = inputfile; + + lexBuf.len = 0; + lexBuf.getPtr = 0; + + lexBuf.maxToken = MAXTOKEN; + lexBuf.strs = (char*)malloc(MAXTOKEN); + lexBuf.strsLen = 0; + + } + +static void finiLex() { + free(lexBuf.strs); + } + + +/****************************************************************************/ +/* This parses and converts the base64 format for binary encoding into + * a decoded buffer (allocated with new). See RFC 1521. + */ +static char * lexGetDataFromBase64() + { + unsigned long bytesLen = 0, bytesMax = 0; + int quadIx = 0, pad = 0; + unsigned long trip = 0; + unsigned char b; + int c; + unsigned char *bytes = NULL; + unsigned char *oldBytes = NULL; + + DBG_(("db: lexGetDataFromBase64\n")); + while (1) { + c = lexGetc(); + if (c == '\n') { + ++mime_lineNum; + if (lexLookahead() == '\n') { + /* a '\n' character by itself means end of data */ + break; + } + else continue; /* ignore '\n' */ + } + else { + if ((c >= 'A') && (c <= 'Z')) + b = (unsigned char)(c - 'A'); + else if ((c >= 'a') && (c <= 'z')) + b = (unsigned char)(c - 'a') + 26; + else if ((c >= '0') && (c <= '9')) + b = (unsigned char)(c - '0') + 52; + else if (c == '+') + b = 62; + else if (c == '/') + b = 63; + else if (c == '=') { + b = 0; + pad++; + } else if ((c == ' ') || (c == '\t')) { + continue; + } else { /* error condition */ + if (bytes) free(bytes); + else if (oldBytes) free(oldBytes); + /* error recovery: skip until 2 adjacent newlines. */ + DBG_(("db: invalid character 0x%x '%c'\n", c,c)); + if (c != EOF) { + c = lexGetc(); + while (c != EOF) { + if (c == '\n' && lexLookahead() == '\n') { + ++mime_lineNum; + break; + } + c = lexGetc(); + } + } + return NULL; + } + trip = (trip << 6) | b; + if (++quadIx == 4) { + unsigned char outBytes[3]; + int numOut; + int i; + for (i = 0; i < 3; i++) { + outBytes[2-i] = (unsigned char)(trip & 0xFF); + trip >>= 8; + } + numOut = 3 - pad; + if (bytesLen + numOut > bytesMax) { + if (!bytes) { + bytesMax = 1024; + bytes = (unsigned char*)malloc((size_t)bytesMax); + } + else { + bytesMax <<= 2; + oldBytes = bytes; + bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax); + } + if (bytes == 0) { + mime_error("out of memory while processing BASE64 data\n"); + } + } + if (bytes) { + memcpy(bytes + bytesLen, outBytes, numOut); + bytesLen += numOut; + } + trip = 0; + quadIx = 0; + } + } + } /* while */ + DBG_(("db: bytesLen = %d\n", bytesLen)); + /* kludge: all this won't be necessary if we have tree form + representation */ + if (bytes) { + setValueWithSize(curProp,bytes,(unsigned int)bytesLen); + free(bytes); + } + else if (oldBytes) { + setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen); + free(oldBytes); + } + return 0; + } + +static int match_begin_end_name(int end) { + int token; + lexSkipWhite(); + if (lexLookahead() != ':') return ID; + lexSkipLookahead(); + lexSkipWhite(); + token = match_begin_name(end); + if (token == ID) { + lexPushLookaheadc(':'); + DBG_(("db: ID '%s'\n", yylval.str)); + return ID; + } + else if (token != 0) { + lexSkipLookaheadWord(); + deleteStr(yylval.str); + DBG_(("db: begin/end %d\n", token)); + return token; + } + return 0; + } + +static char* lexGetQuotedPrintable() + { + char cur; + + lexClearToken(); + do { + cur = lexGetc(); + switch (cur) { + case '=': { + int c = 0; + int next[2]; + int i; + for (i = 0; i < 2; i++) { + next[i] = lexGetc(); + if (next[i] >= '0' && next[i] <= '9') + c = c * 16 + next[i] - '0'; + else if (next[i] >= 'A' && next[i] <= 'F') + c = c * 16 + next[i] - 'A' + 10; + else + break; + } + if (i == 0) { + /* single '=' follow by LINESEP is continuation sign? */ + if (next[0] == '\n') { + ++mime_lineNum; + } + else { + lexPushLookaheadc('='); + goto EndString; + } + } + else if (i == 1) { + lexPushLookaheadc(next[1]); + lexPushLookaheadc(next[0]); + lexAppendc('='); + } else { + lexAppendc(c); + } + break; + } /* '=' */ + case '\n': { + lexPushLookaheadc('\n'); + goto EndString; + } + case (char)EOF: + break; + default: + lexAppendc(cur); + break; + } /* switch */ + } while (cur != (char)EOF); + +EndString: + lexAppendc(0); + return lexStr(); + } /* LexQuotedPrintable */ + +static int yylex() { + + int lexmode = LEXMODE(); + if (lexmode == L_VALUES) { + int c = lexGetc(); + if (c == ';') { + DBG_(("db: SEMICOLON\n")); + lexPushLookaheadc(c); + handleMoreRFC822LineBreak(c); + lexSkipLookahead(); + return SEMICOLON; + } + else if (strchr("\n",c)) { + ++mime_lineNum; + /* consume all line separator(s) adjacent to each other */ + c = lexLookahead(); + while (strchr("\n",c)) { + lexSkipLookahead(); + c = lexLookahead(); + ++mime_lineNum; + } + DBG_(("db: LINESEP\n")); + return LINESEP; + } + else { + char *p = 0; + lexPushLookaheadc(c); + if (lexWithinMode(L_BASE64)) { + /* get each char and convert to bin on the fly... */ + p = lexGetDataFromBase64(); + yylval.str = p; + return STRING; + } + else if (lexWithinMode(L_QUOTED_PRINTABLE)) { + p = lexGetQuotedPrintable(); + } + else { +#ifdef _SUPPORT_LINE_FOLDING + p = lexGet1Value(); +#else + p = lexGetStrUntil(";\n"); +#endif + } + if (p) { + DBG_(("db: STRING: '%s'\n", p)); + yylval.str = p; + return STRING; + } + else return 0; + } + } + + else { + /* normal mode */ + while (1) { + int c = lexGetc(); + switch(c) { + case ':': { + /* consume all line separator(s) adjacent to each other */ + /* ignoring linesep immediately after colon. */ + c = lexLookahead(); + while (strchr("\n",c)) { + lexSkipLookahead(); + c = lexLookahead(); + ++mime_lineNum; + } + DBG_(("db: COLON\n")); + return COLON; + } + case ';': + DBG_(("db: SEMICOLON\n")); + return SEMICOLON; + case '=': + DBG_(("db: EQ\n")); + return EQ; + /* ignore tabs/newlines in this mode. We can't ignore + * spaces, because values like NEEDS ACTION have a space. */ + case '\t': continue; + case '\n': { + ++mime_lineNum; + continue; + } + case EOF: return 0; + break; + default: { + lexPushLookaheadc(c); + /* pending lutz : why linker error with isalpha(c)? */ + /*if ( isalpha(c) || c == ' ') { */ + if ( ( c >= 'A' && c <= 'Z') || ( c >= 'a' && c <= 'z') || c == ' ') { + + char *t = lexGetWord(); + yylval.str = t; + if (!strcasecmp(t, "begin")) { + return match_begin_end_name(0); + } + else if (!strcasecmp(t,"end")) { + return match_begin_end_name(1); + } + else { + DBG_(("db: ID '%s'\n", t)); + return ID; + } + } + else { + /* unknown token */ + return 0; + } + break; + } + } + } + } + + return 0; + } + + +/***************************************************************************/ +/*** Public Functions ****/ +/***************************************************************************/ + +static VObject* Parse_MIMEHelper() + { + ObjStackTop = -1; + mime_numErrors = 0; + mime_lineNum = 1; + vObjList = 0; + curObj = 0; + + if (yyparse() != 0) + return 0; + + finiLex(); + return vObjList; + } + +/****************************************************************************/ +VObject* Parse_MIME(const char *input, unsigned long len) + { + initLex(input, len, 0); + return Parse_MIMEHelper(); + } + + +VObject* Parse_MIME_FromFile(FILE *file) + { + VObject *result; + long startPos; + + initLex(0,(unsigned long)-1,file); + startPos = ftell(file); + if (!(result = Parse_MIMEHelper())) { + fseek(file,startPos,SEEK_SET); + } + return result; + } + +VObject* Parse_MIME_FromFileName(const char *fname) + { + FILE *fp = fopen(fname,"r"); + if (fp) { + VObject* o = Parse_MIME_FromFile(fp); + fclose(fp); + return o; + } + else { + char msg[255]; + sprintf(msg, "can't open file '%s' for reading\n", fname); + mime_error_(msg); + return 0; + } + } + +/****************************************************************************/ +void YYDebug(const char *s) +{ + Parse_Debug(s); +} + + +static MimeErrorHandler mimeErrorHandler; + +void registerMimeErrorHandler(MimeErrorHandler me) + { + mimeErrorHandler = me; + } + +static void mime_error(char *s) + { + char msg[256]; + if (mimeErrorHandler) { + sprintf(msg,"%s at line %d", s, mime_lineNum); + mimeErrorHandler(msg); + } + } + +static void mime_error_(char *s) + { + if (mimeErrorHandler) { + mimeErrorHandler(s); + } + } + diff --git a/libkcal/versit/vcc.h b/libkcal/versit/vcc.h new file mode 100644 index 0000000..03886d1 --- a/dev/null +++ b/libkcal/versit/vcc.h @@ -0,0 +1,76 @@ +/*************************************************************************** +(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. + +For purposes of this license notice, the term Licensors shall mean, +collectively, Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. +The term Licensor shall mean any of the Licensors. + +Subject to acceptance of the following conditions, permission is hereby +granted by Licensors without the need for written agreement and without +license or royalty fees, to use, copy, modify and distribute this +software for any purpose. + +The above copyright notice and the following four paragraphs must be +reproduced in all copies of this software and any software including +this software. + +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE +ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR +MODIFICATIONS. + +IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, +INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT +OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +The software is provided with RESTRICTED RIGHTS. Use, duplication, or +disclosure by the government are subject to restrictions set forth in +DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. + +***************************************************************************/ + +#ifndef __VCC_H__ +#define __VCC_H__ 1 + +#include "vobject.h" + + +#if defined(__CPLUSPLUS__) || defined(__cplusplus) +extern "C" { +#endif + +typedef void (*MimeErrorHandler)(char *); + +extern void registerMimeErrorHandler(MimeErrorHandler); + +extern VObject* Parse_MIME(const char *input, unsigned long len); +extern VObject* Parse_MIME_FromFileName(const char* fname); + + +/* NOTE regarding Parse_MIME_FromFile +The function below, Parse_MIME_FromFile, come in two flavors, +neither of which is exported from the DLL. Each version takes +a CFile or FILE* as a parameter, neither of which can be +passed across a DLL interface (at least that is my experience). +If you are linking this code into your build directly then +you may find them a more convenient API that the other flavors +that take a file name. If you use them with the DLL LIB you +will get a link error. +*/ + + +extern VObject* Parse_MIME_FromFile(FILE *file); + +#if defined(__CPLUSPLUS__) || defined(__cplusplus) +} +#endif + +#endif /* __VCC_H__ */ + diff --git a/libkcal/versit/versit.pro b/libkcal/versit/versit.pro new file mode 100644 index 0000000..915c25c --- a/dev/null +++ b/libkcal/versit/versit.pro @@ -0,0 +1,15 @@ +TEMPLATE = lib +CONFIG = qt warn_on release +TARGET = versit +INTERFACES = \ + +HEADERS = \ + port.h \ + vcc.h \ + vobject.h \ + +SOURCES = \ + \ \ + vcc.c \ + vobject.c \ + diff --git a/libkcal/versit/versit.pro.back b/libkcal/versit/versit.pro.back new file mode 100644 index 0000000..915c25c --- a/dev/null +++ b/libkcal/versit/versit.pro.back @@ -0,0 +1,15 @@ +TEMPLATE = lib +CONFIG = qt warn_on release +TARGET = versit +INTERFACES = \ + +HEADERS = \ + port.h \ + vcc.h \ + vobject.h \ + +SOURCES = \ + \ \ + vcc.c \ + vobject.c \ + diff --git a/libkcal/versit/vobject.c b/libkcal/versit/vobject.c new file mode 100644 index 0000000..637efb2 --- a/dev/null +++ b/libkcal/versit/vobject.c @@ -0,0 +1,1433 @@ +/*************************************************************************** +(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. + +For purposes of this license notice, the term Licensors shall mean, +collectively, Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. +The term Licensor shall mean any of the Licensors. + +Subject to acceptance of the following conditions, permission is hereby +granted by Licensors without the need for written agreement and without +license or royalty fees, to use, copy, modify and distribute this +software for any purpose. + +The above copyright notice and the following four paragraphs must be +reproduced in all copies of this software and any software including +this software. + +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE +ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR +MODIFICATIONS. + +IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, +INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT +OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +The software is provided with RESTRICTED RIGHTS. Use, duplication, or +disclosure by the government are subject to restrictions set forth in +DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. + +***************************************************************************/ + +/* + * src: vobject.c + * doc: vobject and APIs to construct vobject, APIs pretty print + * vobject, and convert a vobject into its textual representation. + */ + +#include <stdlib.h> + +#include "vobject.h" +#include <string.h> +#include <stdio.h> +#ifdef _WIN32_ + + #define strcasecmp _stricmp + +#endif + +#define NAME_OF(o) o->id +#define VALUE_TYPE(o) o->valType +#define STRINGZ_VALUE_OF(o) o->val.strs +#define USTRINGZ_VALUE_OF(o) o->val.ustrs +#define INTEGER_VALUE_OF(o) o->val.i +#define LONG_VALUE_OF(o) o->val.l +#define ANY_VALUE_OF(o) o->val.any +#define VOBJECT_VALUE_OF(o) o->val.vobj + +const char** fieldedProp; + + + +/*---------------------------------------------------------------------- + The following functions involve with memory allocation: + newVObject + deleteVObject + dupStr + deleteStr + newStrItem + deleteStrItem + ----------------------------------------------------------------------*/ + +VObject* newVObject_(const char *id) +{ + VObject *p = (VObject*)malloc(sizeof(VObject)); + p->next = 0; + p->id = id; + p->prop = 0; + VALUE_TYPE(p) = 0; + ANY_VALUE_OF(p) = 0; + return p; +} + +VObject* newVObject(const char *id) +{ + return newVObject_(lookupStr(id)); +} + +void deleteVObject(VObject *p) +{ + if (p->id) + unUseStr(p->id); + if (p) + free(p); + p = NULL; +} + +char* dupStr(const char *s, unsigned int size) +{ + char *t; + if (size == 0) { + size = strlen(s); + } + t = (char*)malloc(size+1); + if (t) { + memcpy(t,s,size); + t[size] = 0; + return t; + } + else { + return (char*)0; + } +} + +void deleteStr(const char *p) +{ + if (p) + free((void*)p); + p = NULL; +} + + +static StrItem* newStrItem(const char *s, StrItem *next) +{ + StrItem *p = (StrItem*)malloc(sizeof(StrItem)); + p->next = next; + p->s = s; + p->refCnt = 1; + return p; +} + +static void deleteStrItem(StrItem *p) +{ + if (p) + free((void*)p); + p = NULL; +} + + +/*---------------------------------------------------------------------- + The following function provide accesses to VObject's value. + ----------------------------------------------------------------------*/ + +const char* vObjectName(VObject *o) +{ + return NAME_OF(o); +} + +void setVObjectName(VObject *o, const char* id) +{ + NAME_OF(o) = id; +} + +const char* vObjectStringZValue(VObject *o) +{ + return STRINGZ_VALUE_OF(o); +} + +void setVObjectStringZValue(VObject *o, const char *s) +{ + STRINGZ_VALUE_OF(o) = dupStr(s,0); + VALUE_TYPE(o) = VCVT_STRINGZ; +} + +void setVObjectStringZValue_(VObject *o, const char *s) +{ + STRINGZ_VALUE_OF(o) = s; + VALUE_TYPE(o) = VCVT_STRINGZ; +} + +const wchar_t* vObjectUStringZValue(VObject *o) +{ + return USTRINGZ_VALUE_OF(o); +} + +void setVObjectUStringZValue(VObject *o, const wchar_t *s) +{ + USTRINGZ_VALUE_OF(o) = (wchar_t*) dupStr((char*)s,(uStrLen(s)+1)*2); + VALUE_TYPE(o) = VCVT_USTRINGZ; +} + +void setVObjectUStringZValue_(VObject *o, const wchar_t *s) +{ + USTRINGZ_VALUE_OF(o) = s; + VALUE_TYPE(o) = VCVT_USTRINGZ; +} + +unsigned int vObjectIntegerValue(VObject *o) +{ + return INTEGER_VALUE_OF(o); +} + +void setVObjectIntegerValue(VObject *o, unsigned int i) +{ + INTEGER_VALUE_OF(o) = i; + VALUE_TYPE(o) = VCVT_UINT; +} + +unsigned long vObjectLongValue(VObject *o) +{ + return LONG_VALUE_OF(o); +} + +void setVObjectLongValue(VObject *o, unsigned long l) +{ + LONG_VALUE_OF(o) = l; + VALUE_TYPE(o) = VCVT_ULONG; +} + +void* vObjectAnyValue(VObject *o) +{ + return ANY_VALUE_OF(o); +} + +void setVObjectAnyValue(VObject *o, void *t) +{ + ANY_VALUE_OF(o) = t; + VALUE_TYPE(o) = VCVT_RAW; +} + +VObject* vObjectVObjectValue(VObject *o) +{ + return VOBJECT_VALUE_OF(o); +} + +void setVObjectVObjectValue(VObject *o, VObject *p) +{ + VOBJECT_VALUE_OF(o) = p; + VALUE_TYPE(o) = VCVT_VOBJECT; +} + +int vObjectValueType(VObject *o) +{ + return VALUE_TYPE(o); +} + + +/*---------------------------------------------------------------------- + The following functions can be used to build VObject. + ----------------------------------------------------------------------*/ + +VObject* addVObjectProp(VObject *o, VObject *p) +{ + /* circular link list pointed to tail */ + /* + o {next,id,prop,val} + V + pn {next,id,prop,val} + V + ... + p1 {next,id,prop,val} + V + pn + --> + o {next,id,prop,val} + V + pn {next,id,prop,val} + V + p {next,id,prop,val} + ... + p1 {next,id,prop,val} + V + pn + */ + + VObject *tail = o->prop; + if (tail) { + p->next = tail->next; + o->prop = tail->next = p; + } + else { + o->prop = p->next = p; + } + return p; +} + +VObject* addProp(VObject *o, const char *id) +{ + return addVObjectProp(o,newVObject(id)); +} + +VObject* addProp_(VObject *o, const char *id) +{ + return addVObjectProp(o,newVObject_(id)); +} + +void addList(VObject **o, VObject *p) +{ + p->next = 0; + if (*o == 0) { + *o = p; + } + else { + VObject *t = *o; + while (t->next) { + t = t->next; + } + t->next = p; + } +} + +VObject* nextVObjectInList(VObject *o) +{ + return o->next; +} + +VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size) +{ + VObject *sizeProp; + setVObjectAnyValue(prop, val); + sizeProp = addProp(prop,VCDataSizeProp); + setVObjectLongValue(sizeProp, size); + return prop; +} + +VObject* setValueWithSize(VObject *prop, void *val, unsigned int size) +{ + void *p = dupStr(val,size); + return setValueWithSize_(prop,p,p?size:0); +} + +void initPropIterator(VObjectIterator *i, VObject *o) +{ + i->start = o->prop; + i->next = 0; +} + +void initVObjectIterator(VObjectIterator *i, VObject *o) +{ + i->start = o->next; + i->next = 0; +} + +int moreIteration(VObjectIterator *i) +{ + return (i->start && (i->next==0 || i->next!=i->start)); +} + +VObject* nextVObject(VObjectIterator *i) +{ + if (i->start && i->next != i->start) { + if (i->next == 0) { + i->next = i->start->next; + return i->next; + } + else { + i->next = i->next->next; + return i->next; + } + } + else return (VObject*)0; +} + +VObject* isAPropertyOf(VObject *o, const char *id) +{ + VObjectIterator i; + initPropIterator(&i,o); + while (moreIteration(&i)) { + VObject *each = nextVObject(&i); + if (!strcasecmp(id,each->id)) + return each; + } + return (VObject*)0; +} + +VObject* addGroup(VObject *o, const char *g) +{ + /* + a.b.c + --> + prop(c) + prop(VCGrouping=b) + prop(VCGrouping=a) + */ + char *dot = strrchr(g,'.'); + if (dot) { + VObject *p, *t; + char *gs, *n = dot+1; + gs = dupStr(g,0); /* so we can write to it. */ + /* used to be + * t = p = addProp_(o,lookupProp_(n)); + */ + t = p = addProp_(o,lookupProp(n)); + dot = strrchr(gs,'.'); + *dot = 0; + do { + dot = strrchr(gs,'.'); + if (dot) { + n = dot+1; + *dot=0; + } + else + n = gs; + /* property(VCGroupingProp=n); + * and the value may have VCGrouping property + */ + t = addProp(t,VCGroupingProp); + setVObjectStringZValue(t,lookupProp_(n)); + } while (n != gs); + deleteStr(gs); + return p; + } + else + return addProp_(o,lookupProp(g)); +} + +VObject* addPropValue(VObject *o, const char *p, const char *v) +{ + VObject *prop; + prop = addProp(o,p); + setVObjectUStringZValue_(prop, fakeUnicode(v,0)); + return prop; +} + +VObject* addPropSizedValue_(VObject *o, const char *p, const char *v, + unsigned int size) +{ + VObject *prop; + prop = addProp(o,p); + setValueWithSize_(prop, (void*)v, size); + return prop; +} + +VObject* addPropSizedValue(VObject *o, const char *p, const char *v, + unsigned int size) +{ + return addPropSizedValue_(o,p,dupStr(v,size),size); +} + + + +/*---------------------------------------------------------------------- + The following pretty print a VObject + ----------------------------------------------------------------------*/ + +static void printVObject_(FILE *fp, VObject *o, int level); + +static void indent(FILE *fp, int level) +{ + int i; + for (i=0;i<level*4;i++) { + fputc(' ', fp); + } +} + +static void printValue(FILE *fp, VObject *o, int level) +{ + switch (VALUE_TYPE(o)) { + case VCVT_USTRINGZ: { + char c; + char *t,*s; + s = t = fakeCString(USTRINGZ_VALUE_OF(o)); + fputc('"',fp); + while (c=*t,c) { + fputc(c,fp); + if (c == '\n') indent(fp,level+2); + t++; + } + fputc('"',fp); + deleteStr(s); + break; + } + case VCVT_STRINGZ: { + char c; + const char *s = STRINGZ_VALUE_OF(o); + fputc('"',fp); + while (c=*s,c) { + fputc(c,fp); + if (c == '\n') indent(fp,level+2); + s++; + } + fputc('"',fp); + break; + } + case VCVT_UINT: + fprintf(fp,"%d", INTEGER_VALUE_OF(o)); break; + case VCVT_ULONG: + fprintf(fp,"%ld", LONG_VALUE_OF(o)); break; + case VCVT_RAW: + fprintf(fp,"[raw data]"); break; + case VCVT_VOBJECT: + fprintf(fp,"[vobject]\n"); + printVObject_(fp,VOBJECT_VALUE_OF(o),level+1); + break; + case 0: + fprintf(fp,"[none]"); break; + default: + fprintf(fp,"[unknown]"); break; + } +} + +static void printNameValue(FILE *fp,VObject *o, int level) +{ + indent(fp,level); + if (NAME_OF(o)) { + fprintf(fp,"%s", NAME_OF(o)); + } + if (VALUE_TYPE(o)) { + fputc('=',fp); + printValue(fp,o, level); + } + fprintf(fp,"\n"); +} + +static void printVObject_(FILE *fp, VObject *o, int level) + { + VObjectIterator t; + if (o == 0) { + fprintf(fp,"[NULL]\n"); + return; + } + printNameValue(fp,o,level); + initPropIterator(&t,o); + while (moreIteration(&t)) { + VObject *eachProp = nextVObject(&t); + printVObject_(fp,eachProp,level+1); + } + } + +void printVObject(FILE *fp,VObject *o) +{ + printVObject_(fp,o,0); +} + +void printVObjectToFile(char *fname,VObject *o) +{ + FILE *fp = fopen(fname,"w"); + if (fp) { + printVObject(fp,o); + fclose(fp); + } +} + +void printVObjectsToFile(char *fname,VObject *list) +{ + FILE *fp = fopen(fname,"w"); + if (fp) { + while (list) { + printVObject(fp,list); + list = nextVObjectInList(list); + } + fclose(fp); + } +} + +void cleanVObject(VObject *o) +{ + if (o == 0) return; + if (o->prop) { + /* destroy time: cannot use the iterator here. + Have to break the cycle in the circular link + list and turns it into regular NULL-terminated + list -- since at some point of destruction, + the reference entry for the iterator to work + will not longer be valid. + */ + VObject *p; + p = o->prop->next; + o->prop->next = 0; + do { + VObject *t = p->next; + cleanVObject(p); + p = t; + } while (p); + } + switch (VALUE_TYPE(o)) { + case VCVT_USTRINGZ: + case VCVT_STRINGZ: + case VCVT_RAW: + /* assume they are all allocated by malloc. */ + free((char*)STRINGZ_VALUE_OF(o)); + break; + case VCVT_VOBJECT: + cleanVObject(VOBJECT_VALUE_OF(o)); + break; + } + deleteVObject(o); +} + +void cleanVObjects(VObject *list) +{ + while (list) { + VObject *t = list; + list = nextVObjectInList(list); + cleanVObject(t); + } +} + +/*---------------------------------------------------------------------- + The following is a String Table Facilities. + ----------------------------------------------------------------------*/ + +#define STRTBLSIZE 255 + +static StrItem *strTbl[STRTBLSIZE]; + +static unsigned int hashStr(const char *s) +{ + unsigned int h = 0; + int i; + for (i=0;s[i];i++) { + h += s[i]*i; + } + return h % STRTBLSIZE; +} + +const char* lookupStr(const char *s) +{ + char *newS; + + StrItem *t; + unsigned int h = hashStr(s); + if ((t = strTbl[h]) != 0) { + do { + if (strcasecmp(t->s,s) == 0) { + t->refCnt++; + return t->s; + } + t = t->next; + } while (t); + } + newS = dupStr(s,0); + strTbl[h] = newStrItem(newS,strTbl[h]); + return newS; +} + +void unUseStr(const char *s) +{ + StrItem *cur, *prev; + + unsigned int h = hashStr(s); + cur = strTbl[h]; + prev = cur; + while (cur != 0) { + if (strcasecmp(cur->s,s) == 0) { + cur->refCnt--; + /* if that was the last reference to this string, kill it. */ + if (cur->refCnt == 0) { + if (cur == strTbl[h]) { + strTbl[h] = cur->next; + deleteStr(prev->s); + deleteStrItem(prev); + } else { + prev->next = cur->next; + deleteStr(cur->s); + deleteStrItem(cur); + } + return; + } + } + prev = cur; + cur = cur->next; + } +} + +void cleanStrTbl() +{ + int i; + for (i=0; i<STRTBLSIZE;i++) { + StrItem *t = strTbl[i]; + while (t) { + StrItem *p; + deleteStr(t->s); + p = t; + t = t->next; + deleteStrItem(p); + } + strTbl[i] = 0; + } +} + + +struct PreDefProp { + const char *name; + const char *alias; + const char** fields; + unsigned int flags; + }; + +/* flags in PreDefProp */ +#define PD_BEGIN 0x1 +#define PD_INTERNAL 0x2 + +static const char *adrFields[] = { + VCPostalBoxProp, + VCExtAddressProp, + VCStreetAddressProp, + VCCityProp, + VCRegionProp, + VCPostalCodeProp, + VCCountryNameProp, + 0 +}; + +static const char *nameFields[] = { + VCFamilyNameProp, + VCGivenNameProp, + VCAdditionalNamesProp, + VCNamePrefixesProp, + VCNameSuffixesProp, + NULL + }; + +static const char *orgFields[] = { + VCOrgNameProp, + VCOrgUnitProp, + VCOrgUnit2Prop, + VCOrgUnit3Prop, + VCOrgUnit4Prop, + NULL + }; + +static const char *AAlarmFields[] = { + VCRunTimeProp, + VCSnoozeTimeProp, + VCRepeatCountProp, + VCAudioContentProp, + 0 + }; + +/* ExDate -- has unamed fields */ +/* RDate -- has unamed fields */ + +static const char *DAlarmFields[] = { + VCRunTimeProp, + VCSnoozeTimeProp, + VCRepeatCountProp, + VCDisplayStringProp, + 0 + }; + +static const char *MAlarmFields[] = { + VCRunTimeProp, + VCSnoozeTimeProp, + VCRepeatCountProp, + VCEmailAddressProp, + VCNoteProp, + 0 + }; + +static const char *PAlarmFields[] = { + VCRunTimeProp, + VCSnoozeTimeProp, + VCRepeatCountProp, + VCProcedureNameProp, + 0 + }; + +static struct PreDefProp propNames[] = { + { VC7bitProp, 0, 0, 0 }, + { VC8bitProp, 0, 0, 0 }, + { VCAAlarmProp, 0, AAlarmFields, 0 }, + { VCAdditionalNamesProp, 0, 0, 0 }, + { VCAdrProp, 0, adrFields, 0 }, + { VCAgentProp, 0, 0, 0 }, + { VCAIFFProp, 0, 0, 0 }, + { VCAOLProp, 0, 0, 0 }, + { VCAppleLinkProp, 0, 0, 0 }, + { VCAttachProp, 0, 0, 0 }, + { VCAttendeeProp, 0, 0, 0 }, + { VCATTMailProp, 0, 0, 0 }, + { VCAudioContentProp, 0, 0, 0 }, + { VCAVIProp, 0, 0, 0 }, + { VCBase64Prop, 0, 0, 0 }, + { VCBBSProp, 0, 0, 0 }, + { VCBirthDateProp, 0, 0, 0 }, + { VCBMPProp, 0, 0, 0 }, + { VCBodyProp, 0, 0, 0 }, + { VCBusinessRoleProp, 0, 0, 0 }, + { VCCalProp, 0, 0, PD_BEGIN }, + { VCCaptionProp, 0, 0, 0 }, + { VCCardProp, 0, 0, PD_BEGIN }, + { VCCarProp, 0, 0, 0 }, + { VCCategoriesProp, 0, 0, 0 }, + { VCCellularProp, 0, 0, 0 }, + { VCCGMProp, 0, 0, 0 }, + { VCCharSetProp, 0, 0, 0 }, + { VCCIDProp, VCContentIDProp, 0, 0 }, + { VCCISProp, 0, 0, 0 }, + { VCCityProp, 0, 0, 0 }, + { VCClassProp, 0, 0, 0 }, + { VCCommentProp, 0, 0, 0 }, + { VCCompletedProp, 0, 0, 0 }, + { VCContentIDProp, 0, 0, 0 }, + { VCCountryNameProp, 0, 0, 0 }, + { VCDAlarmProp, 0, DAlarmFields, 0 }, + { VCDataSizeProp, 0, 0, PD_INTERNAL }, + { VCDayLightProp, 0, 0, 0 }, + { VCDCreatedProp, 0, 0, 0 }, + { VCDeliveryLabelProp, 0, 0, 0 }, + { VCDescriptionProp, 0, 0, 0 }, + { VCDIBProp, 0, 0, 0 }, + { VCDisplayStringProp, 0, 0, 0 }, + { VCDomesticProp, 0, 0, 0 }, + { VCDTendProp, 0, 0, 0 }, + { VCDTstartProp, 0, 0, 0 }, + { VCDueProp, 0, 0, 0 }, + { VCEmailAddressProp, 0, 0, 0 }, + { VCEncodingProp, 0, 0, 0 }, + { VCEndProp, 0, 0, 0 }, + { VCEventProp, 0, 0, PD_BEGIN }, + { VCEWorldProp, 0, 0, 0 }, + { VCExNumProp, 0, 0, 0 }, + { VCExDateProp, 0, 0, 0 }, + { VCExpectProp, 0, 0, 0 }, + { VCExtAddressProp, 0, 0, 0 }, + { VCFamilyNameProp, 0, 0, 0 }, + { VCFaxProp, 0, 0, 0 }, + { VCFullNameProp, 0, 0, 0 }, + { VCGeoLocationProp, 0, 0, 0 }, + { VCGeoProp, 0, 0, 0 }, + { VCGIFProp, 0, 0, 0 }, + { VCGivenNameProp, 0, 0, 0 }, + { VCGroupingProp, 0, 0, 0 }, + { VCHomeProp, 0, 0, 0 }, + { VCIBMMailProp, 0, 0, 0 }, + { VCInlineProp, 0, 0, 0 }, + { VCInternationalProp, 0, 0, 0 }, + { VCInternetProp, 0, 0, 0 }, + { VCISDNProp, 0, 0, 0 }, + { VCJPEGProp, 0, 0, 0 }, + { VCLanguageProp, 0, 0, 0 }, + { VCLastModifiedProp, 0, 0, 0 }, + { VCLastRevisedProp, 0, 0, 0 }, + { VCLocationProp, 0, 0, 0 }, + { VCLogoProp, 0, 0, 0 }, + { VCMailerProp, 0, 0, 0 }, + { VCMAlarmProp, 0, MAlarmFields, 0 }, + { VCMCIMailProp, 0, 0, 0 }, + { VCMessageProp, 0, 0, 0 }, + { VCMETProp, 0, 0, 0 }, + { VCModemProp, 0, 0, 0 }, + { VCMPEG2Prop, 0, 0, 0 }, + { VCMPEGProp, 0, 0, 0 }, + { VCMSNProp, 0, 0, 0 }, + { VCNamePrefixesProp, 0, 0, 0 }, + { VCNameProp, 0, nameFields, 0 }, + { VCNameSuffixesProp, 0, 0, 0 }, + { VCNoteProp, 0, 0, 0 }, + { VCOrgNameProp, 0, 0, 0 }, + { VCOrgProp, 0, orgFields, 0 }, + { VCOrgUnit2Prop, 0, 0, 0 }, + { VCOrgUnit3Prop, 0, 0, 0 }, + { VCOrgUnit4Prop, 0, 0, 0 }, + { VCOrgUnitProp, 0, 0, 0 }, + { VCPagerProp, 0, 0, 0 }, + { VCPAlarmProp, 0, PAlarmFields, 0 }, + { VCParcelProp, 0, 0, 0 }, + { VCPartProp, 0, 0, 0 }, + { VCPCMProp, 0, 0, 0 }, + { VCPDFProp, 0, 0, 0 }, + { VCPGPProp, 0, 0, 0 }, + { VCPhotoProp, 0, 0, 0 }, + { VCPICTProp, 0, 0, 0 }, + { VCPMBProp, 0, 0, 0 }, + { VCPostalBoxProp, 0, 0, 0 }, + { VCPostalCodeProp, 0, 0, 0 }, + { VCPostalProp, 0, 0, 0 }, + { VCPowerShareProp, 0, 0, 0 }, + { VCPreferredProp, 0, 0, 0 }, + { VCPriorityProp, 0, 0, 0 }, + { VCProcedureNameProp, 0, 0, 0 }, + { VCProdIdProp, 0, 0, 0 }, + { VCProdigyProp, 0, 0, 0 }, + { VCPronunciationProp, 0, 0, 0 }, + { VCPSProp, 0, 0, 0 }, + { VCPublicKeyProp, 0, 0, 0 }, + { VCQPProp, VCQuotedPrintableProp, 0, 0 }, + { VCQuickTimeProp, 0, 0, 0 }, + { VCQuotedPrintableProp, 0, 0, 0 }, + { VCRDateProp, 0, 0, 0 }, + { VCRegionProp, 0, 0, 0 }, + { VCRelatedToProp, 0, 0, 0 }, + { VCRepeatCountProp, 0, 0, 0 }, + { VCResourcesProp, 0, 0, 0 }, + { VCRNumProp, 0, 0, 0 }, + { VCRoleProp, 0, 0, 0 }, + { VCRRuleProp, 0, 0, 0 }, + { VCRSVPProp, 0, 0, 0 }, + { VCRunTimeProp, 0, 0, 0 }, + { VCSequenceProp, 0, 0, 0 }, + { VCSnoozeTimeProp, 0, 0, 0 }, + { VCStartProp, 0, 0, 0 }, + { VCStatusProp, 0, 0, 0 }, + { VCStreetAddressProp, 0, 0, 0 }, + { VCSubTypeProp, 0, 0, 0 }, + { VCSummaryProp, 0, 0, 0 }, + { VCTelephoneProp, 0, 0, 0 }, + { VCTIFFProp, 0, 0, 0 }, + { VCTimeZoneProp, 0, 0, 0 }, + { VCTitleProp, 0, 0, 0 }, + { VCTLXProp, 0, 0, 0 }, + { VCTodoProp, 0, 0, PD_BEGIN }, + { VCTranspProp, 0, 0, 0 }, + { VCUniqueStringProp, 0, 0, 0 }, + { VCURLProp, 0, 0, 0 }, + { VCURLValueProp, 0, 0, 0 }, + { VCValueProp, 0, 0, 0 }, + { VCVersionProp, 0, 0, 0 }, + { VCVideoProp, 0, 0, 0 }, + { VCVoiceProp, 0, 0, 0 }, + { VCWAVEProp, 0, 0, 0 }, + { VCWMFProp, 0, 0, 0 }, + { VCWorkProp, 0, 0, 0 }, + { VCX400Prop, 0, 0, 0 }, + { VCX509Prop, 0, 0, 0 }, + { VCXRuleProp, 0, 0, 0 }, + { 0,0,0,0 } + }; + + +static struct PreDefProp* lookupPropInfo(const char* str) +{ + /* brute force for now, could use a hash table here. */ + int i; + + for (i = 0; propNames[i].name; i++) + if (strcasecmp(str, propNames[i].name) == 0) { + return &propNames[i]; + } + + return 0; +} + + +const char* lookupProp_(const char* str) +{ + int i; + + for (i = 0; propNames[i].name; i++) + if (strcasecmp(str, propNames[i].name) == 0) { + const char* s; + s = propNames[i].alias?propNames[i].alias:propNames[i].name; + return lookupStr(s); + } + return lookupStr(str); +} + + +const char* lookupProp(const char* str) +{ + int i; + + for (i = 0; propNames[i].name; i++) + if (strcasecmp(str, propNames[i].name) == 0) { + const char *s; + fieldedProp = propNames[i].fields; + s = propNames[i].alias?propNames[i].alias:propNames[i].name; + return lookupStr(s); + } + fieldedProp = 0; + return lookupStr(str); +} + + +/*---------------------------------------------------------------------- + APIs to Output text form. + ----------------------------------------------------------------------*/ +#define OFILE_REALLOC_SIZE 256 +typedef struct OFile { + FILE *fp; + char *s; + int len; + int limit; + int alloc:1; + int fail:1; + } OFile; + + +/* vCalendar files need crlf linebreaks. The disabled functions didn't provide + that. */ +#if 0 + +static void appendsOFile(OFile *fp, const char *s) +{ + int slen; + if (fp->fail) return; + slen = strlen(s); + if (fp->fp) { + fwrite(s,1,slen,fp->fp); + } + else { +stuff: + if (fp->len + slen < fp->limit) { + memcpy(fp->s+fp->len,s,slen); + fp->len += slen; + return; + } + else if (fp->alloc) { + fp->limit = fp->limit + OFILE_REALLOC_SIZE; + if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen; + if (fp->s) + fp->s = realloc(fp->s,fp->limit); + else + fp->s = malloc(fp->limit); + if (fp->s) goto stuff; + } + if (fp->alloc) + free(fp->s); + fp->s = 0; + fp->fail = 1; + } +} + +static void appendcOFile(OFile *fp, char c) +{ + if (fp->fail) return; + if (fp->fp) { + fputc(c,fp->fp); + } + else { +stuff: + if (fp->len+1 < fp->limit) { + fp->s[fp->len] = c; + fp->len++; + return; + } + else if (fp->alloc) { + fp->limit = fp->limit + OFILE_REALLOC_SIZE; + fp->s = realloc(fp->s,fp->limit); + if (fp->s) goto stuff; + } + if (fp->alloc) + free(fp->s); + fp->s = 0; + fp->fail = 1; + } +} + +#else + +static void appendcOFile_(OFile *fp, char c) +{ + if (fp->fail) return; + if (fp->fp) { + fputc(c,fp->fp); + } + else { +stuff: + if (fp->len+1 < fp->limit) { + fp->s[fp->len] = c; + fp->len++; + return; + } + else if (fp->alloc) { + fp->limit = fp->limit + OFILE_REALLOC_SIZE; + fp->s = realloc(fp->s,fp->limit); + if (fp->s) goto stuff; + } + if (fp->alloc) + free(fp->s); + fp->s = 0; + fp->fail = 1; + } +} + +static void appendcOFile(OFile *fp, char c) +{ + if (c == '\n') { + /* write out as <CR><LF> */ + appendcOFile_(fp,0xd); + appendcOFile_(fp,0xa); + } + else + appendcOFile_(fp,c); +} + +static void appendsOFile(OFile *fp, const char *s) +{ + int i, slen; + slen = strlen(s); + for (i=0; i<slen; i++) { + appendcOFile(fp,s[i]); + } +} + +#endif + +static void initOFile(OFile *fp, FILE *ofp) +{ + fp->fp = ofp; + fp->s = 0; + fp->len = 0; + fp->limit = 0; + fp->alloc = 0; + fp->fail = 0; +} + +static void initMemOFile(OFile *fp, char *s, int len) +{ + fp->fp = 0; + fp->s = s; + fp->len = 0; + fp->limit = s?len:0; + fp->alloc = s?0:1; + fp->fail = 0; +} + + +static int writeBase64(OFile *fp, unsigned char *s, long len) +{ + long cur = 0; + int i, numQuads = 0; + unsigned long trip; + unsigned char b; + char quad[5]; +#define MAXQUADS 16 + + quad[4] = 0; + + while (cur < len) { + /* collect the triplet of bytes into 'trip' */ + trip = 0; + for (i = 0; i < 3; i++) { + b = (cur < len) ? *(s + cur) : 0; + cur++; + trip = trip << 8 | b; + } + /* fill in 'quad' with the appropriate four characters */ + for (i = 3; i >= 0; i--) { + b = (unsigned char)(trip & 0x3F); + trip = trip >> 6; + if ((3 - i) < (cur - len)) + quad[i] = '='; /* pad char */ + else if (b < 26) quad[i] = (char)b + 'A'; + else if (b < 52) quad[i] = (char)(b - 26) + 'a'; + else if (b < 62) quad[i] = (char)(b - 52) + '0'; + else if (b == 62) quad[i] = '+'; + else quad[i] = '/'; + } + /* now output 'quad' with appropriate whitespace and line ending */ + appendsOFile(fp, (numQuads == 0 ? " " : "")); + appendsOFile(fp, quad); + appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : ""))); + numQuads = (numQuads + 1) % MAXQUADS; + } + appendcOFile(fp,'\n'); + + return 1; +} + +/* this function really sucks. Too basic. */ +static void writeQPString(OFile *fp, const char *s, int qp) +{ + const char *p = s; + while (*p) { + if (*p == '\n') { + if (p[1]) appendsOFile(fp,"=0A="); + } + if (*p == '=' && qp) + appendsOFile(fp,"=3D"); + else + appendcOFile(fp,*p); + p++; + } +} + +static void writeVObject_(OFile *fp, VObject *o); + +static void writeValue(OFile *fp, VObject *o, unsigned long size) +{ + if (o == 0) return; + switch (VALUE_TYPE(o)) { + case VCVT_USTRINGZ: { + char *s = fakeCString(USTRINGZ_VALUE_OF(o)); + if (isAPropertyOf(o, VCQuotedPrintableProp)) + writeQPString(fp, s, 1); + else + writeQPString(fp, s, 0); + deleteStr(s); + break; + } + case VCVT_STRINGZ: { + if (isAPropertyOf(o, VCQuotedPrintableProp)) + writeQPString(fp, STRINGZ_VALUE_OF(o), 1); + else + writeQPString(fp, STRINGZ_VALUE_OF(o), 0); + break; + } + case VCVT_UINT: { + char buf[16]; + sprintf(buf,"%u", INTEGER_VALUE_OF(o)); + appendsOFile(fp,buf); + break; + } + case VCVT_ULONG: { + char buf[16]; + sprintf(buf,"%lu", LONG_VALUE_OF(o)); + appendsOFile(fp,buf); + break; + } + case VCVT_RAW: { + appendcOFile(fp,'\n'); + writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size); + break; + } + case VCVT_VOBJECT: + appendcOFile(fp,'\n'); + writeVObject_(fp,VOBJECT_VALUE_OF(o)); + break; + } +} + +static void writeAttrValue(OFile *fp, VObject *o) +{ + if (NAME_OF(o)) { + struct PreDefProp *pi; + pi = lookupPropInfo(NAME_OF(o)); + if (pi && ((pi->flags & PD_INTERNAL) != 0)) return; + appendcOFile(fp,';'); + appendsOFile(fp,NAME_OF(o)); + } + else + appendcOFile(fp,';'); + if (VALUE_TYPE(o)) { + appendcOFile(fp,'='); + writeValue(fp,o,0); + } +} + +static void writeGroup(OFile *fp, VObject *o) +{ + char buf1[256]; + char buf2[256]; + strcpy(buf1,NAME_OF(o)); + while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) { + strncpy(buf2,STRINGZ_VALUE_OF(o),sizeof(buf2)); + buf2[sizeof(buf2)] = '\0'; + strncat(buf2,".",sizeof(buf2)-strlen(buf2)-1); + strncat(buf2,buf1,sizeof(buf2)-strlen(buf2)-1); + strcpy(buf1,buf2); + } + appendsOFile(fp,buf1); +} + +static int inList(const char **list, const char *s) +{ + if (list == 0) return 0; + while (*list) { + if (strcasecmp(*list,s) == 0) return 1; + list++; + } + return 0; +} + +static void writeProp(OFile *fp, VObject *o) +{ + if (NAME_OF(o)) { + struct PreDefProp *pi; + VObjectIterator t; + const char **fields_ = 0; + pi = lookupPropInfo(NAME_OF(o)); + if (pi && ((pi->flags & PD_BEGIN) != 0)) { + writeVObject_(fp,o); + return; + } + if (isAPropertyOf(o,VCGroupingProp)) + writeGroup(fp,o); + else + appendsOFile(fp,NAME_OF(o)); + if (pi) fields_ = pi->fields; + initPropIterator(&t,o); + while (moreIteration(&t)) { + const char *s; + VObject *eachProp = nextVObject(&t); + s = NAME_OF(eachProp); + if (strcasecmp(VCGroupingProp,s) && !inList(fields_,s)) + writeAttrValue(fp,eachProp); + } + if (fields_) { + int i = 0, n = 0; + const char** fields = fields_; + /* output prop as fields */ + appendcOFile(fp,':'); + while (*fields) { + VObject *tl = isAPropertyOf(o,*fields); + i++; + if (tl) n = i; + fields++; + } + fields = fields_; + for (i=0;i<n;i++) { + writeValue(fp,isAPropertyOf(o,*fields),0); + fields++; + if (i<(n-1)) appendcOFile(fp,';'); + } + } + } + + if (VALUE_TYPE(o)) { + unsigned long size = 0; + VObject *p = isAPropertyOf(o,VCDataSizeProp); + if (p) size = LONG_VALUE_OF(p); + appendcOFile(fp,':'); + writeValue(fp,o,size); + } + + appendcOFile(fp,'\n'); +} + +static void writeVObject_(OFile *fp, VObject *o) +{ + if (NAME_OF(o)) { + struct PreDefProp *pi; + pi = lookupPropInfo(NAME_OF(o)); + + if (pi && ((pi->flags & PD_BEGIN) != 0)) { + VObjectIterator t; + const char *begin = NAME_OF(o); + appendsOFile(fp,"BEGIN:"); + appendsOFile(fp,begin); + appendcOFile(fp,'\n'); + initPropIterator(&t,o); + while (moreIteration(&t)) { + VObject *eachProp = nextVObject(&t); + writeProp(fp, eachProp); + } + appendsOFile(fp,"END:"); + appendsOFile(fp,begin); + appendsOFile(fp,"\n\n"); + } + } +} + +void writeVObject(FILE *fp, VObject *o) +{ + OFile ofp; + initOFile(&ofp,fp); + writeVObject_(&ofp,o); +} + +void writeVObjectToFile(char *fname, VObject *o) +{ + FILE *fp = fopen(fname,"w"); + if (fp) { + writeVObject(fp,o); + fclose(fp); + } +} + +void writeVObjectsToFile(char *fname, VObject *list) +{ + FILE *fp = fopen(fname,"w"); + if (fp) { + while (list) { + writeVObject(fp,list); + list = nextVObjectInList(list); + } + fclose(fp); + } +} + +char* writeMemVObject(char *s, int *len, VObject *o) +{ + OFile ofp; + initMemOFile(&ofp,s,len?*len:0); + writeVObject_(&ofp,o); + if (len) *len = ofp.len; + appendcOFile(&ofp,0); + return ofp.s; +} + +char* writeMemVObjects(char *s, int *len, VObject *list) +{ + OFile ofp; + initMemOFile(&ofp,s,len?*len:0); + while (list) { + writeVObject_(&ofp,list); + list = nextVObjectInList(list); + } + if (len) *len = ofp.len; + appendcOFile(&ofp,0); + return ofp.s; +} + +/*---------------------------------------------------------------------- + APIs to do fake Unicode stuff. + ----------------------------------------------------------------------*/ +wchar_t* fakeUnicode(const char *ps, int *bytes) +{ + wchar_t *r, *pw; + int len = strlen(ps)+1; + + pw = r = (wchar_t*)malloc(sizeof(wchar_t)*len); + if (bytes) + *bytes = len * sizeof(wchar_t); + + while (*ps) { + if (*ps == '\n') + *pw = (wchar_t)0x2028; + else if (*ps == '\r') + *pw = (wchar_t)0x2029; + else + *pw = (wchar_t)(unsigned char)*ps; + ps++; pw++; + } + *pw = (wchar_t)0; + + return r; +} + +int uStrLen(const wchar_t *u) +{ + int i = 0; + while (*u != (wchar_t)0) { u++; i++; } + return i; +} + +char* fakeCString(const wchar_t *u) +{ + char *s, *t; + int len = uStrLen(u) + 1; + t = s = (char*)malloc(len+1); + while (*u) { + if (*u == (wchar_t)0x2028) + *t = '\n'; + else if (*u == (wchar_t)0x2029) + *t = '\r'; + else + *t = (char)*u; + u++; t++; + } + *t = 0; + return s; +} + +/* end of source file vobject.c */ diff --git a/libkcal/versit/vobject.h b/libkcal/versit/vobject.h new file mode 100644 index 0000000..0ec8b31 --- a/dev/null +++ b/libkcal/versit/vobject.h @@ -0,0 +1,384 @@ +/*************************************************************************** +(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. + +For purposes of this license notice, the term Licensors shall mean, +collectively, Apple Computer, Inc., AT&T Corp., International +Business Machines Corporation and Siemens Rolm Communications Inc. +The term Licensor shall mean any of the Licensors. + +Subject to acceptance of the following conditions, permission is hereby +granted by Licensors without the need for written agreement and without +license or royalty fees, to use, copy, modify and distribute this +software for any purpose. + +The above copyright notice and the following four paragraphs must be +reproduced in all copies of this software and any software including +this software. + +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE +ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR +MODIFICATIONS. + +IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, +INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT +OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +The software is provided with RESTRICTED RIGHTS. Use, duplication, or +disclosure by the government are subject to restrictions set forth in +DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. + +***************************************************************************/ + +/* + +The vCard/vCalendar C interface is implemented in the set +of files as follows: + +vcc.y, yacc source, and vcc.c, the yacc output you will use +implements the core parser + +vobject.c implements an API that insulates the caller from +the parser and changes in the vCard/vCalendar BNF + +port.h defines compilation environment dependent stuff + +vcc.h and vobject.h are header files for their .c counterparts + +vcaltmp.h and vcaltmp.c implement vCalendar "macro" functions +which you may find useful. + +test.c is a standalone test driver that exercises some of +the features of the APIs provided. Invoke test.exe on a +VCARD/VCALENDAR input text file and you will see the pretty +print output of the internal representation (this pretty print +output should give you a good idea of how the internal +representation looks like -- there is one such output in the +following too). Also, a file with the .out suffix is generated +to show that the internal representation can be written back +in the original text format. + +For more information on this API see the readme.txt file +which accompanied this distribution. + + Also visit: + + http://www.versit.com + http://www.ralden.com + +*/ + + +#ifndef __VOBJECT_H__ +#define __VOBJECT_H__ 1 + + +#include "port.h" +#include <stdlib.h> +#include <stdio.h> + +#if defined(__CPLUSPLUS__) || defined(__cplusplus) +extern "C" { +#endif + + +#define VC7bitProp "7BIT" +#define VC8bitProp "8BIT" +#define VCAAlarmProp "AALARM" +#define VCAdditionalNamesProp "ADDN" +#define VCAdrProp "ADR" +#define VCAgentProp "AGENT" +#define VCAIFFProp "AIFF" +#define VCAOLProp "AOL" +#define VCAppleLinkProp "APPLELINK" +#define VCAttachProp "ATTACH" +#define VCAttendeeProp "ATTENDEE" +#define VCATTMailProp "ATTMAIL" +#define VCAudioContentProp "AUDIOCONTENT" +#define VCAVIProp "AVI" +#define VCBase64Prop "BASE64" +#define VCBBSProp "BBS" +#define VCBirthDateProp "BDAY" +#define VCBMPProp "BMP" +#define VCBodyProp "BODY" +#define VCBusinessRoleProp "ROLE" +#define VCCalProp "VCALENDAR" +#define VCCaptionProp "CAP" +#define VCCardProp "VCARD" +#define VCCarProp "CAR" +#define VCCategoriesProp "CATEGORIES" +#define VCCellularProp "CELL" +#define VCCGMProp "CGM" +#define VCCharSetProp "CS" +#define VCCIDProp "CID" +#define VCCISProp "CIS" +#define VCCityProp "L" +#define VCClassProp "CLASS" +#define VCCommentProp "NOTE" +#define VCCompletedProp "COMPLETED" +#define VCContentIDProp "CONTENT-ID" +#define VCCountryNameProp "C" +#define VCDAlarmProp "DALARM" +#define VCDataSizeProp "DATASIZE" +#define VCDayLightProp "DAYLIGHT" +#define VCDCreatedProp "DCREATED" +#define VCDeliveryLabelProp "LABEL" +#define VCDescriptionProp "DESCRIPTION" +#define VCDIBProp "DIB" +#define VCDisplayStringProp "DISPLAYSTRING" +#define VCDomesticProp "DOM" +#define VCDTendProp "DTEND" +#define VCDTstartProp "DTSTART" +#define VCDueProp "DUE" +#define VCEmailAddressProp "EMAIL" +#define VCEncodingProp "ENCODING" +#define VCEndProp "END" +#define VCEventProp "VEVENT" +#define VCEWorldProp "EWORLD" +#define VCExNumProp "EXNUM" +#define VCExDateProp "EXDATE" +#define VCExpectProp "EXPECT" +#define VCExtAddressProp "EXT ADD" +#define VCFamilyNameProp "F" +#define VCFaxProp "FAX" +#define VCFullNameProp "FN" +#define VCGeoProp "GEO" +#define VCGeoLocationProp "GEO" +#define VCGIFProp "GIF" +#define VCGivenNameProp "G" +#define VCGroupingProp "Grouping" +#define VCHomeProp "HOME" +#define VCIBMMailProp "IBMMail" +#define VCInlineProp "INLINE" +#define VCInternationalProp "INTL" +#define VCInternetProp "INTERNET" +#define VCISDNProp "ISDN" +#define VCJPEGProp "JPEG" +#define VCLanguageProp "LANG" +#define VCLastModifiedProp "LAST-MODIFIED" +#define VCLastRevisedProp "REV" +#define VCLocationProp "LOCATION" +#define VCLogoProp "LOGO" +#define VCMailerProp "MAILER" +#define VCMAlarmProp "MALARM" +#define VCMCIMailProp "MCIMAIL" +#define VCMessageProp "MSG" +#define VCMETProp "MET" +#define VCModemProp "MODEM" +#define VCMPEG2Prop "MPEG2" +#define VCMPEGProp "MPEG" +#define VCMSNProp "MSN" +#define VCNamePrefixesProp "NPRE" +#define VCNameProp "N" +#define VCNameSuffixesProp "NSUF" +#define VCNoteProp "NOTE" +#define VCOrgNameProp "ORGNAME" +#define VCOrgProp "ORG" +#define VCOrgUnit2Prop "OUN2" +#define VCOrgUnit3Prop "OUN3" +#define VCOrgUnit4Prop "OUN4" +#define VCOrgUnitProp "OUN" +#define VCPagerProp "PAGER" +#define VCPAlarmProp "PALARM" +#define VCParcelProp "PARCEL" +#define VCPartProp "PART" +#define VCPCMProp "PCM" +#define VCPDFProp "PDF" +#define VCPGPProp "PGP" +#define VCPhotoProp "PHOTO" +#define VCPICTProp "PICT" +#define VCPMBProp "PMB" +#define VCPostalBoxProp "BOX" +#define VCPostalCodeProp "PC" +#define VCPostalProp "POSTAL" +#define VCPowerShareProp "POWERSHARE" +#define VCPreferredProp "PREF" +#define VCPriorityProp "PRIORITY" +#define VCProcedureNameProp "PROCEDURENAME" +#define VCProdIdProp "PRODID" +#define VCProdigyProp "PRODIGY" +#define VCPronunciationProp "SOUND" +#define VCPSProp "PS" +#define VCPublicKeyProp "KEY" +#define VCQPProp "QP" +#define VCQuickTimeProp "QTIME" +#define VCQuotedPrintableProp "QUOTED-PRINTABLE" +#define VCRDateProp "RDATE" +#define VCRegionProp "R" +#define VCRelatedToProp "RELATED-TO" +#define VCRepeatCountProp "REPEATCOUNT" +#define VCResourcesProp "RESOURCES" +#define VCRNumProp "RNUM" +#define VCRoleProp "ROLE" +#define VCRRuleProp "RRULE" +#define VCRSVPProp "RSVP" +#define VCRunTimeProp "RUNTIME" +#define VCSequenceProp "SEQUENCE" +#define VCSnoozeTimeProp "SNOOZETIME" +#define VCStartProp "START" +#define VCStatusProp "STATUS" +#define VCStreetAddressProp "STREET" +#define VCSubTypeProp "SUBTYPE" +#define VCSummaryProp "SUMMARY" +#define VCTelephoneProp "TEL" +#define VCTIFFProp "TIFF" +#define VCTimeZoneProp "TZ" +#define VCTitleProp "TITLE" +#define VCTLXProp "TLX" +#define VCTodoProp "VTODO" +#define VCTranspProp "TRANSP" +#define VCUniqueStringProp "UID" +#define VCURLProp "URL" +#define VCURLValueProp "URLVAL" +#define VCValueProp "VALUE" +#define VCVersionProp "VERSION" +#define VCVideoProp "VIDEO" +#define VCVoiceProp "VOICE" +#define VCWAVEProp "WAVE" +#define VCWMFProp "WMF" +#define VCWorkProp "WORK" +#define VCX400Prop "X400" +#define VCX509Prop "X509" +#define VCXRuleProp "XRULE" + +/* extensions for KOrganizer / KPilot */ +#define KPilotIdProp "X-PILOTID" +#define KPilotStatusProp "X-PILOTSTAT" + +/* extensions for iMIP / iTIP */ +#define ICOrganizerProp "X-ORGANIZER" +#define ICMethodProp "X-METHOD" +#define ICRequestStatusProp "X-REQUEST-STATUS" + +typedef struct VObject VObject; + +typedef union ValueItem { + const char *strs; + const wchar_t *ustrs; + unsigned int i; + unsigned long l; + void *any; + VObject *vobj; + } ValueItem; + +struct VObject { + VObject *next; + const char *id; + VObject *prop; + unsigned short valType; + ValueItem val; + }; + +typedef struct StrItem StrItem; + +struct StrItem { + StrItem *next; + const char *s; + unsigned int refCnt; + }; + +typedef struct VObjectIterator { + VObject* start; + VObject* next; + } VObjectIterator; + +extern VObject* newVObject(const char *id); +extern void deleteVObject(VObject *p); +extern char* dupStr(const char *s, unsigned int size); +extern void deleteStr(const char *p); +extern void unUseStr(const char *s); + +extern void setVObjectName(VObject *o, const char* id); +extern void setVObjectStringZValue(VObject *o, const char *s); +extern void setVObjectStringZValue_(VObject *o, const char *s); +extern void setVObjectUStringZValue(VObject *o, const wchar_t *s); +extern void setVObjectUStringZValue_(VObject *o, const wchar_t *s); +extern void setVObjectIntegerValue(VObject *o, unsigned int i); +extern void setVObjectLongValue(VObject *o, unsigned long l); +extern void setVObjectAnyValue(VObject *o, void *t); +extern VObject* setValueWithSize(VObject *prop, void *val, unsigned int size); +extern VObject* setValueWithSize_(VObject *prop, void *val, unsigned int size); + +extern const char* vObjectName(VObject *o); +extern const char* vObjectStringZValue(VObject *o); +extern const wchar_t* vObjectUStringZValue(VObject *o); +extern unsigned int vObjectIntegerValue(VObject *o); +extern unsigned long vObjectLongValue(VObject *o); +extern void* vObjectAnyValue(VObject *o); +extern VObject* vObjectVObjectValue(VObject *o); +extern void setVObjectVObjectValue(VObject *o, VObject *p); + +extern VObject* addVObjectProp(VObject *o, VObject *p); +extern VObject* addProp(VObject *o, const char *id); +extern VObject* addProp_(VObject *o, const char *id); +extern VObject* addPropValue(VObject *o, const char *p, const char *v); +extern VObject* addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size); +extern VObject* addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size); +extern VObject* addGroup(VObject *o, const char *g); +extern void addList(VObject **o, VObject *p); + +extern VObject* isAPropertyOf(VObject *o, const char *id); + +extern VObject* nextVObjectInList(VObject *o); +extern void initPropIterator(VObjectIterator *i, VObject *o); +extern int moreIteration(VObjectIterator *i); +extern VObject* nextVObject(VObjectIterator *i); + +extern char* writeMemVObject(char *s, int *len, VObject *o); +extern char* writeMemVObjects(char *s, int *len, VObject *list); + +extern const char* lookupStr(const char *s); +extern void cleanStrTbl(); + +extern void cleanVObject(VObject *o); +extern void cleanVObjects(VObject *list); + +extern const char* lookupProp(const char* str); +extern const char* lookupProp_(const char* str); + +extern wchar_t* fakeUnicode(const char *ps, int *bytes); +extern int uStrLen(const wchar_t *u); +extern char* fakeCString(const wchar_t *u); + +extern void printVObjectToFile(char *fname,VObject *o); +extern void printVObjectsToFile(char *fname,VObject *list); +extern void writeVObjectToFile(char *fname, VObject *o); +extern void writeVObjectsToFile(char *fname, VObject *list); + +extern int vObjectValueType(VObject *o); + +/* return type of vObjectValueType: */ +#define VCVT_NOVALUE 0 + /* if the VObject has no value associated with it. */ +#define VCVT_STRINGZ 1 + /* if the VObject has value set by setVObjectStringZValue. */ +#define VCVT_USTRINGZ 2 + /* if the VObject has value set by setVObjectUStringZValue. */ +#define VCVT_UINT 3 + /* if the VObject has value set by setVObjectIntegerValue. */ +#define VCVT_ULONG 4 + /* if the VObject has value set by setVObjectLongValue. */ +#define VCVT_RAW 5 + /* if the VObject has value set by setVObjectAnyValue. */ +#define VCVT_VOBJECT 6 + /* if the VObject has value set by setVObjectVObjectValue. */ + +extern const char** fieldedProp; + +extern void printVObject(FILE *fp,VObject *o); +extern void writeVObject(FILE *fp, VObject *o); + + +#if defined(__CPLUSPLUS__) || defined(__cplusplus) +} +#endif + +#endif /* __VOBJECT_H__ */ + + diff --git a/libkdepim/addresseeview.cpp b/libkdepim/addresseeview.cpp new file mode 100644 index 0000000..deafd34 --- a/dev/null +++ b/libkdepim/addresseeview.cpp @@ -0,0 +1,282 @@ +/* + This file is part of libkdepim. + + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kabc/address.h> +#include <kabc/addressee.h> +#include <kabc/phonenumber.h> +#include <kglobal.h> +//US#include <kglobalsettings.h> +#include <kiconloader.h> +#include <klocale.h> +//US #include <kstringhandler.h> +#include <qscrollview.h> +#include <qregexp.h> +#include <qfile.h> +#include <qapplication.h> + + +#include "addresseeview.h" + +using namespace KPIM; + +AddresseeView::AddresseeView( QWidget *parent, const char *name ) +//US : KTextBrowser( parent, name ) + : QTextBrowser( parent, name ) + + +{ +//US setWrapPolicy( QTextEdit::AtWordBoundary ); + setLinkUnderline( false ); + // setVScrollBarMode( QScrollView::AlwaysOff ); + //setHScrollBarMode( QScrollView::AlwaysOff ); + +//US QStyleSheet *sheet = styleSheet(); +//US QStyleSheetItem *link = sheet->item( "a" ); +//US link->setColor( KGlobalSettings::linkColor() ); + +} + +void AddresseeView::setAddressee( const KABC::Addressee& addr ) +{ + mAddressee = addr; + + // clear view + setText( QString::null ); + + if ( mAddressee.isEmpty() ) + return; + + QString name = ( mAddressee.formattedName().isEmpty() ? + mAddressee.assembledName() : mAddressee.formattedName() ); + + QString dynamicPart; + + KABC::PhoneNumber::List phones = mAddressee.phoneNumbers(); + KABC::PhoneNumber::List::ConstIterator phoneIt; + for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) { + dynamicPart += QString( + "<tr><td align=\"right\"><b>%1</b></td>" + "<td align=\"left\">%2</td></tr>" ) + .arg( KABC::PhoneNumber::typeLabel( (*phoneIt).type() ) ) + .arg( (*phoneIt).number() ); + } + + QStringList emails = mAddressee.emails(); + QStringList::ConstIterator emailIt; + QString type = i18n( "Email" ); + for ( emailIt = emails.begin(); emailIt != emails.end(); ++emailIt ) { + dynamicPart += QString( + "<tr><td align=\"right\"><b>%1</b></td>" + "<td align=\"left\"><a href=\"mailto:%2\">%3</a></td></tr>" ) + .arg( type ) + .arg( *emailIt ) + .arg( *emailIt ); + type = i18n( "Other" ); + } + + if ( !mAddressee.url().url().isEmpty() ) { + dynamicPart += QString( + "<tr><td align=\"right\"><b>%1</b></td>" + "<td align=\"left\">%2</td></tr>" ) + .arg( i18n( "Homepage" ) ) +//US .arg( KStringHandler::tagURLs( mAddressee.url().url() ) ); + .arg( mAddressee.url().url() ); + //qDebug("AddresseeView::setAddressee has to be verified."); + } + + KABC::Address::List addresses = mAddressee.addresses(); + KABC::Address::List::ConstIterator addrIt; + for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) { + if ( true /*(*addrIt).label().isEmpty()*/ ) { + QString formattedAddress = (*addrIt).formattedAddress().stripWhiteSpace(); +//US formattedAddress = formattedAddress.replace( '\n', "<br>" ); + //qDebug("adresss %s ",formattedAddress.latin1() ); + formattedAddress = formattedAddress.replace( QRegExp("\n"), "<br>" ); + //qDebug("AddresseeView::setAddressee has to be verified."); + + dynamicPart += QString( + "<tr><td align=\"right\"><b>%1</b></td>" + "<td align=\"left\">%2</td></tr>" ) + .arg( KABC::Address::typeLabel( (*addrIt).type() ) ) + .arg( formattedAddress ); + } else { + + dynamicPart += QString( + "<tr><td align=\"right\"><b>%1</b></td>" + "<td align=\"left\">%2</td></tr>" ) + .arg( KABC::Address::typeLabel( (*addrIt).type() ) ) +//US .arg( (*addrIt).label().replace( '\n', "<br>" ) ); + .arg( (*addrIt).label() /*replace( QRegExp("\n"), "<br>" )*/ ); + + } + } + + QString notes; + if ( !mAddressee.note().isEmpty() ) { + notes = QString( + "<tr>" + "<td align=\"right\" valign=\"top\"><b>%1:</b></td>" // note label + "<td align=\"left\">%2</td>" // note + "</tr>" ).arg( i18n( "Notes" ) ) +//US .arg( mAddressee.note().replace( '\n', "<br>" ) ); + .arg( mAddressee.note().replace( QRegExp("\n"), "<br>" ) ); + //qDebug("AddresseeView::setAddressee has to be verified."); + } + + QString aRole = ""; + QString aOrga = ""; + if ( true /*!mAddressee.role().isEmpty()*/ ) { + aRole = "<tr>" + "<td align=\"left\">" + mAddressee.role() + "</td>" + "</tr>"; + } + if ( true /*!mAddressee.organization().isEmpty()*/ ) { + aOrga = "<tr>" + "<td align=\"left\">" + mAddressee.organization() + "</td>" ; + "</tr>"; + } + mText = ""; + QString picString = ""; + KABC::Picture picture = mAddressee.photo(); + bool picAvailintern = false; + bool picAvailUrl = false; + if (! picture.undefined() ) { + picAvailintern = (picture.isIntern() && !picture.data().isNull()); + picAvailUrl = !picture.isIntern() && QFile::exists(picture.url() ); + } + if ( picAvailUrl || picAvailintern || QApplication::desktop()->width() > 320 ) { + if ( picAvailintern ) { + QMimeSourceFactory::defaultFactory()->setImage( "myimage", picture.data() ); + } else { + if ( picAvailUrl ) { + QMimeSourceFactory::defaultFactory()->setPixmap( "myimage", QPixmap( picture.url() )); + } else { + QMimeSourceFactory::defaultFactory()->setPixmap( "myimage", KGlobal::iconLoader()->loadIcon( "package_toys", KIcon::Desktop, 128 ) ); + } + } + picString = "<img src=\"myimage\" width=\"50\" height=\"70\">"; + mText = QString::fromLatin1( + "<html>" + "<body text=\"%1\" bgcolor=\"%2\">" // text and background color + "<table>" + "<tr>" + "<td rowspan=\"3\" align=\"right\" valign=\"top\">" + "%3" + "</td>" + "<td align=\"left\"><font size=\"+2\"><b>%4</b></font></td>" // name + "</tr>" + "%5" // role + "%6" // organization + "<td colspan=\"2\"> </td>" + "%7" // dynamic part + "%8" // notes + "</table>" + "</body>" + "</html>") +//US + .arg( /*KGlobalSettings::textColor().name()*/ "black" ) +//US + .arg( /*KGlobalSettings::baseColor().name()*/ "white" ) + .arg( picString ) + .arg( name ) + .arg( aRole ) + .arg( aOrga ) + .arg( dynamicPart ) + .arg( notes ); + + } else { // no picture! + +mText = "<table width=\"100%\">\n"; + //mText += "<tr bgcolor=\"#3679AD\"><td><h2>"; +#ifdef DESKTOP_VERSION + mText += "<tr bgcolor=\"#5699CD\"><td align=\"left\"><h1>"; +#else + mText += "<tr bgcolor=\"#5699CD\"><td align=\"left\"><h2>"; +#endif + +#ifdef DESKTOP_VERSION + mText += "<font color=\"#FFFFFF\"> <em>" + name+"</em></font></h1>"; +#else + mText += "<font color=\"#FFFFFF\"> <em>" + name +"</em></font></h2>"; +#endif + mText += "</td></tr>\n<tr bgcolor=\"#EAF8FA\"><td>"; + + mText += "<table><td colspan=\"2\"> </td>"; + /* + mText += QString("<tr><td align=\"right\"><b2>%1</b2></td>" + "<td align=\"left\"><b>%2</b></td></tr>" ) + .arg( i18n(" ") ) + .arg( name ); + */ + if ( ! mAddressee.role().isEmpty() ) + mText += QString("<tr><td align=\"right\"><b>%1</b></td>" + "<td align=\"left\">%2</td></tr>" ) + .arg( i18n(" ") ) + .arg( mAddressee.role()); + if ( ! mAddressee.organization().isEmpty() ) + mText += QString("<tr><td align=\"right\"><b>%1</b></td>" + "<td align=\"left\">%2</td></tr>" ) + .arg( i18n(" ") ) + .arg( mAddressee.organization()); + mText += dynamicPart; + mText += notes; + mText += "</table>"; + + } + + // at last display it... + setText( mText ); +} + +KABC::Addressee AddresseeView::addressee() const +{ + return mAddressee; +} +void AddresseeView::addTag(const QString & tag,const QString & text) +{ + if ( text.isEmpty() ) + return; + int number=text.contains("\n"); + QString str = "<" + tag + ">"; + QString tmpText=text; + QString tmpStr=str; + if(number !=-1) + { + if (number > 0) { + int pos=0; + QString tmp; + for(int i=0;i<=number;i++) { + pos=tmpText.find("\n"); + tmp=tmpText.left(pos); + tmpText=tmpText.right(tmpText.length()-pos-1); + tmpStr+=tmp+"<br>"; + } + } + else tmpStr += tmpText; + tmpStr+="</" + tag + ">"; + mText.append(tmpStr); + } + else + { + str += text + "</" + tag + ">"; + mText.append(str); + } +} diff --git a/libkdepim/addresseeview.h b/libkdepim/addresseeview.h new file mode 100644 index 0000000..598ef0d --- a/dev/null +++ b/libkdepim/addresseeview.h @@ -0,0 +1,60 @@ +/* + This file is part of libkdepim. + + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KPIM_ADDRESSEEVIEW_H +#define KPIM_ADDRESSEEVIEW_H + +#include <kabc/addressee.h> + +//US #include <ktextbrowser.h> +#include <qtextbrowser.h> + +namespace KPIM { + +//US class AddresseeView : public KTextBrowser +class AddresseeView : public QTextBrowser +{ + public: + AddresseeView( QWidget *parent = 0, const char *name = 0 ); + + /** + Sets the addressee object. The addressee is displayed immediately. + + @param addr The addressee object. + */ + void setAddressee( const KABC::Addressee& addr ); + + /** + Returns the current addressee object. + */ + KABC::Addressee addressee() const; + + private: + KABC::Addressee mAddressee; + QString mText; + void addTag(const QString & tag,const QString & text); + class AddresseeViewPrivate; + AddresseeViewPrivate *d; +}; + +} + +#endif diff --git a/libkdepim/categoryeditdialog.cpp b/libkdepim/categoryeditdialog.cpp new file mode 100644 index 0000000..87172c1 --- a/dev/null +++ b/libkdepim/categoryeditdialog.cpp @@ -0,0 +1,135 @@ +/* + This file is part of libkdepim. + Copyright (c) 2000, 2001, 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qstringlist.h> +#include <qlineedit.h> +#include <qlistview.h> +#include <qheader.h> +#include <qpushbutton.h> +#include <qapplication.h> + +#include "kpimprefs.h" + +#include "categoryeditdialog.h" + +using namespace KPIM; + +CategoryEditDialog::CategoryEditDialog( KPimPrefs *prefs, QWidget* parent, + const char* name, bool modal, + WFlags fl ) + : CategoryEditDialog_base( parent, name, modal, fl ), + mPrefs( prefs ) +{ + mCategories->header()->hide(); + + QStringList::Iterator it; + bool categoriesExist=false; + for (it = mPrefs->mCustomCategories.begin(); + it != mPrefs->mCustomCategories.end(); ++it ) { + new QListViewItem(mCategories,*it); + categoriesExist=true; + } + + connect(mCategories,SIGNAL(selectionChanged(QListViewItem *)), + SLOT(editItem(QListViewItem *))); + connect(mEdit,SIGNAL(textChanged ( const QString & )),this,SLOT(slotTextChanged(const QString &))); + mButtonRemove->setEnabled(categoriesExist); + mButtonModify->setEnabled(categoriesExist); + mButtonAdd->setEnabled(!mEdit->text().isEmpty()); + if ( QApplication::desktop()->width() > 460 ) + resize( 300, 360 ); +} + +/* + * Destroys the object and frees any allocated resources + */ +CategoryEditDialog::~CategoryEditDialog() +{ + // no need to delete child widgets, Qt does it all for us +} + +void CategoryEditDialog::slotTextChanged(const QString &text) +{ + mButtonAdd->setEnabled(!text.isEmpty()); +} + +void CategoryEditDialog::add() +{ + if (!mEdit->text().isEmpty()) { + new QListViewItem(mCategories,mEdit->text()); + mEdit->setText(""); + mButtonRemove->setEnabled(mCategories->childCount()>0); + mButtonModify->setEnabled(mCategories->childCount()>0); + } +} + +void CategoryEditDialog::remove() +{ + if (mCategories->currentItem()) { + delete mCategories->currentItem(); + mButtonRemove->setEnabled(mCategories->childCount()>0); + mButtonModify->setEnabled(mCategories->childCount()>0); + } +} + +void CategoryEditDialog::modify() +{ + if (!mEdit->text().isEmpty()) { + if (mCategories->currentItem()) { + mCategories->currentItem()->setText(0,mEdit->text()); + } + } +} +void CategoryEditDialog::accept() +{ + slotOk(); +} + +void CategoryEditDialog::slotOk() +{ + slotApply(); + QDialog::accept(); +} + +void CategoryEditDialog::slotApply() +{ + mPrefs->mCustomCategories.clear(); + + QListViewItem *item = mCategories->firstChild(); + while(item) { + mPrefs->mCustomCategories.append(item->text(0)); + item = item->nextSibling(); + } + mPrefs->writeConfig(); + + emit categoryConfigChanged(); +} + +void CategoryEditDialog::editItem(QListViewItem *item) +{ + mEdit->setText(item->text(0)); + mButtonRemove->setEnabled(true); + mButtonModify->setEnabled(true); +} + +#include "categoryeditdialog.moc" diff --git a/libkdepim/categoryeditdialog.h b/libkdepim/categoryeditdialog.h new file mode 100644 index 0000000..027cb98 --- a/dev/null +++ b/libkdepim/categoryeditdialog.h @@ -0,0 +1,62 @@ +/* + This file is part of libkdepim. + Copyright (c) 2000, 2001, 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KPIM_CATEGORYEDITDIALOG_H +#define KPIM_CATEGORYEDITDIALOG_H + +#include <libkdepim/categoryeditdialog_base.h> + +class KPimPrefs; + +namespace KPIM { + +class CategoryEditDialog : public CategoryEditDialog_base +{ + Q_OBJECT + public: + CategoryEditDialog( KPimPrefs *prefs, QWidget* parent = 0, + const char* name = 0, + bool modal = FALSE, WFlags fl = 0 ); + ~CategoryEditDialog(); + + public slots: + void add(); + void remove(); + void modify(); + void accept(); + + void slotOk(); + void slotApply(); + + signals: + void categoryConfigChanged(); + + private slots: + void editItem(QListViewItem *item); + void slotTextChanged(const QString &text); + + KPimPrefs *mPrefs; +}; + +} + +#endif diff --git a/libkdepim/categoryeditdialog.moc b/libkdepim/categoryeditdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libkdepim/categoryeditdialog.moc diff --git a/libkdepim/categoryeditdialog_base.cpp b/libkdepim/categoryeditdialog_base.cpp new file mode 100644 index 0000000..ac99190 --- a/dev/null +++ b/libkdepim/categoryeditdialog_base.cpp @@ -0,0 +1,154 @@ +#include <klocale.h> +/**************************************************************************** +** Form implementation generated from reading ui file '/build/kde/cvs/korge/kdepim/libkdepim/categoryeditdialog_base.ui' +** +** Created: Sat Mar 29 21:46:09 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#include "categoryeditdialog_base.h" + +#include <qvariant.h> +#include <qheader.h> +#include <qlineedit.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a CategoryEditDialog_base as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +CategoryEditDialog_base::CategoryEditDialog_base( QWidget* parent, const char* name, bool modal, WFlags fl ) + : QDialog( parent, name, true, fl ) + +{ + if ( !name ) + setName( "CategoryEditDialog_base" ); + CategoryEditDialog_baseLayout = new QGridLayout( this, 1, 1, 11, 6, "CategoryEditDialog_baseLayout"); + + mEdit = new QLineEdit( this, "mEdit" ); + + CategoryEditDialog_baseLayout->addMultiCellWidget( mEdit, 1, 1, 0, 1 ); + + Layout13 = new QHBoxLayout( 0, 0, 6, "Layout13"); + + // mButtonHelp = new QPushButton( this, "mButtonHelp" ); + //mButtonHelp->setAutoDefault( TRUE ); + //Layout13->addWidget( mButtonHelp ); + //QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + //Layout13->addItem( spacer ); + + //mApply = new QPushButton( this, "mApply" ); + // Layout13->addWidget( mApply ); + + mButtonOk = new QPushButton( this, "mButtonOk" ); + mButtonOk->setAutoDefault( TRUE ); + mButtonOk->setDefault( TRUE ); + Layout13->addWidget( mButtonOk ); + + mButtonCancel = new QPushButton( this, "mButtonCancel" ); + mButtonCancel->setAutoDefault( TRUE ); + Layout13->addWidget( mButtonCancel ); + + CategoryEditDialog_baseLayout->addMultiCellLayout( Layout13, 2, 2, 0, 1 ); + + mCategories = new QListView( this, "mCategories" ); + mCategories->addColumn( tr2i18n( "Category" ) ); + + CategoryEditDialog_baseLayout->addWidget( mCategories, 0, 0 ); + + layout103 = new QVBoxLayout( 0, 0, 6, "layout103"); + + mButtonAdd = new QPushButton( this, "mButtonAdd" ); + layout103->addWidget( mButtonAdd ); + + mButtonModify = new QPushButton( this, "mButtonModify" ); + layout103->addWidget( mButtonModify ); + + mButtonRemove = new QPushButton( this, "mButtonRemove" ); + layout103->addWidget( mButtonRemove ); + QSpacerItem* spacer_2 = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding ); + layout103->addItem( spacer_2 ); + + CategoryEditDialog_baseLayout->addLayout( layout103, 0, 1 ); + languageChange(); + resize( sizeHint() ); + + // signals and slots connections + connect( mButtonCancel, SIGNAL( clicked() ), this, SLOT( reject() ) ); + connect( mButtonAdd, SIGNAL( clicked() ), this, SLOT( add() ) ); + connect( mButtonModify, SIGNAL( clicked() ), this, SLOT( modify() ) ); + connect( mButtonRemove, SIGNAL( clicked() ), this, SLOT( remove() ) ); + connect( mButtonOk, SIGNAL( clicked() ), this, SLOT( slotOk() ) ); + //connect( mApply, SIGNAL( clicked() ), this, SLOT( slotApply() ) ); + + // tab order + // setTabOrder( mCategories, mEdit ); +// setTabOrder( mEdit, mButtonAdd ); +// setTabOrder( mButtonAdd, mButtonModify ); +// setTabOrder( mButtonModify, mButtonRemove ); +// setTabOrder( mButtonRemove, mButtonHelp ); +// setTabOrder( mButtonHelp, mApply ); +// setTabOrder( mApply, mButtonOk ); +// setTabOrder( mButtonOk, mButtonCancel ); +} + +/* + * Destroys the object and frees any allocated resources + */ +CategoryEditDialog_base::~CategoryEditDialog_base() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void CategoryEditDialog_base::languageChange() +{ + setCaption( tr2i18n( "Edit Categories" ) ); + // mButtonHelp->setText( tr2i18n( "&Help" ) ); + // mApply->setText( tr2i18n( "&Apply" ) ); + mButtonOk->setText( tr2i18n( "&OK" ) ); + mButtonCancel->setText( tr2i18n( "&Cancel" ) ); + mCategories->header()->setLabel( 0, tr2i18n( "Category" ) ); + mButtonAdd->setText( tr2i18n( "A&dd" ) ); + mButtonModify->setText( tr2i18n( "&Modify" ) ); + mButtonRemove->setText( tr2i18n( "&Remove" ) ); +} + +void CategoryEditDialog_base::add() +{ + qWarning( "CategoryEditDialog_base::add(): Not implemented yet" ); +} + +void CategoryEditDialog_base::modify() +{ + qWarning( "CategoryEditDialog_base::modify(): Not implemented yet" ); +} + +void CategoryEditDialog_base::slotApply() +{ + qWarning( "CategoryEditDialog_base::slotApply(): Not implemented yet" ); +} + +void CategoryEditDialog_base::remove() +{ + qWarning( "CategoryEditDialog_base::remove(): Not implemented yet" ); +} + +void CategoryEditDialog_base::slotOk() +{ + qWarning( "CategoryEditDialog_base::slotOk(): Not implemented yet" ); +} + +#include "categoryeditdialog_base.moc" diff --git a/libkdepim/categoryeditdialog_base.h b/libkdepim/categoryeditdialog_base.h new file mode 100644 index 0000000..5557ad0 --- a/dev/null +++ b/libkdepim/categoryeditdialog_base.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** Form interface generated from reading ui file '/build/kde/cvs/korge/kdepim/libkdepim/categoryeditdialog_base.ui' +** +** Created: Sat Mar 29 21:45:20 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#ifndef CATEGORYEDITDIALOG_BASE_H +#define CATEGORYEDITDIALOG_BASE_H + +#include <qvariant.h> +#include <qdialog.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QLineEdit; +class QListView; +class QListViewItem; +class QPushButton; + +class CategoryEditDialog_base : public QDialog +{ + Q_OBJECT + +public: + CategoryEditDialog_base( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~CategoryEditDialog_base(); + + QLineEdit* mEdit; + QPushButton* mButtonHelp; + QPushButton* mApply; + QPushButton* mButtonOk; + QPushButton* mButtonCancel; + QListView* mCategories; + QPushButton* mButtonAdd; + QPushButton* mButtonModify; + QPushButton* mButtonRemove; + +public slots: + virtual void add(); + virtual void modify(); + virtual void slotApply(); + virtual void remove(); + virtual void slotOk(); + +protected: + QGridLayout* CategoryEditDialog_baseLayout; + QHBoxLayout* Layout13; + QVBoxLayout* layout103; + +protected slots: + virtual void languageChange(); +}; + +#endif // CATEGORYEDITDIALOG_BASE_H diff --git a/libkdepim/categoryeditdialog_base.moc b/libkdepim/categoryeditdialog_base.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libkdepim/categoryeditdialog_base.moc diff --git a/libkdepim/categoryselectdialog.cpp b/libkdepim/categoryselectdialog.cpp new file mode 100644 index 0000000..7b0aced --- a/dev/null +++ b/libkdepim/categoryselectdialog.cpp @@ -0,0 +1,173 @@ +/* + This file is part of libkdepim. + Copyright (c) 2000, 2001, 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qlistview.h> +#include <qpushbutton.h> +#include <qheader.h> +#include <qapp.h> +#include <qmessagebox.h> + + +#include <libkdepim/categoryeditdialog.h> +#include "categoryselectdialog.h" + +#include "kpimprefs.h" + +using namespace KPIM; + +CategorySelectDialog::CategorySelectDialog( KPimPrefs *prefs, QWidget* parent, + const char* name, + bool modal, WFlags fl ) + : CategorySelectDialog_base( parent, name, true, fl ), + mPrefs( prefs ) +{ + mCategories->header()->hide(); + + setCategories(); + + connect(mButtonEdit,SIGNAL(clicked()),this, SLOT(editCategoriesDialog())); + if ( qApp->desktop()->height() < 321 ) + setMaximumHeight( QApplication::desktop()->height() - 50 ); + else + setMaximumHeight( QApplication::desktop()->height() - 80 ); + if ( QApplication::desktop()->width() > 460 ) + resize( 260, 360 ); +} +void CategorySelectDialog::editCategoriesDialog() +{ + KPIM::CategoryEditDialog* ced = new KPIM::CategoryEditDialog(mPrefs,this ); + + ced->exec(); + delete ced; + setCategories(); +} +void CategorySelectDialog::setCategories() +{ + mCategories->clear(); + mCategoryList.clear(); + + QStringList::Iterator it; + + for (it = mPrefs->mCustomCategories.begin(); + it != mPrefs->mCustomCategories.end(); ++it ) { + new QCheckListItem(mCategories,*it,QCheckListItem::CheckBox); + } +} + +CategorySelectDialog::~CategorySelectDialog() +{ +} + +void CategorySelectDialog::setSelected(const QStringList &selList) +{ + clear(); + + QStringList::ConstIterator it; + QStringList notFound; + bool found = false; + for (it=selList.begin();it!=selList.end();++it) { + //qDebug(" CategorySelectDialog::setSelected("); + QCheckListItem *item = (QCheckListItem *)mCategories->firstChild(); + while (item) { + if (item->text() == *it) { + item->setOn(true); + found = true; + break; + } + item = (QCheckListItem *)item->nextSibling(); + } +// if ( ! found ) { + +//emit updateCategoriesGlobal(); +// QMessageBox::information( this, "KO/E: Information!", +// "Categories found, which were not\n" +// "in list of categories!\n" +// "message", +// "OK", "", 0, +// 0, 1 ); +// setSelected(selList); +// return; +// } + } +} + +QStringList CategorySelectDialog::selectedCategories() const +{ + return mCategoryList; +} + +void CategorySelectDialog::slotApply() +{ + QStringList categories; + QCheckListItem *item = (QCheckListItem *)mCategories->firstChild(); + while (item) { + if (item->isOn()) { + categories.append(item->text()); + } + item = (QCheckListItem *)item->nextSibling(); + } + + QString categoriesStr = categories.join(","); + + mCategoryList = categories; + + emit categoriesSelected(categories); + emit categoriesSelected(categoriesStr); +} +void CategorySelectDialog::accept() +{ + slotOk(); +} + +void CategorySelectDialog::slotOk() +{ + slotApply(); + QDialog::accept(); +} + +void CategorySelectDialog::clear() +{ + QCheckListItem *item = (QCheckListItem *)mCategories->firstChild(); + while (item) { + item->setOn(false); + item = (QCheckListItem *)item->nextSibling(); + } +} + +void CategorySelectDialog::updateCategoryConfig() +{ + QStringList selected; + QCheckListItem *item = (QCheckListItem *)mCategories->firstChild(); + while (item) { + if (item->isOn()) { + selected.append(item->text()); + } + item = (QCheckListItem *)item->nextSibling(); + } + + setCategories(); + + setSelected(selected); +} + +#include "categoryselectdialog.moc" diff --git a/libkdepim/categoryselectdialog.h b/libkdepim/categoryselectdialog.h new file mode 100644 index 0000000..8507dc4 --- a/dev/null +++ b/libkdepim/categoryselectdialog.h @@ -0,0 +1,69 @@ +/* + This file is part of libkdepim. + Copyright (c) 2000, 2001, 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KPIM_CATEGORYSELECTDIALOG_H +#define KPIM_CATEGORYSELECTDIALOG_H + +#include <libkdepim/categoryselectdialog_base.h> + +class KPimPrefs; + +namespace KPIM { + +class CategorySelectDialog : public CategorySelectDialog_base +{ + Q_OBJECT + public: + CategorySelectDialog( KPimPrefs *prefs, QWidget* parent = 0, + const char* name = 0, + bool modal = FALSE, WFlags fl = 0 ); + ~CategorySelectDialog(); + + void setCategories(); + void setSelected(const QStringList &selList); + + QStringList selectedCategories() const; + + public slots: + void slotOk(); + void slotApply(); + void clear(); + void accept(); + void editCategoriesDialog(); + void updateCategoryConfig(); + + signals: + void categoriesSelected(const QString &); + void categoriesSelected(const QStringList &); + void editCategories(); + + private: + KPimPrefs *mPrefs; + QStringList mCategoryList; + + class CategorySelectDialogPrivate; + CategorySelectDialogPrivate *d; +}; + +} + +#endif diff --git a/libkdepim/categoryselectdialog.moc b/libkdepim/categoryselectdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libkdepim/categoryselectdialog.moc diff --git a/libkdepim/categoryselectdialog_base.cpp b/libkdepim/categoryselectdialog_base.cpp new file mode 100644 index 0000000..5e5fa72 --- a/dev/null +++ b/libkdepim/categoryselectdialog_base.cpp @@ -0,0 +1,128 @@ +#include <klocale.h> +/**************************************************************************** +** Form implementation generated from reading ui file '/build/kde/cvs/korge/kdepim/libkdepim/categoryselectdialog_base.ui' +** +** Created: Sat Mar 29 21:46:05 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#include "categoryselectdialog_base.h" + +#include <qvariant.h> +#include <qheader.h> +#include <qlistview.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a CategorySelectDialog_base as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +CategorySelectDialog_base::CategorySelectDialog_base( QWidget* parent, const char* name, bool modal, WFlags fl ) + : QDialog( parent, name, modal, fl ) + +{ + if ( !name ) + setName( "CategorySelectDialog_base" ); + CategorySelectDialog_baseLayout = new QVBoxLayout( this, 11, 6, "CategorySelectDialog_baseLayout"); + + mCategories = new QListView( this, "mCategories" ); + mCategories->addColumn( i18n( "Category" ) ); + CategorySelectDialog_baseLayout->addWidget( mCategories ); + + Layout12 = new QHBoxLayout( 0, 0, 6, "Layout12"); + + mClear = new QPushButton( this, "mClear" ); + Layout12->addWidget( mClear ); + // QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + //Layout12->addItem( spacer ); + + mButtonEdit = new QPushButton( this, "mButtonEdit" ); + Layout12->addWidget( mButtonEdit ); + CategorySelectDialog_baseLayout->addLayout( Layout12 ); + + Layout11 = new QHBoxLayout( 0, 0, 6, "Layout11"); + + //mButtonHelp = new QPushButton( this, "mButtonHelp" ); + //Layout11->addWidget( mButtonHelp ); + //QSpacerItem* spacer_2 = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + // Layout11->addItem( spacer_2 ); + + //mApply = new QPushButton( this, "mApply" ); + // Layout11->addWidget( mApply ); + + mButtonOk = new QPushButton( this, "mButtonOk" ); + mButtonOk->setOn( FALSE ); + mButtonOk->setDefault( TRUE ); + Layout11->addWidget( mButtonOk ); + + mButtonCancel = new QPushButton( this, "mButtonCancel" ); + Layout11->addWidget( mButtonCancel ); + CategorySelectDialog_baseLayout->addLayout( Layout11 ); + languageChange(); + // resize( sizeHint() ); + + // signals and slots connections + connect( mButtonCancel, SIGNAL( clicked() ), this, SLOT( reject() ) ); + connect( mButtonOk, SIGNAL( clicked() ), this, SLOT( slotOk() ) ); + connect( mClear, SIGNAL( clicked() ), this, SLOT( clear() ) ); + //connect( mApply, SIGNAL( clicked() ), this, SLOT( slotApply() ) ); + + // tab order + setTabOrder( mCategories, mClear ); + setTabOrder( mClear, mButtonEdit ); + setTabOrder( mButtonEdit, mButtonOk );//mButtonHelp ); + // setTabOrder( mButtonHelp, mApply ); + // setTabOrder( mApply, mButtonOk ); + setTabOrder( mButtonOk, mButtonCancel ); + // showMaximized(); + //raise(); +} + +/* + * Destroys the object and frees any allocated resources + */ +CategorySelectDialog_base::~CategorySelectDialog_base() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void CategorySelectDialog_base::languageChange() +{ + setCaption( i18n( "Select Categories" ) ); + mCategories->header()->setLabel( 0, tr2i18n( "Category" ) ); + mClear->setText( i18n( " &Deselect All " ) ); + mButtonEdit->setText( i18n( " &Edit Categories " ) ); + // mButtonHelp->setText( tr2i18n( "&Help" ) ); + //mApply->setText( i18n( "&Apply" ) ); + mButtonOk->setText( i18n( "&OK" ) ); + mButtonCancel->setText( i18n( "&Cancel" ) ); +} + +void CategorySelectDialog_base::clear() +{ + qWarning( "CategorySelectDialog_base::clear(): Not implemented yet" ); +} + +void CategorySelectDialog_base::slotApply() +{ + qWarning( "CategorySelectDialog_base::slotApply(): Not implemented yet" ); +} + +void CategorySelectDialog_base::slotOk() +{ + qWarning( "CategorySelectDialog_base::slotOk(): Not implemented yet" ); +} + +#include "categoryselectdialog_base.moc" diff --git a/libkdepim/categoryselectdialog_base.h b/libkdepim/categoryselectdialog_base.h new file mode 100644 index 0000000..af905ed --- a/dev/null +++ b/libkdepim/categoryselectdialog_base.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** Form interface generated from reading ui file '/build/kde/cvs/korge/kdepim/libkdepim/categoryselectdialog_base.ui' +** +** Created: Sat Mar 29 21:45:20 2003 +** by: The User Interface Compiler () +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#ifndef CATEGORYSELECTDIALOG_BASE_H +#define CATEGORYSELECTDIALOG_BASE_H + +#include <qvariant.h> +#include <qdialog.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QListView; +class QListViewItem; +class QPushButton; + +class CategorySelectDialog_base : public QDialog +{ + Q_OBJECT + +public: + CategorySelectDialog_base( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~CategorySelectDialog_base(); + + QListView* mCategories; + QPushButton* mClear; + QPushButton* mButtonEdit; + QPushButton* mButtonHelp; + QPushButton* mApply; + QPushButton* mButtonOk; + QPushButton* mButtonCancel; + +public slots: + virtual void clear(); + virtual void slotApply(); + virtual void slotOk(); + +protected: + QVBoxLayout* CategorySelectDialog_baseLayout; + QHBoxLayout* Layout12; + QHBoxLayout* Layout11; + +protected slots: + virtual void languageChange(); +}; + +#endif // CATEGORYSELECTDIALOG_BASE_H diff --git a/libkdepim/categoryselectdialog_base.moc b/libkdepim/categoryselectdialog_base.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libkdepim/categoryselectdialog_base.moc diff --git a/libkdepim/kdateedit.cpp b/libkdepim/kdateedit.cpp new file mode 100644 index 0000000..60bd2cf --- a/dev/null +++ b/libkdepim/kdateedit.cpp @@ -0,0 +1,486 @@ +/* + This file is part of libkdepim. + + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qapplication.h> +#include <qevent.h> +#include <qlineedit.h> +#include <qpixmap.h> +#include <qpushbutton.h> + +#include <kdatepicker.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <knotifyclient.h> +#include <qpalette.h> + +#include "kdateedit.h" +#include "kdateedit.moc" + +KDateEdit::KDateEdit(QWidget *parent, const char *name, bool withoutDP ) + : QHBox(parent, name) +{ + dateFormShort = true; + withoutDp = withoutDP; + mDateEdit = new QLineEdit(this); + mDateEdit->setText(KGlobal::locale()->formatDate(QDate::currentDate(),dateFormShort)); + setFocusProxy(mDateEdit); + mDateEdit->installEventFilter(this); + + // Highlight Background and Textcolor + QPalette palette = QWidget::palette(); + unsigned char red, green, blue; + red = palette.color( QPalette::Normal , QColorGroup::Background ).red() - 10; + green = palette.color( QPalette::Normal , QColorGroup::Background ).green() - 10; + blue = palette.color( QPalette::Normal , QColorGroup::Background ).blue() - 10; + palette.setColor( QColorGroup::Highlight, QColor(red,green,blue) ); + palette.setColor( QColorGroup::HighlightedText, palette.color( QPalette::Normal , QColorGroup::Foreground ) ); + mDateEdit->setPalette( palette ); + + if ( withoutDP ) { + mDateFrame = 0; + mDateButton = 0; + mDatePicker = 0; + } else { + QPixmap pixmap = SmallIcon("smallcal"); + mDateButton = new QPushButton(this); + mDateButton->setPixmap(pixmap); + + mDateFrame = new QVBox(0,0,WType_Popup); + // mDateFrame->setFrameStyle(QFrame::PopupPanel | QFrame::Raised); + mDateFrame->setFrameStyle( QFrame::WinPanel |QFrame::Raised ); + mDateFrame->setLineWidth(3); + mDateFrame->hide(); + + mDatePicker = new KDatePicker(mDateFrame,QDate::currentDate()); + connect(mDatePicker,SIGNAL(dateEntered(QDate)),SLOT(setDate(QDate))); + connect(mDatePicker,SIGNAL(dateEntered(QDate)),SIGNAL(dateChanged(QDate))); + connect(mDatePicker,SIGNAL(dateSelected(QDate)),SLOT(setDate(QDate))); + connect(mDatePicker,SIGNAL(dateSelected(QDate)),SIGNAL(dateChanged(QDate))); + connect(mDatePicker,SIGNAL(dateSelected(QDate)),mDateFrame,SLOT(hide())); + connect(mDateButton,SIGNAL(clicked()),SLOT(toggleDatePicker())); + + //mDateFrame->resize( 400, 300 ); + + } + connect(mDateEdit,SIGNAL(returnPressed()),SLOT(lineEnterPressed())); + connect(mDateEdit,SIGNAL(textChanged(const QString &)), + SLOT(textChanged(const QString &))); + + // Create the keyword list. This will be used to match against when the user + // enters information. + mKeywordMap[i18n("tomorrow")] = 1; + mKeywordMap[i18n("today")] = 0; + mKeywordMap[i18n("yesterday")] = -1; + + /* + * This loop uses some math tricks to figure out the offset in days + * to the next date the given day of the week occurs. There + * are two cases, that the new day is >= the current day, which means + * the new day has not occured yet or that the new day < the current day, + * which means the new day is already passed (so we need to find the + * day in the next week). + */ + QString dayName; + int currentDay = QDate::currentDate().dayOfWeek(); + for (int i = 1; i <= 7; ++i) + { + dayName = KGlobal::locale()->weekDayName(i).lower(); + if (i >= currentDay) + mKeywordMap[dayName] = i - currentDay; + else + mKeywordMap[dayName] = 7 - currentDay + i; + } + + mTextChanged = false; + mHandleInvalid = false; + QWidget::setTabOrder( mDateEdit, mDateButton ); +} + +KDateEdit::~KDateEdit() +{ + delete mDateFrame; +} + +void KDateEdit::setDate(QDate newDate) +{ + if (!newDate.isValid() && !mHandleInvalid) + return; + if ( readDate() == newDate ) + return; + QString dateString = ""; + if(newDate.isValid()) + dateString = KGlobal::locale()->formatDate( newDate, dateFormShort ); + + mTextChanged = false; + + // We do not want to generate a signal here, since we explicity setting + // the date + bool b = mDateEdit->signalsBlocked(); + mDateEdit->blockSignals(true); + mDateEdit->setText(dateString); + mDateEdit->blockSignals(b); +} + +void KDateEdit::setDate( QDate date,int *cpos,const int key ,const bool dateFormShort) +{ + QString dateForm = dateFormShort ? + KGlobal::locale()->dateFormatShort() : + KGlobal::locale()->dateFormat(); + + int begin = dateForm.find("%"); + int space = 0; + int allStrLength = 0; + int strLength = 0; + int repeat = 0; + + // witch? Day, Month or Year switch? + while(1){ + switch ( dateForm.at(begin + 1).latin1() ) + { + case 'd':// 16 (month day) + strLength = 2; //Ok + break; + case 'm':// 01 (month) + strLength = 2; //Ok + break; + case 'a':// Mon (Weekday) + strLength = KGlobal::locale()->weekDayName(date.dayOfWeek(), true).length(); + break; + case 'A':// Monday (Weekday) + strLength = KGlobal::locale()->weekDayName(date.dayOfWeek(), false).length(); + break; + case 'b':// Jan (monthName) + strLength = KGlobal::locale()->monthName(date.month(), true).length(); + break; + case 'B':// January (monthName) + strLength = KGlobal::locale()->monthName(date.month(), false).length(); + break; + case 'y':// 04 (year short) + strLength = 2; //Ok + break; + case 'Y':// 2004 (year) + strLength = 4; //Ok + break; + default: + break; + } + space = begin - (repeat++ * 2); + // all select? then dayswitch + if( (mDateEdit->text().length() == mDateEdit->markedText().length() ) && + ( (dateForm.at(begin + 1).latin1() == 'd') || + (dateForm.at(begin + 1).latin1() == 'a') || + (dateForm.at(begin + 1).latin1() == 'A') ) ) { + break; + } + // mDateEdit-StringPos == CursorPosition(cpos) then break and set date + if( ( (space + allStrLength) <= *cpos && *cpos <= (space + allStrLength + strLength) ) || *cpos < begin ) { + break; + } + allStrLength += strLength; + begin = dateForm.find("%", begin +1); + } + + // set date + switch ( dateForm.at(begin + 1).latin1() ) { + case 'd': + case 'a': + case 'A': + if(key == Key_Up) { + setDate( date.addDays( 1 ) ); + } + else if(key == Key_Down) { + setDate( date.addDays( -1 ) ); + } + maxDay = readDate().day(); + break; + case 'm': + case 'b': + case 'B': + if(key == Key_Up) { + int year = ((date.month()+1)>12)?date.year()+1:date.year(); + int month = ((date.month()+1)>12)?1:date.month()+1; + int day = (QDate(year,month,1).daysInMonth()<maxDay)?QDate(year,month,1).daysInMonth():maxDay; + setDate( QDate( year, month, day ) ); + } else if(key == Key_Down) { + int year = ((date.month()-1)<1)?date.year()-1:date.year(); + int month = ((date.month()-1)<1)?12:date.month()-1; + int day = (QDate(year,month,1).daysInMonth()<maxDay)?QDate(year,month,1).daysInMonth():maxDay; + setDate( QDate( year, month, day ) ); + } + break; + case 'y': + case 'Y': + if(key == Key_Up) { + setDate( QDate( date.year() + 1, date.month() , date.day()) ); + } + else if(key == Key_Down) { + setDate( QDate( date.year() - 1, date.month() , date.day()) ); + } + break; +/* default: + if(key == Key_Up) { + setDate( date.addDays( 1 ) ); + } else if(key == Key_Down) { + setDate( date.addDays( -1 ) ); + } + break;*/ + } + + date = readDate(); + begin = dateForm.find("%"); + int allSelectStrLength = 0; + int selectStrLength = 0; + + // set selection do new date an set cursor at end of selection + for(int i = 0; i < repeat; i++){ + switch ( dateForm.at(begin + 1).latin1() ) + { + case 'd':// 16 (month day) + selectStrLength = 2; //Ok + break; + case 'm':// 01 (month) + selectStrLength = 2; //Ok + break; + case 'a':// Mon (Weekday short) + selectStrLength = KGlobal::locale()->weekDayName(date.dayOfWeek(), true).length(); + break; + case 'A':// Monday (Weekday) + selectStrLength = KGlobal::locale()->weekDayName(date.dayOfWeek(), false).length(); + break; + case 'b':// Jan (monthName short) + selectStrLength = KGlobal::locale()->monthName(date.month(), true).length(); + break; + case 'B':// January (monthName) + selectStrLength = KGlobal::locale()->monthName(date.month(), false).length(); + break; + case 'y':// 04 (year short) + selectStrLength = 2; //Ok + break; + case 'Y':// 2004 (year) + selectStrLength = 4; //Ok + break; + default: + break; + } + space = begin - (i * 2); + allSelectStrLength += selectStrLength; + begin = dateForm.find("%", begin +1); + } + // set selection from begin of date + setSelect( space + allSelectStrLength - selectStrLength , selectStrLength); + *cpos = space + allSelectStrLength; + emit(dateChanged(date)); + + return; +} + +void KDateEdit::setHandleInvalid(bool handleInvalid) +{ + mHandleInvalid = handleInvalid; +} + +void KDateEdit::setEnabled(bool on) +{ + mDateEdit->setEnabled(on); + mDateButton->setEnabled(on); +} + +QDate KDateEdit::date() const +{ + QDate date = readDate(); + + if (date.isValid() || mHandleInvalid) { + return date; + } else { + KNotifyClient::beep(); + return QDate::currentDate(); + } +} + +void KDateEdit::keyPressEvent(QKeyEvent *e) +{ + QDate date = readDate(); + int cpos = mDateEdit->cursorPosition(); + + switch(e->key()) + { + case Key_Escape: + mDateEdit->deselect(); + case Key_Tab: + QHBox::keyPressEvent(e); + break; + case Key_Up: + // when date invalid then set to currend and return + if(!date.isValid()) { + date = QDate::currentDate(); + setDate(date); + mDateEdit->setCursorPosition(cpos); + emit(dateChanged(date)); + QString text = i18n( "You entered an invalid date!\n Date changed to current date." ); + KMessageBox::information( 0, text ); + return; + } + setDate(date, &cpos, Key_Up, dateFormShort); + break; + case Key_Down: + // when date invalid then set to current and return + if(!date.isValid()) { + date = QDate::currentDate(); + setDate(date); + mDateEdit->setCursorPosition(cpos); + emit(dateChanged(date)); + QString text = i18n( "You entered an invalid date!\n Date changed to current date." ); + KMessageBox::information( 0, text ); + return; + } + setDate(date, &cpos, Key_Down, dateFormShort); + break; + default: + QHBox::keyPressEvent(e); + break; + } // switch + mDateEdit->setCursorPosition(cpos); +} + +void KDateEdit::setSelect( int from, int to ) +{ +// return; + mDateEdit->setSelection( from , to ); +} + +void KDateEdit::toggleDatePicker() +{ + if( mDateFrame->isVisible() ) { + mDateFrame->hide(); + } else { + QPoint tmpPoint = mapToGlobal(mDateButton->geometry().bottomRight()); + QSize datepickersize = mDatePicker->sizeHint(); + + if ( tmpPoint.x() < 7+datepickersize.width() ) tmpPoint.setX( 7+datepickersize.width() ); + + int h = QApplication::desktop()->height(); + + if ( tmpPoint.y() + datepickersize.height() > h ) tmpPoint.setY( h - datepickersize.height() ); + + mDateFrame->setGeometry(tmpPoint.x()-datepickersize.width()-7, tmpPoint.y(), + datepickersize.width()+2*mDateFrame->lineWidth(), datepickersize.height()+2*mDateFrame->lineWidth()); + + QDate date = readDate(); + if(date.isValid()) { + mDatePicker->setDate(date); + } else { + mDatePicker->setDate(QDate::currentDate()); + } + mDateFrame->show(); + } +} + + +void KDateEdit::lineEnterPressed() +{ + QDate date = readDate(); + + if(date.isValid()) + { + // Update the edit. This is needed if the user has entered a + // word rather than the actual date. + setDate(date); + emit(dateChanged(date)); + emit returnPressed(); + } + else + { + if ( withoutDp ) { + KNotifyClient::beep(); + } else { + if ( !mDateEdit->text().isEmpty() ) { + mTextChanged = false; + QString text = i18n( "You entered an invalid date!\n Will use current date instead." ); + if ( KMessageBox::warningContinueCancel( 0, text ) == KMessageBox::Continue ) { + setDate( QDate::currentDate() ); + emit dateChanged( QDate::currentDate() ); + } + } + } + } +} + +bool KDateEdit::inputIsValid() +{ + return readDate().isValid(); +} + +QDate KDateEdit::readDate() const +{ + QString text = mDateEdit->text(); + QDate date; + + if (mKeywordMap.contains(text.lower())) + { + date = QDate::currentDate().addDays(mKeywordMap[text.lower()]); + } + else + { + date = KGlobal::locale()->readDate(text); + } + + return date; +} + +bool KDateEdit::eventFilter(QObject *, QEvent *e) +{ + // We only process the focus out event if the text has changed + // since we got focus + if ((e->type() == QEvent::FocusOut) && mTextChanged) + { + lineEnterPressed(); + mTextChanged = false; + } + // switch dateFormShort by double klick with mouse + else if (e->type() == QEvent::MouseButtonDblClick) + { + dateFormShort = dateFormShort?false:true; + mDateEdit->setText(KGlobal::locale()->formatDate(readDate(),dateFormShort)); + } + else if (e->type() == QEvent::FocusIn) + { + maxDay = readDate().day(); + } + + return false; +} + +void KDateEdit::textChanged(const QString &) +{ + if(mHandleInvalid && mDateEdit->text().stripWhiteSpace().isEmpty()) { + QDate date; //invalid date + emit(dateChanged(date)); + } else { + mTextChanged = true; + } + maxDay = readDate().day(); +} diff --git a/libkdepim/kdateedit.h b/libkdepim/kdateedit.h new file mode 100644 index 0000000..742d843 --- a/dev/null +++ b/libkdepim/kdateedit.h @@ -0,0 +1,140 @@ +/* + This file is part of libkdepim. + + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KDATEEDIT_H +#define KDATEEDIT_H + +#include <qhbox.h> +#include <qvbox.h> +#include <qdatetime.h> +#include <qmap.h> + +class QLineEdit; +class QPushButton; +class QObject; +class QEvent; +class KDatePicker; +class KDateValidator; + +/** +* A date editing widget that consists of a line edit followed by +* a small push button. The line edit contains the date in text form, +* and the push button will display a 'popup' style date picker. +* +* This widget also supports advanced features like allowing the user +* to type in the day name to get the date. The following keywords +* are supported (in the native language): tomorrow, yesturday, today, +* monday, tuesday, wednesday, thursday, friday, saturday, sunday. +* +* @author Cornelius Schumacher <schumacher@kde.org> +* @author Mike Pilone <mpilone@slac.com> +*/ +class KDateEdit : public QHBox +{ + Q_OBJECT + public: + KDateEdit(QWidget *parent=0, const char *name=0, bool withoutDP = false ); + virtual ~KDateEdit(); + + /** @return True if the date in the text edit is valid, + * false otherwise. This will not modify the display of the date, + * but only check for validity. + */ + bool inputIsValid(); + + /** @return The date entered. This will not + * modify the display of the date, but only return it. + */ + QDate date() const; + + /** @param handleInvalid If true the date edit accepts invalid dates + * and displays them as the empty ("") string. It also returns an invalid date. + * If false (default) invalid dates are not accepted and instead the date + * of today will be returned. + */ + void setHandleInvalid(bool handleInvalid); + + /** Checks for a focus out event. The display of the date is updated + * to display the proper date when the focus leaves. + */ + virtual bool eventFilter(QObject *o, QEvent *e); + + signals: + /** This signal is emitted whenever the user modifies the date. This + * may not get emitted until the user presses enter in the line edit or + * focus leaves the widget (ie: the user confirms their selection). + */ + void dateChanged(QDate); + void returnPressed(); + public slots: + /** Sets the date. + * + * @param date The new date to display. This date must be valid or + * it will not be displayed. + */ + void setDate(QDate date); + // set Date with key_up key_down to relation of cursor Position + // and set selection from begin to end of single date + void setDate(QDate, int *cpos, const int, const bool); + + /** Sets the date edit to be enabled or disabled (grayed out) + * + * @param on Enabled if true, disabled if false + */ + void setEnabled(bool on); + + protected slots: + void toggleDatePicker(); + void lineEnterPressed(); + void textChanged(const QString &); + + private: + /** Reads the text from the line edit. If the text is a keyword, the + * word will be translated to a date. If the text is not a keyword, the + * text will be interpreted as a date. + */ + QDate readDate() const; + + /** Maps the text that the user can enter to the offset in days from + * today. For example, the text 'tomorrow' is mapped to +1. + */ + QMap<QString, int> mKeywordMap; + bool mTextChanged; + bool mHandleInvalid; + + QPushButton *mDateButton; + QLineEdit *mDateEdit; + KDatePicker *mDatePicker; + QVBox *mDateFrame; + int maxDay; + bool withoutDp; + + protected: + virtual void keyPressEvent(QKeyEvent *qke); + void setSelect ( int, int ); + bool dateFormShort; + char lengthMonthName; + +}; + +#endif diff --git a/libkdepim/kdateedit.moc b/libkdepim/kdateedit.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libkdepim/kdateedit.moc diff --git a/libkdepim/kdatepicker.cpp b/libkdepim/kdatepicker.cpp new file mode 100644 index 0000000..6e5ec0f --- a/dev/null +++ b/libkdepim/kdatepicker.cpp @@ -0,0 +1,472 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kdatepicker.h" +#include <kglobal.h> +#include <kapplication.h> +#include <klocale.h> +#include <kiconloader.h> +#include <qframe.h> +#include <qpainter.h> +#include <qdialog.h> +#include <qtoolbutton.h> +#include <qfont.h> +#include <qapplication.h> +#include <qlineedit.h> +#include <qvalidator.h> +#include <kdebug.h> +#include <knotifyclient.h> +#include "kdatetbl.h" +#include "kdateedit.h" +#include "kdatepicker.moc" + + +KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name) + : QFrame(parent,name), + yearForward(new QToolButton(this)), + yearBackward(new QToolButton(this)), + monthForward(new QToolButton(this)), + monthBackward(new QToolButton(this)), + selectMonth(new QToolButton(this)), + selectYear(new QToolButton(this)), + //line(new QLineEdit(this)), + val(new KDateValidator(this)) + //table(new KDateTable(this)), + //fontsize(1) +{ + // ----- + int size = 12; + if ( QApplication::desktop()->width() >= 480 ) + size = 18; + fontsize = size; + setFont ( QFont("helvetica",size) ); + table = new KDateTable(this); + setFontSize(size); + //line->setValidator(val); + lineDate = new KDateEdit( this, "dateediipicker", true ); + yearForward->setPixmap(SmallIcon("2rightarrowB")); + yearBackward->setPixmap(SmallIcon("2leftarrowB")); + monthForward->setPixmap(SmallIcon("1rightarrowB")); + monthBackward->setPixmap(SmallIcon("1leftarrowB")); + + setDate(dt); // set button texts + connect(table, SIGNAL(dateChanged(QDate)), SLOT(dateChangedSlot(QDate))); + connect(table, SIGNAL(tableClicked()), SLOT(tableClickedSlot())); + connect(monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked())); + connect(monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked())); + connect(yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked())); + connect(yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked())); + connect(selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked())); + connect(selectYear, SIGNAL(clicked()), SLOT(selectYearClicked())); + //connect(line, SIGNAL(returnPressed()), SLOT(lineEnterPressed())); + connect(lineDate, SIGNAL(dateChanged(QDate)), SLOT(slotSetDate(QDate))); + connect(lineDate, SIGNAL(returnPressed()), SLOT(lineEnterPressed())); + table->setFocus(); + +} + +KDatePicker::~KDatePicker() +{ +} + +void +KDatePicker::resizeEvent(QResizeEvent*) +{ + QWidget *buttons[] = { + yearBackward, + monthBackward, + selectMonth, + selectYear, + monthForward, + yearForward }; + const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]); + QSize sizes[NoOfButtons]; + int buttonHeight=0; + int count; + int w; + int x=0; + // ----- calculate button row height: + for(count=0; count<NoOfButtons; ++count) { + int xS = buttons[count]->sizeHint().width(); + int yS = buttons[count]->sizeHint().height(); + sizes[count]=QSize ( xS+10, yS ); + buttonHeight=QMAX(buttonHeight, sizes[count].height()); + } + buttonHeight += 10; + // ----- calculate size of the month button: + w=0; + for(count=0; count<NoOfButtons; ++count) { + if(buttons[count]!=selectMonth) + { + w+=sizes[count].width(); + } else { + x=count; + } + } + sizes[x].setWidth(width()-w); // stretch the month button + // ----- place the buttons: + x=0; + for(count=0; count<NoOfButtons; ++count) + { + w=sizes[count].width(); + buttons[count]->setGeometry(x, 0, w, buttonHeight); + x+=w; + } + // ----- place the line edit for direct input: + sizes[0]=lineDate->sizeHint(); + //line->setGeometry(0, height()-sizes[0].height(), width(), sizes[0].height()); + lineDate->setGeometry(0, height()-sizes[0].height(), width(), sizes[0].height()); + // ----- adjust the table: + table->setGeometry(0, buttonHeight, width(), + height()-buttonHeight-sizes[0].height()); +} + +void +KDatePicker::dateChangedSlot(QDate date) +{ + lineDate->setDate( date );//(KGlobal::locale()->formatDate(date, true)); + //line->setText(KGlobal::locale()->formatDate(date, true)); + emit(dateChanged(date)); +} + +void +KDatePicker::tableClickedSlot() +{ + + emit(dateSelected(table->getDate())); + emit(tableClicked()); +} + +const QDate& +KDatePicker::getDate() const +{ + return table->getDate(); +} + +const QDate & +KDatePicker::date() const +{ + return table->getDate(); +} + +void KDatePicker::slotSetDate( QDate date ) +{ + + if(date.isValid()) { + QString temp; + // ----- + table->setDate(date); + selectMonth->setText(KGlobal::locale()->monthName(date.month(), false)); + temp.setNum(date.year()); + selectYear->setText(temp); + //line->setText(KGlobal::locale()->formatDate(date, true)); + lineDate->setDate( date ); + } + +} +bool +KDatePicker::setDate(const QDate& date) +{ + table->setFocus(); + if(date.isValid()) { + QString temp; + // ----- + table->setDate(date); + selectMonth->setText(KGlobal::locale()->monthName(date.month(), false)); + temp.setNum(date.year()); + selectYear->setText(temp); + //line->setText(KGlobal::locale()->formatDate(date, true)); + lineDate->setDate( date ); + return true; + } else { + + return false; + } + + +} + +void +KDatePicker::monthForwardClicked() +{ + QDate temp=table->getDate(); + int day=temp.day(); + // ----- + if(temp.month()==12) { + temp.setYMD(temp.year()+1, 1, 1); + } else { + temp.setYMD(temp.year(), temp.month()+1, 1); + } + if(temp.daysInMonth()<day) { + temp.setYMD(temp.year(), temp.month(), temp.daysInMonth()); + } else { + temp.setYMD(temp.year(), temp.month(), day); + } + // assert(temp.isValid()); + setDate(temp); +} + +void +KDatePicker::monthBackwardClicked() +{ + QDate temp=table->getDate(); + int day=temp.day(); + // ----- + if(temp.month()==1) + { + temp.setYMD(temp.year()-1, 12, 1); + } else { + temp.setYMD(temp.year(), temp.month()-1, 1); + } + if(temp.daysInMonth()<day) + { + temp.setYMD(temp.year(), temp.month(), temp.daysInMonth()); + } else { + temp.setYMD(temp.year(), temp.month(), day); + } + // assert(temp.isValid()); + setDate(temp); +} + +void +KDatePicker::yearForwardClicked() +{ + QDate temp=table->getDate(); + int day=temp.day(); + // ----- + temp.setYMD(temp.year()+1, temp.month(), 1); + if(temp.daysInMonth()<day) + { + temp.setYMD(temp.year(), temp.month(), temp.daysInMonth()); + } else { + temp.setYMD(temp.year(), temp.month(), day); + } + // assert(temp.isValid()); + setDate(temp); +} + +void +KDatePicker::yearBackwardClicked() +{ + QDate temp=table->getDate(); + int day=temp.day(); + // ----- + temp.setYMD(temp.year()-1, temp.month(), 1); + if(temp.daysInMonth()<day) + { + temp.setYMD(temp.year(), temp.month(), temp.daysInMonth()); + } else { + temp.setYMD(temp.year(), temp.month(), day); + } + // assert(temp.isValid()); + setDate(temp); +} + +void +KDatePicker::selectMonthClicked() +{ + int month; + KPopupFrame* popup = new KPopupFrame(this); + KDateInternalMonthPicker* picker = new KDateInternalMonthPicker(fontsize, popup); + // ----- + picker->resize(picker->sizeHint()); + popup->setMainWidget(picker); + picker->setFocus(); + connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int))); + if(popup->exec(selectMonth->mapToGlobal(QPoint(0, selectMonth->height())))) + { + QDate date; + int day; + // ----- + month=picker->getResult(); + date=table->getDate(); + day=date.day(); + // ----- construct a valid date in this month: + date.setYMD(date.year(), month, 1); + date.setYMD(date.year(), month, QMIN(day, date.daysInMonth())); + // ----- set this month + setDate(date); + } else { + KNotifyClient::beep(); + } + delete popup; +} + +void +KDatePicker::selectYearClicked() +{ + int year; + KPopupFrame* popup = new KPopupFrame(this); + KDateInternalYearSelector* picker = new KDateInternalYearSelector(fontsize, popup); + // ----- + picker->resize(picker->sizeHint()); + popup->setMainWidget(picker); + connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int))); + picker->setFocus(); + if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height())))) + { + QDate date; + int day; + // ----- + year=picker->getYear(); + date=table->getDate(); + day=date.day(); + // ----- construct a valid date in this month: + date.setYMD(year, date.month(), 1); + date.setYMD(year, date.month(), QMIN(day, date.daysInMonth())); + // ----- set this month + setDate(date); + } else { + KNotifyClient::beep(); + } + delete popup; +} + +void +KDatePicker::setEnabled(bool enable) +{ + QWidget *widgets[]= { + yearForward, yearBackward, monthForward, monthBackward, + selectMonth, selectYear, + lineDate, table }; + const int Size=sizeof(widgets)/sizeof(widgets[0]); + int count; + // ----- + for(count=0; count<Size; ++count) + { + widgets[count]->setEnabled(enable); + } +} + +void +KDatePicker::lineEnterPressed() +{ + QDate temp; + // ----- + temp = lineDate->date(); + //if(val->date(line->text(), temp)==QValidator::Acceptable) + //{ + emit(dateEntered(temp)); + setDate(temp); + // } else { +// KNotifyClient::beep(); +// } +} + +QSize +KDatePicker::sizeHint() const +{ + QSize tableSize=table->sizeHint(); + QWidget *buttons[]={ + yearBackward, + monthBackward, + selectMonth, + selectYear, + monthForward, + yearForward }; + const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]); + QSize sizes[NoOfButtons]; + int cx=0, cy=0, count; + // ----- store the size hints: + for(count=0; count<NoOfButtons; ++count) + { + sizes[count]=buttons[count]->sizeHint(); + if(buttons[count]==selectMonth) + { + cx+=maxMonthRect.width()+15; + } else { + cx+=sizes[count].width()+15; + } + cy=QMAX(sizes[count].height(), cy); + } + // ----- calculate width hint: + cx=QMAX(cx, tableSize.width()); // line edit ignored + if ( cx > QApplication::desktop()->width() -5 ) + cx = QApplication::desktop()->width() -5; + // ----- calculate height hint: + cy+=tableSize.height()+lineDate->sizeHint().height(); + + return QSize(cx, cy); +} + +void +KDatePicker::setFontSize(int s) +{ + QWidget *buttons[]= { + // yearBackward, + // monthBackward, + selectMonth, + selectYear, + // monthForward, + // yearForward + }; + const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]); + int count; + QFont font; + QRect r; + // ----- + fontsize=s; + for(count=0; count<NoOfButtons; ++count) + { + font=buttons[count]->font(); + font.setPointSize(s); + buttons[count]->setFont(font); + } + QFontMetrics metrics(selectMonth->fontMetrics()); + for(int i=1; i <= 12; ++i) + { // maxMonthRect is used by sizeHint() + r=metrics.boundingRect(KGlobal::locale()->monthName(i, false)); + maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width())); + maxMonthRect.setHeight(QMAX(r.height(), maxMonthRect.height())); + } + table->setFontSize(s); +} + +void KDatePicker::virtual_hook( int id, void* data ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDatePicker::keyPressEvent ( QKeyEvent * e ) +{ + switch ( e->key() ) { + case Qt::Key_Right: + monthForwardClicked(); + break; + case Qt::Key_Left: + monthBackwardClicked(); + break; + + case Qt::Key_Down: + yearForwardClicked(); + + break; + + case Qt::Key_Up: + yearBackwardClicked(); + break; + + case Qt::Key_Return: + tableClickedSlot(); + break; + + default: + break; + } + +} diff --git a/libkdepim/kdatepicker.h b/libkdepim/kdatepicker.h new file mode 100644 index 0000000..6625357 --- a/dev/null +++ b/libkdepim/kdatepicker.h @@ -0,0 +1,181 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef MICROKDE_KDATEPICKER_H +#define MICROKDE_KDATEPICKER_H +#include <qdatetime.h> +#include <qframe.h> +#include <qevent.h> + +class QLineEdit; +class QToolButton; +class KDateValidator; +class KDateTable; +class KDateEdit; + +/** + * Provides a widget for calendar date input. + * + * Different from the + * previous versions, it now emits two types of signals, either + * @ref dateSelected() or @ref dateEntered() (see documentation for both + * signals). + * + * A line edit has been added in the newer versions to allow the user + * to select a date directly by entering numbers like 19990101 + * or 990101. + * + * @image kdatepicker.png KDatePicker + * + * @version $Id$ + * @author Tim Gilman, Mirko Boehm + * + * @short A date selection widget. + **/ +class KDatePicker: public QFrame +{ + Q_OBJECT +public: + /** The usual constructor. The given date will be displayed + * initially. + **/ + KDatePicker(QWidget *parent=0, + QDate=QDate::currentDate(), + const char *name=0); + /** + * The destructor. + **/ + virtual ~KDatePicker(); + + /** The size hint for date pickers. The size hint recommends the + * minimum size of the widget so that all elements may be placed + * without clipping. This sometimes looks ugly, so when using the + * size hint, try adding 28 to each of the reported numbers of + * pixels. + **/ + QSize sizeHint() const; + + /** + * Sets the date. + * + * @returns @p false and does not change anything + * if the date given is invalid. + **/ + bool setDate(const QDate&); + + /** + * Returns the selected date. + * @deprecated + **/ + const QDate& getDate() const; + + /** + * @returns the selected date. + */ + const QDate &date() const; + + /** + * Enables or disables the widget. + **/ + void setEnabled(bool); + + /** + * Sets the font size of the widgets elements. + **/ + void setFontSize(int); + /** + * Returns the font size of the widget elements. + */ + int fontSize() const + { return fontsize; } +protected: + /// the resize event + void resizeEvent(QResizeEvent*); + /// the year forward button + QToolButton *yearForward; + /// the year backward button + QToolButton *yearBackward; + /// the month forward button + QToolButton *monthForward; + /// the month backward button + QToolButton *monthBackward; + /// the button for selecting the month directly + QToolButton *selectMonth; + /// the button for selecting the year directly + QToolButton *selectYear; + /// the line edit to enter the date directly + //QLineEdit *line; + KDateEdit *lineDate; + /// the validator for the line edit: + KDateValidator *val; + /// the date table + KDateTable *table; + /// the size calculated during resize events + // QSize sizehint; + /// the widest month string in pixels: + QSize maxMonthRect; +protected slots: + void dateChangedSlot(QDate); + void tableClickedSlot(); + void monthForwardClicked(); + void monthBackwardClicked(); + void yearForwardClicked(); + void yearBackwardClicked(); + void selectMonthClicked(); + void selectYearClicked(); + void lineEnterPressed(); + void slotSetDate(QDate); +signals: + /** This signal is emitted each time the selected date is changed. + * Usually, this does not mean that the date has been entered, + * since the date also changes, for example, when another month is + * selected. + * @see dateSelected + */ + void dateChanged(QDate); + /** This signal is emitted each time a day has been selected by + * clicking on the table (hitting a day in the current month). It + * has the same meaning as dateSelected() in older versions of + * KDatePicker. + */ + void dateSelected(QDate); + /** This signal is emitted when enter is pressed and a VALID date + * has been entered before into the line edit. Connect to both + * dateEntered() and dateSelected() to receive all events where the + * user really enters a date. + */ + void dateEntered(QDate); + /** This signal is emitted when the day has been selected by + * clicking on it in the table. + */ + void tableClicked(); + +private: + /// the font size for the widget + int fontsize; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDatePickerPrivate; + KDatePickerPrivate *d; + void keyPressEvent ( QKeyEvent * ) ; +}; + +#endif // KDATEPICKER_H diff --git a/libkdepim/kdatepicker.moc b/libkdepim/kdatepicker.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libkdepim/kdatepicker.moc diff --git a/libkdepim/kdepim.pro.back b/libkdepim/kdepim.pro.back new file mode 100644 index 0000000..4dfc301 --- a/dev/null +++ b/libkdepim/kdepim.pro.back @@ -0,0 +1,34 @@ +TEMPLATE = lib +CONFIG = qt warn_on release +TARGET = kdepim +INCLUDEPATH += ../microkde ../qtcompat +INCLUDEPATH += . .. +LIBS += -lmicrokde +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc +DESTDIR=$(QPEDIR)/lib + +INTERFACES = \ + +HEADERS = \ + categoryeditdialog.h \ + categoryeditdialog_base.h \ + categoryselectdialog.h \ + categoryselectdialog_base.h \ + kdateedit.h \ + kinputdialog.h \ + kpimprefs.h \ + kprefs.h \ + kprefsdialog.h \ + +SOURCES = \ + categoryeditdialog.cpp \ + categoryeditdialog_base.cpp \ + categoryselectdialog.cpp \ + categoryselectdialog_base.cpp \ + kdateedit.cpp \ + kinputdialog.cpp \ + kpimprefs.cpp \ + kprefs.cpp \ + kprefsdialog.cpp \ + diff --git a/libkdepim/kincidenceformatter.cpp b/libkdepim/kincidenceformatter.cpp new file mode 100644 index 0000000..4815519 --- a/dev/null +++ b/libkdepim/kincidenceformatter.cpp @@ -0,0 +1,326 @@ +#include "kincidenceformatter.h" +#include <kstaticdeleter.h> +#include <kglobal.h> +#include <klocale.h> +#ifndef KORG_NOKABC +#include <kabc/stdaddressbook.h> +#define size count +#endif + +KIncidenceFormatter* KIncidenceFormatter::mInstance = 0; +static KStaticDeleter<KIncidenceFormatter> insd; + +QString KIncidenceFormatter::getFormattedText( Incidence * inc ) +{ +// #ifndef QT_NO_INPUTDIALOG +// return QInputDialog::getItem( caption, label, items, current, editable ); +// #else +// return QString::null; +// #endif + mText = ""; + if ( inc->type() == "Event" ) + setEvent((Event *) inc ); + else if ( inc->type() == "Todo" ) + setTodo((Todo *) inc ); + return mText; +} + +KIncidenceFormatter* KIncidenceFormatter::instance() +{ + if (!mInstance) { + mInstance = insd.setObject(new KIncidenceFormatter()); + } + return mInstance; +} +KIncidenceFormatter::~KIncidenceFormatter() +{ + if (mInstance == this) + mInstance = insd.setObject(0); + //qDebug("KIncidenceFormatter::~KIncidenceFormatter "); +} +KIncidenceFormatter::KIncidenceFormatter() +{ + mColorMode = 0; +} +void KIncidenceFormatter::setEvent(Event *event) +{ + int mode = 0; + mCurrentIncidence = event; + bool shortDate = true; + if ( mode == 0 ) { + addTag("h3",event->summary()); + } + else { + if ( mColorMode == 1 ) { + mText +="<font color=\"#00A000\">"; + } + if ( mColorMode == 2 ) { + mText +="<font color=\"#C00000\">"; + } + // mText +="<font color=\"#F00000\">" + i18n("O-due!") + "</font>"; + if ( mode == 1 ) { + addTag("h2",i18n( "Local: " ) +event->summary()); + } else { + addTag("h2",i18n( "Remote: " ) +event->summary()); + } + addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) ); + if ( mColorMode ) + mText += "</font>"; + } + if (event->cancelled ()) { + mText +="<font color=\"#B00000\">"; + addTag("i",i18n("This event has been cancelled!")); + mText.append("<br>"); + mText += "</font>"; + } + if (!event->location().isEmpty()) { + addTag("b",i18n("Location: ")); + mText.append(event->location()+"<br>"); + } + if (event->doesFloat()) { + if (event->isMultiDay()) { + mText.append(i18n("<p><b>From:</b> %1 </p><p><b>To:</b> %2</p>") + .arg(event->dtStartDateStr(shortDate)) + .arg(event->dtEndDateStr(shortDate))); + } else { + mText.append(i18n("<p><b>On:</b> %1</p>").arg(event->dtStartDateStr( shortDate ))); + } + } else { + if (event->isMultiDay()) { + mText.append(i18n("<p><b>From:</b> %1</p> ") + .arg(event->dtStartStr( shortDate))); + mText.append(i18n("<p><b>To:</b> %1</p>") + .arg(event->dtEndStr(shortDate))); + } else { + mText.append(i18n("<p><b>On:</b> %1</p> ") + .arg(event->dtStartDateStr( shortDate ))); + mText.append(i18n("<p><b>From:</b> %1 <b>To:</b> %2</p>") + .arg(event->dtStartTimeStr()) + .arg(event->dtEndTimeStr())); + } + } + + if (event->recurrence()->doesRecur()) { + + QString recurText = event->recurrence()->recurrenceText(); + addTag("p","<em>" + i18n("This is a %1 recurring event.").arg(recurText ) + "</em>"); + bool last; + QDate start = QDate::currentDate(); + QDate next; + next = event->recurrence()->getPreviousDate( start , &last ); + if ( !last ) { + next = event->recurrence()->getNextDate( start.addDays( - 1 ) ); + addTag("p",i18n("Next recurrence is on: ")+ KGlobal::locale()->formatDate( next, shortDate ) ); + //addTag("p", KGlobal::locale()->formatDate( next, shortDate )); + } else { + addTag("p",i18n("<b>Last recurrence was on:</b>") ); + addTag("p", KGlobal::locale()->formatDate( next, shortDate )); + } + } + + + if (event->isAlarmEnabled()) { + Alarm *alarm =event->alarms().first() ; + QDateTime t = alarm->time(); + int min = t.secsTo( event->dtStart() )/60; + QString s =i18n("(%1 min before)").arg( min ); + addTag("p",i18n("<b>Alarm on: </b>") + s + ": "+KGlobal::locale()->formatDateTime( t, shortDate )); + //addTag("p", KGlobal::locale()->formatDateTime( t, shortDate )); + //addTag("p",s); + } + + addTag("p",i18n("<b>Access: </b>") +event->secrecyStr() ); + // mText.append(event->secrecyStr()+"<br>"); + formatCategories(event); + if (!event->description().isEmpty()) { + addTag("p",i18n("<b>Details: </b>")); + addTag("p",event->description()); + } + + + formatReadOnly(event); + formatAttendees(event); + + +} + +void KIncidenceFormatter::setTodo(Todo *event ) +{ + int mode = 0; + mCurrentIncidence = event; + bool shortDate = true; + if (mode == 0 ) + addTag("h3",event->summary()); + else { + if ( mColorMode == 1 ) { + mText +="<font color=\"#00A000\">"; + } + if ( mColorMode == 2 ) { + mText +="<font color=\"#B00000\">"; + } + if ( mode == 1 ) { + addTag("h2",i18n( "Local: " ) +event->summary()); + } else { + addTag("h2",i18n( "Remote: " ) +event->summary()); + } + addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) ); + if ( mColorMode ) + mText += "</font>"; + } + if (event->cancelled ()) { + mText +="<font color=\"#B00000\">"; + addTag("i",i18n("This todo has been cancelled!")); + mText.append("<br>"); + mText += "</font>"; + } + + if (!event->location().isEmpty()) { + addTag("b",i18n("Location: ")); + mText.append(event->location()+"<br>"); + } + if (event->hasDueDate()) { + mText.append(i18n("<p><b>Due on:</b> %1</p>").arg(event->dtDueStr(shortDate))); + } + mText.append(i18n("<p><b>Priority:</b> %2</p>") + .arg(QString::number(event->priority()))); + + mText.append(i18n("<p><i>%1 % completed</i></p>") + .arg(event->percentComplete())); + addTag("p",i18n("<b>Access: </b>") +event->secrecyStr() ); + formatCategories(event); + if (!event->description().isEmpty()) { + addTag("p",i18n("<b>Details: </b>")); + addTag("p",event->description()); + } + + + + formatReadOnly(event); + formatAttendees(event); + +} + +void KIncidenceFormatter::setJournal(Journal* ) +{ + +} + +void KIncidenceFormatter::formatCategories(Incidence *event) +{ + if (!event->categoriesStr().isEmpty()) { + addTag("p",i18n("<b>Categories: </b>")+event->categoriesStr() ); + //mText.append(event->categoriesStr()); + } +} +void KIncidenceFormatter::addTag(const QString & tag,const QString & text) +{ + int number=text.contains("\n"); + QString str = "<" + tag + ">"; + QString tmpText=text; + QString tmpStr=str; + if(number !=-1) + { + if (number > 0) { + int pos=0; + QString tmp; + for(int i=0;i<=number;i++) { + pos=tmpText.find("\n"); + tmp=tmpText.left(pos); + tmpText=tmpText.right(tmpText.length()-pos-1); + tmpStr+=tmp+"<br>"; + } + } + else tmpStr += tmpText; + tmpStr+="</" + tag + ">"; + mText.append(tmpStr); + } + else + { + str += text + "</" + tag + ">"; + mText.append(str); + } +} + +void KIncidenceFormatter::formatAttendees(Incidence *event) +{ + QPtrList<Attendee> attendees = event->attendees(); + if (attendees.count()) { + QString iconPath = KGlobal::iconLoader()->iconPath("mailappt",KIcon::Small); + addTag("h3",i18n("Organizer")); + mText.append("<ul><li>"); +#ifndef KORG_NOKABC + + KABC::AddressBook *add_book = KABC::StdAddressBook::self(); + KABC::Addressee::List addressList; + addressList = add_book->findByEmail(event->organizer()); + KABC::Addressee o = addressList.first(); + if (!o.isEmpty() && addressList.size()<2) { + mText += "<a href=\"uid:" + o.uid() + "\">"; + mText += o.formattedName(); + mText += "</a>\n"; + } else { + mText.append(event->organizer()); + } +#else + mText.append(event->organizer()); +#endif + if (iconPath) { + mText += " <a href=\"mailto:" + event->organizer() + "\">"; + mText += "<IMG src=\"" + iconPath + "\">"; + mText += "</a>\n"; + } + mText.append("</li></ul>"); + + addTag("h3",i18n("Attendees")); + Attendee *a; + mText.append("<ul>"); + for(a=attendees.first();a;a=attendees.next()) { +#ifndef KORG_NOKABC + if (a->name().isEmpty()) { + addressList = add_book->findByEmail(a->email()); + KABC::Addressee o = addressList.first(); + if (!o.isEmpty() && addressList.size()<2) { + mText += "<a href=\"uid:" + o.uid() + "\">"; + mText += o.formattedName(); + mText += "</a>\n"; + } else { + mText += "<li>"; + mText.append(a->email()); + mText += "\n"; + } + } else { + mText += "<li><a href=\"uid:" + a->uid() + "\">"; + if (!a->name().isEmpty()) mText += a->name(); + else mText += a->email(); + mText += "</a>\n"; + } +#else + //qDebug("nokabc "); + mText += "<li><a href=\"uid:" + a->uid() + "\">"; + if (!a->name().isEmpty()) mText += a->name(); + else mText += a->email(); + mText += "</a>\n"; +#endif + + if (!a->email().isEmpty()) { + if (iconPath) { + mText += "<a href=\"mailto:" + a->name() +" "+ "<" + a->email() + ">" + "\">"; + mText += "<IMG src=\"" + iconPath + "\">"; + mText += "</a>\n"; + } + } + if (a->status() != Attendee::NeedsAction ) + mText +="[" + a->statusStr() + "] "; + if (a->role() == Attendee::Chair ) + mText +="(" + a->roleStr().left(1) + ".)"; + } + mText.append("</li></ul>"); + } +} + +void KIncidenceFormatter::formatReadOnly(Incidence *event) +{ + if (event->isReadOnly()) { + addTag("p","<em>(" + i18n("read-only") + ")</em>"); + } +} diff --git a/libkdepim/kincidenceformatter.h b/libkdepim/kincidenceformatter.h new file mode 100644 index 0000000..8fe259a --- a/dev/null +++ b/libkdepim/kincidenceformatter.h @@ -0,0 +1,42 @@ +#ifndef KINCIDENCENFORMATTER_H +#define KINCIDENCENFORMATTER_H + +#include <qstring.h> +#include <qobject.h> + +#include "libkcal/incidence.h" +#include "libkcal/event.h" +#include "libkcal/todo.h" +#include "libkcal/journal.h" + +using namespace KCal; + +class KIncidenceFormatter : public QObject +{ + public: + static KIncidenceFormatter* instance(); + KIncidenceFormatter(); + ~KIncidenceFormatter(); + QString getFormattedText( Incidence * inc ); + + void setEvent(Event *event); + void setTodo(Todo *event ); + void setJournal(Journal* ); + + protected: + int mColorMode; + void addTag(const QString & tag,const QString & text); + + void formatCategories(Incidence *event); + void formatAttendees(Incidence *event); + void formatReadOnly(Incidence *event); + + private: + bool mSyncMode; + + QString mText; + Incidence* mCurrentIncidence; + static KIncidenceFormatter* mInstance; +}; + +#endif diff --git a/libkdepim/kinputdialog.cpp b/libkdepim/kinputdialog.cpp new file mode 100644 index 0000000..0c31ca9 --- a/dev/null +++ b/libkdepim/kinputdialog.cpp @@ -0,0 +1,14 @@ +#include "kinputdialog.h" + +#include <qinputdialog.h> + +QString KInputDialog::getItem( const QString &caption, const QString &label, + const QStringList &items, int current, + bool editable ) +{ +#ifndef QT_NO_INPUTDIALOG + return QInputDialog::getItem( caption, label, items, current, editable ); +#else + return QString::null; +#endif +} diff --git a/libkdepim/kinputdialog.h b/libkdepim/kinputdialog.h new file mode 100644 index 0000000..0072391 --- a/dev/null +++ b/libkdepim/kinputdialog.h @@ -0,0 +1,15 @@ +#ifndef KINPUTDIALOG_H +#define KINPUTDIALOG_H + +#include <qstring.h> +#include <qstringlist.h> + +class KInputDialog +{ + public: + static QString getItem( const QString &caption, const QString &label, + const QStringList &items, int current, + bool editable ); +}; + +#endif diff --git a/libkdepim/kpimprefs.cpp b/libkdepim/kpimprefs.cpp new file mode 100644 index 0000000..ce4c540 --- a/dev/null +++ b/libkdepim/kpimprefs.cpp @@ -0,0 +1,59 @@ +/* + This file is part of libkdepim. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kglobal.h> +#include <kconfig.h> +#include <klocale.h> +#include <kdebug.h> + +#include "kpimprefs.h" + +KPimPrefs::KPimPrefs( const QString &name ) : + KPrefs( name ) +{ +} + +KPimPrefs::~KPimPrefs() +{ +} + +void KPimPrefs::usrSetDefaults() +{ + setCategoryDefaults(); +} + +void KPimPrefs::usrReadConfig() +{ + kdDebug(5300) << "KPimPrefs::usrReadConfig()" << endl; + + config()->setGroup("General"); + mCustomCategories = config()->readListEntry("Custom Categories"); + if (mCustomCategories.isEmpty()) setCategoryDefaults(); +} + + +void KPimPrefs::usrWriteConfig() +{ + config()->setGroup("General"); + config()->writeEntry("Custom Categories",mCustomCategories); +} diff --git a/libkdepim/kpimprefs.h b/libkdepim/kpimprefs.h new file mode 100644 index 0000000..05a564c --- a/dev/null +++ b/libkdepim/kpimprefs.h @@ -0,0 +1,53 @@ +/* + This file is part of libkdepim. + Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef KPIMPREFS_H +#define KPIMPREFS_H + +#include <qstringlist.h> + +#include "kprefs.h" + +class KPimPrefs : public KPrefs +{ + public: + KPimPrefs( const QString &name = QString::null ); + + virtual ~KPimPrefs(); + + /** Set preferences to default values */ + void usrSetDefaults(); + + /** Read preferences from config file */ + void usrReadConfig(); + + /** Write preferences to config file */ + void usrWriteConfig(); + + public: + QStringList mCustomCategories; + + protected: + virtual void setCategoryDefaults() = 0; +}; + +#endif diff --git a/libkdepim/kprefs.cpp b/libkdepim/kprefs.cpp new file mode 100644 index 0000000..f5e5e5a --- a/dev/null +++ b/libkdepim/kprefs.cpp @@ -0,0 +1,463 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// $Id$ + +#include <qcolor.h> + +#include <kconfig.h> +#include <kstandarddirs.h> +#include <kglobal.h> +#include <kdebug.h> + +#include "kprefs.h" + +class KPrefsItemBool : public KPrefsItem { + public: + KPrefsItemBool(const QString &group,const QString &name,bool *,bool defaultValue=true); + virtual ~KPrefsItemBool() {} + + void setDefault(); + void readConfig(KConfig *); + void writeConfig(KConfig *); + + private: + bool *mReference; + bool mDefault; +}; + +class KPrefsItemInt : public KPrefsItem { + public: + KPrefsItemInt(const QString &group,const QString &name,int *,int defaultValue=0); + virtual ~KPrefsItemInt() {} + + void setDefault(); + void readConfig(KConfig *); + void writeConfig(KConfig *); + + private: + int *mReference; + int mDefault; +}; + + +class KPrefsItemColor : public KPrefsItem { + public: + KPrefsItemColor(const QString &group,const QString &name,QColor *, + const QColor &defaultValue=QColor(128,128,128)); + virtual ~KPrefsItemColor() {} + + void setDefault(); + void readConfig(KConfig *); + void writeConfig(KConfig *); + + private: + QColor *mReference; + QColor mDefault; +}; + + +class KPrefsItemFont : public KPrefsItem { + public: + KPrefsItemFont(const QString &group,const QString &name,QFont *, + const QFont &defaultValue=QFont("helvetica",12)); + virtual ~KPrefsItemFont() {} + + void setDefault(); + void readConfig(KConfig *); + void writeConfig(KConfig *); + + private: + QFont *mReference; + QFont mDefault; +}; + + +class KPrefsItemString : public KPrefsItem { + public: + KPrefsItemString(const QString &group,const QString &name,QString *, + const QString &defaultValue="", bool isPassword=false); + virtual ~KPrefsItemString() {} + + void setDefault(); + void readConfig(KConfig *); + void writeConfig(KConfig *); + + private: + QString *mReference; + QString mDefault; + bool mPassword; +}; + + +class KPrefsItemStringList : public KPrefsItem { + public: + KPrefsItemStringList(const QString &group,const QString &name,QStringList *, + const QStringList &defaultValue=QStringList()); + virtual ~KPrefsItemStringList() {} + + void setDefault(); + void readConfig(KConfig *); + void writeConfig(KConfig *); + + private: + QStringList *mReference; + QStringList mDefault; +}; + + +class KPrefsItemIntList : public KPrefsItem { + public: + KPrefsItemIntList(const QString &group,const QString &name,QValueList<int> *, + const QValueList<int> &defaultValue=QValueList<int>()); + virtual ~KPrefsItemIntList() {} + + void setDefault(); + void readConfig(KConfig *); + void writeConfig(KConfig *); + + private: + QValueList<int> *mReference; + QValueList<int> mDefault; +}; + + +KPrefsItemBool::KPrefsItemBool(const QString &group,const QString &name, + bool *reference,bool defaultValue) : + KPrefsItem(group,name) +{ + mReference = reference; + mDefault = defaultValue; +} + +void KPrefsItemBool::setDefault() +{ + *mReference = mDefault; +} + +void KPrefsItemBool::writeConfig(KConfig *config) +{ + config->setGroup(mGroup); + config->writeEntry(mName,*mReference); +} + + +void KPrefsItemBool::readConfig(KConfig *config) +{ + config->setGroup(mGroup); + *mReference = config->readBoolEntry(mName,mDefault); +} + + +KPrefsItemInt::KPrefsItemInt(const QString &group,const QString &name, + int *reference,int defaultValue) : + KPrefsItem(group,name) +{ + mReference = reference; + mDefault = defaultValue; +} + +void KPrefsItemInt::setDefault() +{ + *mReference = mDefault; +} + +void KPrefsItemInt::writeConfig(KConfig *config) +{ + config->setGroup(mGroup); + config->writeEntry(mName,*mReference); +} + +void KPrefsItemInt::readConfig(KConfig *config) +{ + config->setGroup(mGroup); + *mReference = config->readNumEntry(mName,mDefault); +} + + +KPrefsItemColor::KPrefsItemColor(const QString &group,const QString &name, + QColor *reference,const QColor &defaultValue) : + KPrefsItem(group,name) +{ + mReference = reference; + mDefault = defaultValue; +} + +void KPrefsItemColor::setDefault() +{ + *mReference = mDefault; +} + +void KPrefsItemColor::writeConfig(KConfig *config) +{ + config->setGroup(mGroup); + config->writeEntry(mName,*mReference); +} + +void KPrefsItemColor::readConfig(KConfig *config) +{ + config->setGroup(mGroup); + *mReference = config->readColorEntry(mName,&mDefault); + +} + + +KPrefsItemFont::KPrefsItemFont(const QString &group,const QString &name, + QFont *reference,const QFont &defaultValue) : + KPrefsItem(group,name) +{ + mReference = reference; + mDefault = defaultValue; +} + +void KPrefsItemFont::setDefault() +{ + *mReference = mDefault; +} + +void KPrefsItemFont::writeConfig(KConfig *config) +{ + config->setGroup(mGroup); + config->writeEntry(mName,*mReference); +} + +void KPrefsItemFont::readConfig(KConfig *config) +{ + config->setGroup(mGroup); + *mReference = config->readFontEntry(mName,&mDefault); +} + + +QString endecryptStr( const QString &aStr ) +{ + QString result; + uint i; + for ( i = 0; i < aStr.length(); i++) + result += (aStr.at(i).unicode() < 0x20) ? + aStr.at(i) : + QChar(0x1001F - aStr.at(i).unicode()); + return result; +} + + +KPrefsItemString::KPrefsItemString(const QString &group,const QString &name, + QString *reference,const QString &defaultValue, + bool isPassword) : + KPrefsItem(group,name) +{ + mReference = reference; + mDefault = defaultValue; + mPassword = isPassword; +} + +void KPrefsItemString::setDefault() +{ + *mReference = mDefault; +} + +void KPrefsItemString::writeConfig(KConfig *config) +{ + config->setGroup(mGroup); + if ( mPassword ) + config->writeEntry(mName, endecryptStr( *mReference ) ); + else + config->writeEntry(mName,*mReference); +} + +void KPrefsItemString::readConfig(KConfig *config) +{ + config->setGroup(mGroup); + + QString value; + if ( mPassword ) { + value = config->readEntry( mName, endecryptStr( mDefault ) ); + *mReference = endecryptStr( value ); + } else { + *mReference = config->readEntry( mName, mDefault ); + } +} + + +KPrefsItemStringList::KPrefsItemStringList(const QString &group,const QString &name, + QStringList *reference,const QStringList &defaultValue) : + KPrefsItem(group,name) +{ + mReference = reference; + mDefault = defaultValue; +} + +void KPrefsItemStringList::setDefault() +{ + *mReference = mDefault; +} + +void KPrefsItemStringList::writeConfig(KConfig *config) +{ + config->setGroup(mGroup); + config->writeEntry(mName,*mReference); +} + +void KPrefsItemStringList::readConfig(KConfig *config) +{ + config->setGroup(mGroup); + *mReference = config->readListEntry(mName); +} + + +KPrefsItemIntList::KPrefsItemIntList(const QString &group,const QString &name, + QValueList<int> *reference,const QValueList<int> &defaultValue) : + KPrefsItem(group,name) +{ + mReference = reference; + mDefault = defaultValue; +} + +void KPrefsItemIntList::setDefault() +{ + *mReference = mDefault; +} + +void KPrefsItemIntList::writeConfig(KConfig *config) +{ + config->setGroup(mGroup); + config->writeEntry(mName,*mReference); +} + +void KPrefsItemIntList::readConfig(KConfig *config) +{ + config->setGroup(mGroup); + *mReference = config->readIntListEntry(mName); +} + + +QString *KPrefs::mCurrentGroup = 0; + +KPrefs::KPrefs(const QString &configname) +{ + if (!configname.isEmpty()) { + //qDebug("KPrefs::KPrefs %s",configname.latin1() ); + mConfig = new KConfig(locateLocal("config",configname)); + } else { + mConfig = KGlobal::config(); + } + + mItems.setAutoDelete(true); + + // Set default group + if (mCurrentGroup == 0) mCurrentGroup = new QString("No Group"); +} + +KPrefs::~KPrefs() +{ + if (mConfig != KGlobal::config()) { + delete mConfig; + } +} + +void KPrefs::setCurrentGroup(const QString &group) +{ + if (mCurrentGroup) delete mCurrentGroup; + mCurrentGroup = new QString(group); +} + +KConfig *KPrefs::config() const +{ + return mConfig; +} + +void KPrefs::setDefaults() +{ + KPrefsItem *item; + for(item = mItems.first();item;item = mItems.next()) { + item->setDefault(); + } + + usrSetDefaults(); +} + +void KPrefs::readConfig() +{ + KPrefsItem *item; + for(item = mItems.first();item;item = mItems.next()) { + item->readConfig(mConfig); + } + + usrReadConfig(); +} + +void KPrefs::writeConfig() +{ + KPrefsItem *item; + for(item = mItems.first();item;item = mItems.next()) { + item->writeConfig(mConfig); + } + + usrWriteConfig(); + + mConfig->sync(); +} + + +void KPrefs::addItem(KPrefsItem *item) +{ + mItems.append(item); +} + +void KPrefs::addItemBool(const QString &key,bool *reference,bool defaultValue) +{ + addItem(new KPrefsItemBool(*mCurrentGroup,key,reference,defaultValue)); +} + +void KPrefs::addItemInt(const QString &key,int *reference,int defaultValue) +{ + addItem(new KPrefsItemInt(*mCurrentGroup,key,reference,defaultValue)); +} + +void KPrefs::addItemColor(const QString &key,QColor *reference,const QColor &defaultValue) +{ + addItem(new KPrefsItemColor(*mCurrentGroup,key,reference,defaultValue)); +} + +void KPrefs::addItemFont(const QString &key,QFont *reference,const QFont &defaultValue) +{ + addItem(new KPrefsItemFont(*mCurrentGroup,key,reference,defaultValue)); +} + +void KPrefs::addItemString(const QString &key,QString *reference,const QString &defaultValue) +{ + addItem(new KPrefsItemString(*mCurrentGroup,key,reference,defaultValue,false)); +} + +void KPrefs::addItemPassword(const QString &key,QString *reference,const QString &defaultValue) +{ + addItem(new KPrefsItemString(*mCurrentGroup,key,reference,defaultValue,true)); +} + +void KPrefs::addItemStringList(const QString &key,QStringList *reference, + const QStringList &defaultValue) +{ + addItem(new KPrefsItemStringList(*mCurrentGroup,key,reference,defaultValue)); +} + +void KPrefs::addItemIntList(const QString &key,QValueList<int> *reference, + const QValueList<int> &defaultValue) +{ + addItem(new KPrefsItemIntList(*mCurrentGroup,key,reference,defaultValue)); +} diff --git a/libkdepim/kprefs.h b/libkdepim/kprefs.h new file mode 100644 index 0000000..7014bb8 --- a/dev/null +++ b/libkdepim/kprefs.h @@ -0,0 +1,301 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef _KPREFS_H +#define _KPREFS_H +// $Id$ + +#include <qptrlist.h> +#include <qcolor.h> +#include <qfont.h> +#include <qstringlist.h> + +class KConfig; + +/** + @short Class for storing a preferences setting + @author Cornelius Schumacher + @see KPref + + This class represents one preferences setting as used by @ref KPrefs. + Subclasses of KPrefsItem implement storage functions for a certain type of + setting. Normally you don't have to use this class directly. Use the special + addItem() functions of KPrefs instead. If you subclass this class you will + have to register instances with the function KPrefs::addItem(). +*/ +class KPrefsItem { + public: + /** + Constructor. + + @param group Config file group. + @param name Config file key. + */ + KPrefsItem(const QString &group,const QString &name) : + mGroup(group),mName(name) {} + /** + Destructor. + */ + virtual ~KPrefsItem() {} + + /** + This function is called by @ref KPrefs to set this setting to its default + value. + */ + virtual void setDefault() = 0; + /** + This function is called by @ref KPrefs to read the value for this setting + from a config file. + value. + */ + virtual void readConfig(KConfig *) = 0; + /** + This function is called by @ref KPrefs to write the value of this setting + to a config file. + */ + virtual void writeConfig(KConfig *) = 0; + + protected: + QString mGroup; + QString mName; +}; + +/** + @short Class for handling preferences settings for an application. + @author Cornelius Schumacher + @see KPrefsItem + + This class provides an interface to preferences settings. Preferences items + can be registered by the addItem() function corresponding to the data type of + the seetting. KPrefs then handles reading and writing of config files and + setting of default values. + + Normally you will subclass KPrefs, add data members for the preferences + settings and register the members in the constructor of the subclass. + + Example: + <pre> + class MyPrefs : public KPrefs { + public: + MyPrefs() + { + setCurrentGroup("MyGroup"); + addItemBool("MySetting1",&mMyBool,false); + addItemColor("MySetting2",&mMyColor,QColor(1,2,3)); + + setCurrentGroup("MyOtherGroup"); + addItemFont("MySetting3",&mMyFont,QFont("helvetica",12)); + } + + bool mMyBool; + QColor mMyColor; + QFont mMyFont; + } + </pre> + + It might be convenient in many cases to make this subclass of KPrefs a + singleton for global access from all over the application without passing + references to the KPrefs object around. + + You can set all values to default values by calling @ref setDefaults(), write + the data to the configuration file by calling @ref writeConfig() and read the + data from the configuration file by calling @ref readConfig(). + + If you have items, which are not covered by the existing addItem() functions + you can add customized code for reading, writing and default setting by + implementing the functions @ref usrSetDefaults(), @ref usrReadConfig() and + @ref usrWriteConfig(). + + Internally preferences settings are stored in instances of subclasses of + @ref KPrefsItem. You can also add KPrefsItem subclasses for your own types + and call the generic @ref addItem() to register them. +*/ + +class KPrefs { + public: + /** + Constructor. + + @param configname name of config file. If no name is given, the default + config file as returned by kapp()->config() is used. + */ + KPrefs(const QString &configname=QString::null); + /** + Destructor + */ + virtual ~KPrefs(); + + /** + Set preferences to default values. All registered items are set to their + default values. + */ + void setDefaults(); + + /** + Read preferences from config file. All registered items are set to the + values read from disk. + */ + void readConfig(); + + /** + Write preferences to config file. The values of all registered items are + written to disk. + */ + void writeConfig(); + + /** + Set the config file group for subsequent addItem() calls. It is valid + until setCurrentGroup() is called with a new argument. Call this before + you add any items. The default value is "No Group". + */ + static void setCurrentGroup(const QString &group); + + /** + Register a custom @ref KPrefsItem. + */ + void addItem(KPrefsItem *); + + /** + Register an item of type bool. + + @param key Key used in config file. + @param reference Pointer to the variable, which is set by readConfig() + and setDefaults() calls and read by writeConfig() calls. + @param defaultValue Default value, which is used by setDefaults() and + when the config file does not yet contain the key of + this item. + */ + void addItemBool(const QString &key,bool *reference, + bool defaultValue=false); + /** + Register an item of type int. + + @param key Key used in config file. + @param reference Pointer to the variable, which is set by readConfig() + and setDefaults() calls and read by writeConfig() calls. + @param defaultValue Default value, which is used by setDefaults() and + when the config file does not yet contain the key of + this item. + */ + void addItemInt(const QString &key,int *reference, + int defaultValue=0); + /** + Register an item of type QColor. + + @param key Key used in config file. + @param reference Pointer to the variable, which is set by readConfig() + and setDefaults() calls and read by writeConfig() calls. + @param defaultValue Default value, which is used by setDefaults() and + when the config file does not yet contain the key of + this item. + */ + void addItemColor(const QString &key,QColor *reference, + const QColor &defaultValue=QColor(128,128,128)); + /** + Register an item of type QFont. + + @param key Key used in config file. + @param reference Pointer to the variable, which is set by readConfig() + and setDefaults() calls and read by writeConfig() calls. + @param defaultValue Default value, which is used by setDefaults() and + when the config file does not yet contain the key of + this item. + */ + void addItemFont(const QString &key,QFont *reference, + const QFont &defaultValue=QFont("helvetica",12)); + /** + Register an item of type QString. + + @param key Key used in config file. + @param reference Pointer to the variable, which is set by readConfig() + and setDefaults() calls and read by writeConfig() calls. + @param defaultValue Default value, which is used by setDefaults() and + when the config file does not yet contain the key of + this item. + */ + void addItemString(const QString &key,QString *reference, + const QString &defaultValue=""); + /** + Register a password item of type QString. The string value is written + encrypted to the config file. Note that the current encryption scheme + is very weak. + + @param key Key used in config file. + @param reference Pointer to the variable, which is set by readConfig() + and setDefaults() calls and read by writeConfig() calls. + @param defaultValue Default value, which is used by setDefaults() and + when the config file does not yet contain the key of + this item. + */ + void addItemPassword(const QString &key,QString *reference, + const QString &defaultValue=""); + /** + Register an item of type QStringList. + + @param key Key used in config file. + @param reference Pointer to the variable, which is set by readConfig() + and setDefaults() calls and read by writeConfig() calls. + @param defaultValue Default value, which is used by setDefaults() and + when the config file does not yet contain the key of + this item. + */ + void addItemStringList(const QString &key,QStringList *reference, + const QStringList &defaultValue=QStringList()); + + /** + Register an item of type QValueList<int>. + + @param key Key used in config file. + @param reference Pointer to the variable, which is set by readConfig() + and setDefaults() calls and read by writeConfig() calls. + @param defaultValue Default value, which is used by setDefaults() and + when the config file does not yet contain the key of + this item. + */ + void addItemIntList(const QString &key,QValueList<int> *reference, + const QValueList<int> &defaultValue=QValueList<int>()); + + protected: + /** + Implemented by subclasses that use special defaults. + */ + virtual void usrSetDefaults() {}; + /** + Implemented by subclasses that read special config values. + */ + virtual void usrReadConfig() {}; + /** + Implemented by subclasses that write special config values. + */ + virtual void usrWriteConfig() {}; + + /** + Return the @ref KConfig object used for reading and writing the settings. + */ + KConfig *config() const; + + private: + static QString *mCurrentGroup; + + KConfig *mConfig; // pointer to KConfig object + + QPtrList<KPrefsItem> mItems; +}; + +#endif diff --git a/libkdepim/kprefsdialog.cpp b/libkdepim/kprefsdialog.cpp new file mode 100644 index 0000000..3a39ea9 --- a/dev/null +++ b/libkdepim/kprefsdialog.cpp @@ -0,0 +1,410 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +// $Id$ + +#include <qlayout.h> +#include <qlabel.h> +#include <qgroupbox.h> +#include <qbuttongroup.h> +#include <qlineedit.h> +#include <qfont.h> +#include <qslider.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qvbox.h> +#include <qhbox.h> +#include <qspinbox.h> +#include <qdatetime.h> +#include <qframe.h> +#include <qcombobox.h> +#include <qcheckbox.h> +#include <qradiobutton.h> +#include <qpushbutton.h> +#include <qapplication.h> + +#include <kcolorbutton.h> +#include <kdebug.h> +#include <klocale.h> +#include <kglobal.h> +#include <kfontdialog.h> +#include <kmessagebox.h> +#include <kcolordialog.h> +#include <kiconloader.h> + +#include "kprefs.h" + +#include "kprefsdialog.h" +#include "kprefsdialog.moc" + +KPrefsWidBool::KPrefsWidBool(const QString &text,bool *reference, + QWidget *parent) +{ + mReference = reference; + + mCheck = new QCheckBox(text,parent); +} + +void KPrefsWidBool::readConfig() +{ + mCheck->setChecked(*mReference); +} + +void KPrefsWidBool::writeConfig() +{ + *mReference = mCheck->isChecked(); +} + +QCheckBox *KPrefsWidBool::checkBox() +{ + return mCheck; +} + + +KPrefsWidColor::KPrefsWidColor(const QString &text,QColor *reference, + QWidget *parent) +{ + mReference = reference; + + mButton = new KColorButton(parent); + mLabel = new QLabel(mButton, text, parent); + mButton->setColor( *mReference ); + mButton->setColor( Qt::red ); + +} + +KPrefsWidColor::~KPrefsWidColor() +{ +// kdDebug(5300) << "KPrefsWidColor::~KPrefsWidColor()" << endl; +} + +void KPrefsWidColor::readConfig() +{ + mButton->setColor(*mReference); +} + +void KPrefsWidColor::writeConfig() +{ + *mReference = mButton->color(); +} + +QLabel *KPrefsWidColor::label() +{ + return mLabel; +} + +KColorButton *KPrefsWidColor::button() +{ + return mButton; +} + +KPrefsWidFont::KPrefsWidFont(const QString &sampleText,const QString &labelText, + QFont *reference,QWidget *parent) +{ + mReference = reference; + + mLabel = new QLabel(labelText, parent); + + mPreview = new QLabel(sampleText,parent); + mPreview->setFrameStyle(QFrame::Panel|QFrame::Sunken); + + mButton = new QPushButton(i18n("Choose..."), parent); + connect(mButton,SIGNAL(clicked()),SLOT(selectFont())); + mPreview->setMaximumHeight( QApplication::desktop()->height() / 12 ); + mPreview->setMaximumWidth( (QApplication::desktop()->width() / 2)-10 ); +} + +KPrefsWidFont::~KPrefsWidFont() +{ +} + +void KPrefsWidFont::readConfig() +{ + mPreview->setFont(*mReference); +} + +void KPrefsWidFont::writeConfig() +{ + *mReference = mPreview->font(); +} + +QLabel *KPrefsWidFont::label() +{ + return mLabel; +} + +QLabel *KPrefsWidFont::preview() +{ + return mPreview; +} + +QPushButton *KPrefsWidFont::button() +{ + return mButton; +} + +void KPrefsWidFont::selectFont() +{ + QFont myFont(mPreview->font()); + bool ok; + myFont = KFontDialog::getFont(myFont, ok); + if ( ok ) { + mPreview->setFont(myFont); + } +} + + +KPrefsWidTime::KPrefsWidTime(const QString &text,int *reference, + QWidget *parent) +{ + mReference = reference; + + mLabel = new QLabel(text,parent); + mSpin = new QSpinBox(0,23,1,parent); + mSpin->setSuffix(":00"); +} + +void KPrefsWidTime::readConfig() +{ + mSpin->setValue(*mReference); +} + +void KPrefsWidTime::writeConfig() +{ + *mReference = mSpin->value(); +} + +QLabel *KPrefsWidTime::label() +{ + return mLabel; +} + +QSpinBox *KPrefsWidTime::spinBox() +{ + return mSpin; +} + + +KPrefsWidRadios::KPrefsWidRadios(const QString &text,int *reference, + QWidget *parent) +{ + mReference = reference; + + mBox = new QButtonGroup(1,Qt::Horizontal,text,parent); +} + +KPrefsWidRadios::~KPrefsWidRadios() +{ +} + +void KPrefsWidRadios::addRadio(const QString &text) +{ + new QRadioButton(text,mBox); +} + +QButtonGroup *KPrefsWidRadios::groupBox() +{ + return mBox; +} + +void KPrefsWidRadios::readConfig() +{ + mBox->setButton(*mReference); +} + +void KPrefsWidRadios::writeConfig() +{ + *mReference = mBox->id(mBox->selected()); +} + + +KPrefsWidString::KPrefsWidString(const QString &text,QString *reference, + QWidget *parent, QLineEdit::EchoMode echomode) +{ + mReference = reference; + + mLabel = new QLabel(text,parent); + mEdit = new QLineEdit(parent); + mEdit->setEchoMode( echomode ); +} + +KPrefsWidString::~KPrefsWidString() +{ +} + +void KPrefsWidString::readConfig() +{ + mEdit->setText(*mReference); +} + +void KPrefsWidString::writeConfig() +{ + *mReference = mEdit->text(); +} + +QLabel *KPrefsWidString::label() +{ + return mLabel; +} + +QLineEdit *KPrefsWidString::lineEdit() +{ + return mEdit; +} + + +KPrefsDialog::KPrefsDialog(KPrefs *prefs,QWidget *parent,char *name,bool modal) : + KDialogBase(IconList,i18n("Preferences"),Ok|Cancel|Default,Ok,parent, + name,modal,true) +{ + mPrefs = prefs; + +// This seems to cause a crash on exit. Investigate later. +// mPrefsWids.setAutoDelete(true); + + connect(this,SIGNAL(defaultClicked()),SLOT(slotDefault())); + //connect(this,SIGNAL(cancelClicked()),SLOT(slotDefault())); + //connect(this,SIGNAL(cancelClicked()),SLOT(reject())); +} + +KPrefsDialog::~KPrefsDialog() +{ +} + +void KPrefsDialog::addWid(KPrefsWid *wid) +{ + mPrefsWids.append(wid); +} + +KPrefsWidBool *KPrefsDialog::addWidBool(const QString &text,bool *reference,QWidget *parent) +{ + KPrefsWidBool *w = new KPrefsWidBool(text,reference,parent); + addWid(w); + return w; +} + +KPrefsWidTime *KPrefsDialog::addWidTime(const QString &text,int *reference,QWidget *parent) +{ + KPrefsWidTime *w = new KPrefsWidTime(text,reference,parent); + addWid(w); + return w; +} + +KPrefsWidColor *KPrefsDialog::addWidColor(const QString &text,QColor *reference,QWidget *parent) +{ + KPrefsWidColor *w = new KPrefsWidColor(text,reference,parent); + addWid(w); + return w; +} + +KPrefsWidRadios *KPrefsDialog::addWidRadios(const QString &text,int *reference,QWidget *parent) +{ + KPrefsWidRadios *w = new KPrefsWidRadios(text,reference,parent); + addWid(w); + return w; +} + +KPrefsWidString *KPrefsDialog::addWidString(const QString &text,QString *reference,QWidget *parent) +{ + KPrefsWidString *w = new KPrefsWidString(text,reference,parent); + addWid(w); + return w; +} + +KPrefsWidString *KPrefsDialog::addWidPassword(const QString &text,QString *reference,QWidget *parent) +{ + KPrefsWidString *w = new KPrefsWidString(text,reference,parent,QLineEdit::Password); + addWid(w); + return w; +} + +KPrefsWidFont *KPrefsDialog::addWidFont(const QString &sampleText,const QString &buttonText, + QFont *reference,QWidget *parent) +{ + KPrefsWidFont *w = new KPrefsWidFont(sampleText,buttonText,reference,parent); + addWid(w); + return w; +} + +void KPrefsDialog::setDefaults() +{ + mPrefs->setDefaults(); + + readConfig(); +} + +void KPrefsDialog::readConfig() +{ +// kdDebug(5300) << "KPrefsDialog::readConfig()" << endl; + + KPrefsWid *wid; + for(wid = mPrefsWids.first();wid;wid=mPrefsWids.next()) { + wid->readConfig(); + } + + usrReadConfig(); +} + +void KPrefsDialog::writeConfig() +{ +// kdDebug(5300) << "KPrefsDialog::writeConfig()" << endl; + + KPrefsWid *wid; + for(wid = mPrefsWids.first();wid;wid=mPrefsWids.next()) { + wid->writeConfig(); + } + + usrWriteConfig(); + +// kdDebug(5300) << "KPrefsDialog::writeConfig() now writing..." << endl; + + mPrefs->writeConfig(); + +// kdDebug(5300) << "KPrefsDialog::writeConfig() done" << endl; +} + + +void KPrefsDialog::slotApply() +{ + writeConfig(); + emit configChanged(); +} + +void KPrefsDialog::slotOk() +{ + slotApply(); + QDialog::accept(); +} +void KPrefsDialog::accept() +{ + slotOk(); +} + +void KPrefsDialog::slotDefault() +{ + if (KMessageBox::warningContinueCancel(this, + i18n("You are about to set all\npreferences to default values.\nAll " + "custom modifications will be lost."),i18n("Setting Default Preferences"), + i18n("Continue")) + == KMessageBox::Continue) setDefaults(); +} diff --git a/libkdepim/kprefsdialog.h b/libkdepim/kprefsdialog.h new file mode 100644 index 0000000..dceab01 --- a/dev/null +++ b/libkdepim/kprefsdialog.h @@ -0,0 +1,446 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef _KPREFSDIALOG_H +#define _KPREFSDIALOG_H +// $Id$ + +#include <qptrlist.h> +#include <qlineedit.h> + +#include <kdialogbase.h> + +class KPrefs; +class KPrefsDialog; + +class KColorButton; +class QCheckBox; +class QLabel; +class QSpinBox; +class QButtonGroup; + +/** + @short Base class for widgets used by @ref KPrefsDialog. + @author Cornelius Schumacher + @see KPrefsDialog + + This class provides the interface for the preferences widgets used by + KPrefsDialog. +*/ +class KPrefsWid +{ + public: + /** + This function is called to read value of the setting from the + stored configuration and display it in the widget. + */ + virtual void readConfig() = 0; + /** + This function is called to write the current setting of the widget to the + stored configuration. + */ + virtual void writeConfig() = 0; +}; + +/** + @short Widget for bool settings in @ref KPrefsDialog. + + This class provides a widget for configuring bool values. It is meant to be + used by KPrefsDialog. The user is responsible for the layout management. +*/ +class KPrefsWidBool : public KPrefsWid +{ + public: + /** + Create a bool widget consisting of a QCheckbox. + + @param text Text of QCheckBox. + @param reference Pointer to variable read and written by this widget. + @param parent Parent widget. + */ + KPrefsWidBool(const QString &text,bool *reference,QWidget *parent); + + /** + Return the QCheckbox used by this widget. + */ + QCheckBox *checkBox(); + + void readConfig(); + void writeConfig(); + + private: + bool *mReference; + + QCheckBox *mCheck; +}; + +/** + @short Widget for time settings in @ref KPrefsDialog. + + This class provides a widget for configuring time values. It is meant to be + used by KPrefsDialog. The user is responsible for the layout management. +*/ +class KPrefsWidTime : public KPrefsWid +{ + public: + /** + Create a time widget consisting of a label and a spinbox. + + @param text Text of Label. + @param reference Pointer to variable read and written by this widget. + @param parent Parent widget. + */ + KPrefsWidTime(const QString &text,int *reference,QWidget *parent); + + /** + Return QLabel used by this widget. + */ + QLabel *label(); + /** + Return QSpinBox used by this widget. + */ + QSpinBox *spinBox(); + + void readConfig(); + void writeConfig(); + + private: + int *mReference; + + QLabel *mLabel; + QSpinBox *mSpin; +}; + +/** + @short Widget for color settings in @ref KPrefsDialog. + + This class provides a widget for configuring color values. It is meant to be + used by KPrefsDialog. The user is responsible for the layout management. +*/ +class KPrefsWidColor : public QObject, public KPrefsWid +{ + Q_OBJECT + public: + /** + Create a color widget consisting of a test field and a button for opening + a color dialog. + + @param text Text of button. + @param reference Pointer to variable read and written by this widget. + @param parent Parent widget. + */ + KPrefsWidColor(const QString &text,QColor *reference,QWidget *parent); + /** + Destruct color setting widget. + */ + ~KPrefsWidColor(); + + /** + Return QLabel for the button + */ + QLabel *label(); + /** + Return button opening the color dialog. + */ + KColorButton *button(); + + void readConfig(); + void writeConfig(); + + private: + QColor *mReference; + + QLabel *mLabel; + KColorButton *mButton; +}; + +/** + @short Widget for font settings in @ref KPrefsDialog. + + This class provides a widget for configuring font values. It is meant to be + used by KPrefsDialog. The user is responsible for the layout management. +*/ +class KPrefsWidFont : public QObject, public KPrefsWid +{ + Q_OBJECT + public: + /** + Create a font widget consisting of a test field and a button for opening + a font dialog. + + @param label Text of label. + @param reference Pointer to variable read and written by this widget. + @param parent Parent widget. + */ + KPrefsWidFont(const QString &sampleText,const QString &labelText, + QFont *reference,QWidget *parent); + /** + Destruct font setting widget. + */ + ~KPrefsWidFont(); + + /** + Return label. + */ + QLabel *label(); + /** + Return QFrame used as preview field. + */ + QLabel *preview(); + /** + Return button opening the font dialog. + */ + QPushButton *button(); + + void readConfig(); + void writeConfig(); + + protected slots: + void selectFont(); + + private: + QFont *mReference; + + QLabel *mLabel; + QLabel *mPreview; + QPushButton *mButton; +}; + +/** + @short Widget for settings represented by a group of radio buttons in + @ref KPrefsDialog. + + This class provides a widget for configuring selections. It is meant to be + used by KPrefsDialog. The user is responsible for the layout management. The + setting is interpreted as an int value, corresponding to the position of the + radio button. The position of the button is defined by the sequence of @ref + addRadio() calls, starting with 0. +*/ +class KPrefsWidRadios : public KPrefsWid +{ + public: + /** + Create a widget for selection of an option. It consists of a box with + several radio buttons. + + @param text Text of main box. + @param reference Pointer to variable read and written by this widget. + @param parent Parent widget. + */ + KPrefsWidRadios(const QString &text,int *reference,QWidget *parent); + virtual ~KPrefsWidRadios(); + + /** + Add a radio button. + + @param text Text of the button. + */ + void addRadio(const QString &text); + + /** + Return the box widget used by this widget. + */ + QButtonGroup *groupBox(); + + void readConfig(); + void writeConfig(); + + private: + int *mReference; + + QButtonGroup *mBox; +}; + + +/** + @short Widget for string settings in @ref KPrefsDialog. + + This class provides a widget for configuring string values. It is meant to be + used by KPrefsDialog. The user is responsible for the layout management. +*/ +class KPrefsWidString : public KPrefsWid +{ + public: + /** + Create a string widget consisting of a test label and a line edit. + + @param text Text of label. + @param reference Pointer to variable read and written by this widget. + @param parent Parent widget. + */ + KPrefsWidString(const QString &text,QString *reference,QWidget *parent,QLineEdit::EchoMode echomode=QLineEdit::Normal); + /** + Destructor. + */ + virtual ~KPrefsWidString(); + + /** + Return label used by this widget. + */ + QLabel *label(); + /** + Return QLineEdit used by this widget. + */ + QLineEdit *lineEdit(); + + void readConfig(); + void writeConfig(); + + private: + QString *mReference; + + QLabel *mLabel; + QLineEdit *mEdit; +}; + + +/** + @short Base class for a preferences dialog. + + This class provides the framework for a preferences dialog. You have to + subclass it and add the code to create the actual configuration widgets and + do the layout management. + + KPrefsDialog provides functions to add subclasses of @ref KPrefsWid. For + these widgets the reading, writing and setting to default values is handled + automatically. Custom widgets have to be handled in the functions @ref + usrReadConfig() and @ref usrWriteConfig(). +*/ +class KPrefsDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + Create a KPrefsDialog for a KPrefs object. + + @param prefs KPrefs object used to access te configuration. + @param parent Parent widget. + @param name Widget name. + @param modal true, if dialog has to be modal, false for non-modal. + */ + KPrefsDialog(KPrefs *prefs,QWidget *parent=0,char *name=0,bool modal=false); + /** + Destructor. + */ + virtual ~KPrefsDialog(); + + /** + Register a custom KPrefsWid object. + */ + void addWid(KPrefsWid *); + /** + Register a @ref KPrefsWidBool object. + + @param text Text of bool widget. + @param reference Reference to variable storing the setting. + @param parent Parent widget. + */ + KPrefsWidBool *addWidBool(const QString &text,bool *reference,QWidget *parent); + /** + Register a @ref KPrefsWidTime object. + + @param text Text of time widget. + @param reference Reference to variable storing the setting. + @param parent Parent widget. + */ + KPrefsWidTime *addWidTime(const QString &text,int *reference,QWidget *parent); + /** + Register a @ref KPrefsWidColor object. + + @param text Text of color widget. + @param reference Reference to variable storing the setting. + @param parent Parent widget. + */ + KPrefsWidColor *addWidColor(const QString &text,QColor *reference,QWidget *parent); + /** + Register a @ref KPrefsWidRadios object. + + @param text Text of radio button box widget. + @param reference Reference to variable storing the setting. + @param parent Parent widget. + */ + KPrefsWidRadios *addWidRadios(const QString &text,int *reference,QWidget *parent); + /** + Register a @ref KPrefsWidString object. + + @param text Text of string widget. + @param reference Reference to variable storing the setting. + @param parent Parent widget. + */ + KPrefsWidString *addWidString(const QString &text,QString *reference,QWidget *parent); + /** + Register a password @ref KPrefsWidString object, with echomode set to QLineEdit::Password. + + @param text Text of string widget. + @param reference Reference to variable storing the setting. + @param parent Parent widget. + */ + KPrefsWidString *addWidPassword (const QString &text,QString *reference,QWidget *parent); + /** + Register a @ref KPrefsWidFont object. + + @param sampleText Sample text of font widget. + @param buttonText Button text of font widget. + @param reference Reference to variable storing the setting. + @param parent Parent widget. + */ + KPrefsWidFont *addWidFont(const QString &sampleText,const QString &buttonText, + QFont *reference,QWidget *parent); + + public slots: + /** Set all widgets to default values. */ + void setDefaults(); + + /** Read preferences from config file. */ + void readConfig(); + + /** Write preferences to config file. */ + void writeConfig(); + + signals: + /** Emitted when the a changed configuration has been stored. */ + void configChanged(); + + protected slots: + /** Apply changes to preferences */ + void slotApply(); + + void accept(); + /** Accept changes to preferences and close dialog */ + void slotOk(); + + /** Set preferences to default values */ + void slotDefault(); + + protected: + /** Implement this to read custom configuration widgets. */ + virtual void usrReadConfig() {} + /** Implement this to write custom configuration widgets. */ + virtual void usrWriteConfig() {} + + private: + KPrefs *mPrefs; + + QPtrList<KPrefsWid> mPrefsWids; +}; + +#endif diff --git a/libkdepim/kprefsdialog.moc b/libkdepim/kprefsdialog.moc new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/libkdepim/kprefsdialog.moc diff --git a/libkdepim/ksyncprofile.cpp b/libkdepim/ksyncprofile.cpp new file mode 100644 index 0000000..d6d8fa3 --- a/dev/null +++ b/libkdepim/ksyncprofile.cpp @@ -0,0 +1,125 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2004 Lutz Rogowski <rogowski@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// $Id$ + +#include <qcolor.h> + +#include <kconfig.h> +#include <kstandarddirs.h> +#include <kglobal.h> +#include <kdebug.h> + +#include "ksyncprofile.h" + + +KSyncProfile::KSyncProfile( const char * name): QObject (0, name ) +{ + setDefault(); +} +KSyncProfile::~KSyncProfile() +{ + +} + + +KSyncProfile* KSyncProfile::clone() +{ + KSyncProfile* myClone = new KSyncProfile(); + myClone->setPreSyncCommand( mPreSyncCommand ); + myClone->setPostSyncCommand( mPostSyncCommand ); + myClone->setLocalTempFile( mLocalTempFile); + myClone->setRemoteFileName( mRemoteFileName ); + myClone->setShowSummaryAfterSync( mShowSummaryAfterSync ); + myClone->setAskForPreferences( mAskForPreferences); + myClone->setWriteBackExisting(mWriteBackExisting ); + myClone->setWriteBackFile( mWriteBackFile); + myClone->setIncludeInRingSync( mIncludeInRingSync ); + myClone->setSyncPrefs( mSyncPrefs); + myClone->setIsLocalFileSync( mIsLocalFileSync ); + myClone->setName( "noName" ); + return myClone; +} + + +void KSyncProfile::setDefault() +{ + mName = "noName"; + mPreSyncCommand = i18n("command for downloading remote file to local device"); + mPostSyncCommand = i18n("command for uploading local temp file to remote device"); + mLocalTempFile = "/tmp/mycalendar.ics"; + mRemoteFileName = "/home/polo/kdepim/apps/korganizer/localfile.ics"; + mShowSummaryAfterSync = true; + mAskForPreferences = true; + mWriteBackExisting = false; + mWriteBackFile = true; + mIncludeInRingSync = false; + mSyncPrefs = SYNC_PREF_ASK; + mIsLocalFileSync = true; + +} +void KSyncProfile::readConfig(KConfig *config ) +{ + config->setGroup("SyncProfiles"); + QString prefix = "Profile_"+mName+"_"; + //mName = config->readEntry( prefix+ "Name", mName ); + mPreSyncCommand = config->readEntry( prefix+ "PreSyncCommand",mPreSyncCommand ); + mPostSyncCommand = config->readEntry( prefix+ "PostSyncCommand", mPostSyncCommand ); + mIncludeInRingSync = config->readBoolEntry( prefix+ "IncludeInRingSync",mIncludeInRingSync ); + mLocalTempFile = config->readEntry( prefix+ "LocalTempFile", mLocalTempFile ); + mRemoteFileName = config->readEntry( prefix+ "RemoteFileName", mRemoteFileName ); + mShowSummaryAfterSync = config->readBoolEntry( prefix+ "ShowSummaryAfterSync", mShowSummaryAfterSync ); + mAskForPreferences = config->readBoolEntry( prefix+ "AskForPreferences",mAskForPreferences ); + mWriteBackExisting = config->readBoolEntry( prefix+ "WriteBackExisting",mWriteBackExisting ); + mSyncPrefs = config->readNumEntry( prefix+ "SyncPrefs", mSyncPrefs ); + mIsLocalFileSync= config->readBoolEntry( prefix+ "IsLocalFileSync", mIsLocalFileSync ); +} +void KSyncProfile::writeConfig( KConfig * config ) +{ + config->setGroup("SyncProfiles"); + QString prefix = "Profile_"+mName+"_"; + // config->writeEntry( prefix+ "Name", mName ); + config->writeEntry( prefix+ "PreSyncCommand",mPreSyncCommand ); + config->writeEntry( prefix+ "PostSyncCommand", mPostSyncCommand ); + config->writeEntry( prefix+ "IncludeInRingSync",mIncludeInRingSync ); + config->writeEntry( prefix+ "LocalTempFile", mLocalTempFile ); + config->writeEntry( prefix+ "RemoteFileName", mRemoteFileName ); + config->writeEntry( prefix+ "ShowSummaryAfterSync", mShowSummaryAfterSync ); + config->writeEntry( prefix+ "AskForPreferences",mAskForPreferences ); + config->writeEntry( prefix+ "WriteBackExisting",mWriteBackExisting ); + config->writeEntry( prefix+ "SyncPrefs", mSyncPrefs ); + config->writeEntry( prefix+ "IsLocalFileSync", mIsLocalFileSync ); +} + +/* +class KPrefsItemInt : public KPrefsItem { + public: + KPrefsItemInt(const QString &group,const QString &name,int *,int defaultValue=0); + virtual ~KPrefsItemInt() {} + + void setDefault(); + void readConfig(KConfig *); + void writeConfig(KConfig *); + + private: + int *mReference; + int mDefault; +}; +*/ diff --git a/libkdepim/ksyncprofile.h b/libkdepim/ksyncprofile.h new file mode 100644 index 0000000..238ffad --- a/dev/null +++ b/libkdepim/ksyncprofile.h @@ -0,0 +1,106 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2004 Lutz Rogowski <rogowski@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef _KSYNCPROFILE_H +#define _KSYNCPROFILE_H + +#include <qptrlist.h> +#include <qcolor.h> +#include <qfont.h> +#include <qstringlist.h> +#include <qobject.h> +#include <qstring.h> + +#define SYNC_PREF_LOCAL 0 +#define SYNC_PREF_REMOTE 1 +#define SYNC_PREF_NEWEST 2 +#define SYNC_PREF_ASK 3 +#define SYNC_PREF_FORCE_LOCAL 4 +#define SYNC_PREF_FORCE_REMOTE 5 +#define SYNC_PREF_TAKE_BOTH 6 + +class KConfig; + +/** + @short Class for storing a preferences setting + @author Cornelius Schumacher + @see KPref + + This class represents one preferences setting as used by @ref KPrefs. + Subclasses of KPrefsItem implement storage functions for a certain type of + setting. Normally you don't have to use this class directly. Use the special + addItem() functions of KPrefs instead. If you subclass this class you will + have to register instances with the function KPrefs::addItem(). +*/ +class KSyncProfile : public QObject { + public: + KSyncProfile( const char * name = 0); + ~KSyncProfile() ; + + KSyncProfile* clone(); + void setDefault(); + void readConfig(KConfig *); + void writeConfig(KConfig *); + void setName( const QString& n ) {mName = n;} + QString getName( ) { return mName;} + void setPreSyncCommand( const QString& n ) {mPreSyncCommand = n;} + QString getPreSyncCommand( ) { return mPreSyncCommand; } + void setPostSyncCommand( const QString& n ) {mPostSyncCommand = n;} + QString getPostSyncCommand( ) { return mPostSyncCommand;} + + void setLocalTempFile( const QString& n ) { mLocalTempFile= n;} + QString getLocalTempFile( ) { return mLocalTempFile;} + void setRemoteFileName( const QString& n ) { mRemoteFileName = n;} + QString getRemoteFileName( ) { return mRemoteFileName;} + /* + void set( const QString& n ) { = n;} + QString get( ) { return ;} + */ + + void setShowSummaryAfterSync( bool b ) { mShowSummaryAfterSync = b;} + bool getShowSummaryAfterSync( ) { return mShowSummaryAfterSync ;} + void setAskForPreferences( bool b ) { mAskForPreferences= b;} + bool getAskForPreferences( ) { return mAskForPreferences;} + void setWriteBackExisting( bool b ) { mWriteBackExisting = b;} + bool getWriteBackExisting( ) { return mWriteBackExisting;} + void setWriteBackFile( bool b ) { mWriteBackFile= b;} + bool getWriteBackFile( ) { return mWriteBackFile;} + void setIncludeInRingSync( bool b ) {mIncludeInRingSync = b;} + bool getIncludeInRingSync( ) { return mIncludeInRingSync;} + void setSyncPrefs( int n ) { mSyncPrefs= n;} + int getSyncPrefs( ) { return mSyncPrefs;} + void setIsLocalFileSync( bool b ) { mIsLocalFileSync= b;} + bool getIsLocalFileSync( ) { return mIsLocalFileSync;} + + private: + QString mName; + QString mPreSyncCommand; + QString mPostSyncCommand; + QString mLocalTempFile; + QString mRemoteFileName; + bool mIncludeInRingSync; + int mSyncPrefs; + bool mWriteBackFile; + bool mWriteBackExisting; + bool mAskForPreferences; + bool mShowSummaryAfterSync; + bool mIsLocalFileSync; +}; + +#endif diff --git a/libkdepim/libkdepim.pro b/libkdepim/libkdepim.pro new file mode 100644 index 0000000..b490899 --- a/dev/null +++ b/libkdepim/libkdepim.pro @@ -0,0 +1,50 @@ +TEMPLATE = lib +CONFIG = qt warn_on +DEFINES +=KORG_NOKABC +TARGET = microkdepim +INCLUDEPATH += ../microkde ../libkabcwrap ../microkde/kdecore . .. +DESTDIR=../bin + +DEFINES += DESKTOP_VERSION +include( ../variables.pri ) +unix : { +OBJECTS_DIR = obj/unix +MOC_DIR = moc/unix +} +win32: { +DEFINES += _WIN32_ +OBJECTS_DIR = obj/win +MOC_DIR = moc/win +} +INTERFACES = \ + +HEADERS = \ + categoryeditdialog.h \ + categoryeditdialog_base.h \ + categoryselectdialog.h \ + categoryselectdialog_base.h \ + kdateedit.h \ + kdatepicker.h \ + kinputdialog.h \ + kincidenceformatter.h \ + kpimprefs.h \ + kprefs.h \ + kprefsdialog.h \ + addresseeview.h \ + ksyncprofile.h + +SOURCES = \ + categoryeditdialog.cpp \ + categoryeditdialog_base.cpp \ + categoryselectdialog.cpp \ + categoryselectdialog_base.cpp \ + kdateedit.cpp \ + kdatepicker.cpp \ + kinputdialog.cpp \ + kincidenceformatter.cpp \ + kpimprefs.cpp \ + kprefs.cpp \ + kprefsdialog.cpp \ + addresseeview.cpp \ + ksyncprofile.cpp + diff --git a/libkdepim/libkdepimE.pro b/libkdepim/libkdepimE.pro new file mode 100644 index 0000000..05abaa5 --- a/dev/null +++ b/libkdepim/libkdepimE.pro @@ -0,0 +1,43 @@ +TEMPLATE = lib +CONFIG += qt warn_on +TARGET = microkdepim +INCLUDEPATH += ../microkde ../qtcompat ../libkabcwrap ../microkde/kdecore +INCLUDEPATH += . .. +LIBS += -lmicrokde +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR=$(QPEDIR)/lib + + +INTERFACES = \ + +HEADERS = \ + categoryeditdialog.h \ + categoryeditdialog_base.h \ + categoryselectdialog.h \ + categoryselectdialog_base.h \ + kdateedit.h \ + kdatepicker.h \ + kinputdialog.h \ + kincidenceformatter.h \ + kpimprefs.h \ + kprefs.h \ + kprefsdialog.h \ + addresseeview.h \ + ksyncprofile.h + + +SOURCES = \ + categoryeditdialog.cpp \ + categoryeditdialog_base.cpp \ + categoryselectdialog.cpp \ + categoryselectdialog_base.cpp \ + kdateedit.cpp \ + kinputdialog.cpp \ + kdatepicker.cpp \ + kincidenceformatter.cpp \ + kpimprefs.cpp \ + kprefs.cpp \ + kprefsdialog.cpp \ + addresseeview.cpp \ + ksyncprofile.cpp diff --git a/microkde/KDGanttMinimizeSplitter.cpp b/microkde/KDGanttMinimizeSplitter.cpp new file mode 100644 index 0000000..60b8bc7 --- a/dev/null +++ b/microkde/KDGanttMinimizeSplitter.cpp @@ -0,0 +1,1636 @@ +/* -*- Mode: C++ -*- + $Id$ +*/ + +/**************************************************************************** + ** Copyright (C) 2002-2004 Klarälvdalens Datakonsult AB. All rights reserved. + ** + ** This file is part of the KDGantt library. + ** + ** This file may be distributed and/or modified under the terms of the + ** GNU General Public License version 2 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. + ** + ** Licensees holding valid commercial KDGantt licenses may use this file in + ** accordance with the KDGantt Commercial License Agreement provided with + ** the Software. + ** + ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + ** + ** See http://www.klaralvdalens-datakonsult.se/Public/products/ for + ** information about KDGantt Commercial License Agreements. + ** + ** Contact info@klaralvdalens-datakonsult.se if any conditions of this + ** licensing are not clear to you. + ** + ** As a special exception, permission is given to link this program + ** with any edition of Qt, and distribute the resulting executable, + ** without including the source code for Qt in the source distribution. + ** + **********************************************************************/ + +#include "KDGanttMinimizeSplitter.h" +#ifndef QT_NO_SPLITTER___ + +#include "qpainter.h" +#include "qdrawutil.h" +#include "qbitmap.h" +#if QT_VERSION >= 300 +#include "qptrlist.h" +#include "qmemarray.h" +#else +#include <qlist.h> +#include <qarray.h> +#define QPtrList QList +#define QMemArray QArray +#endif +#include "qlayoutengine_p.h" +#include "qobjectlist.h" +#include "qstyle.h" +#include "qapplication.h" //sendPostedEvents +#include <qvaluelist.h> +#include <qcursor.h> +#ifndef KDGANTT_MASTER_CVS +//#include "KDGanttMinimizeSplitter.moc" +#endif + + + +#ifndef DOXYGEN_SKIP_INTERNAL + +#if QT_VERSION >= 232 +static int mouseOffset; +static int opaqueOldPos = -1; //### there's only one mouse, but this is a bit risky + + +KDGanttSplitterHandle::KDGanttSplitterHandle( Qt::Orientation o, + KDGanttMinimizeSplitter *parent, const char * name ) + : QWidget( parent, name ), _activeButton( 0 ), _collapsed( false ) +{ + + if ( QApplication::desktop()->width() > 320 && QApplication::desktop()->width() < 650 ) { + mSizeHint = QSize(7,7); + mUseOffset = true; + } else { + mSizeHint = QSize(6,6); + mUseOffset = false; + } + s = parent; + setOrientation(o); + setMouseTracking( true ); + //setMaximumHeight( 5 ); // test only +} + +QSize KDGanttSplitterHandle::sizeHint() const +{ + return mSizeHint; +} + +void KDGanttSplitterHandle::setOrientation( Qt::Orientation o ) +{ + orient = o; +#ifndef QT_NO_CURSOR + if ( o == KDGanttMinimizeSplitter::Horizontal ) + setCursor( splitHCursor ); + else + setCursor( splitVCursor ); +#endif +} + + +void KDGanttSplitterHandle::mouseMoveEvent( QMouseEvent *e ) +{ + updateCursor( e->pos() ); + if ( !(e->state()&LeftButton) ) + return; + + if ( _activeButton != 0) + return; + + QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos())) + - mouseOffset; + if ( true /*opaque()*/ ) { + s->moveSplitter( pos, id() ); + } else { + int min = pos; int max = pos; + s->getRange( id(), &min, &max ); + s->setRubberband( QMAX( min, QMIN(max, pos ))); + } + _collapsed = false; +} + +void KDGanttSplitterHandle::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == LeftButton ) { + _activeButton = onButton( e->pos() ); + mouseOffset = s->pick(e->pos()); + if ( _activeButton != 0) + repaint(); + updateCursor( e->pos() ); + } +} + +void KDGanttSplitterHandle::updateCursor( const QPoint& p) +{ + if ( onButton( p ) != 0 ) { + setCursor( arrowCursor ); + } + else { + if ( orient == KDGanttMinimizeSplitter::Horizontal ) + setCursor( splitHCursor ); + else + setCursor( splitVCursor ); + } +} +void KDGanttSplitterHandle::toggle() +{ + int pos; + int min, max; + if ( !_collapsed ) { + s->expandPos( id(), &min, &max ); + if ( s->minimizeDirection() == KDGanttMinimizeSplitter::Left + || s->minimizeDirection() == KDGanttMinimizeSplitter::Up ) { + pos = min; + } + else { + pos = max; + } + + _origPos = s->pick(mapToParent( QPoint( 0,0 ) )); + s->moveSplitter( pos, id() ); + _collapsed = true; + } + else { + s->moveSplitter( _origPos, id() ); + _collapsed = false; + } +} + +void KDGanttSplitterHandle::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( _activeButton != 0 ) { + if ( onButton( e->pos() ) == _activeButton ) + { + toggle(); + } + _activeButton = 0; + updateCursor( e->pos() ); + } + else { + if ( !opaque() && e->button() == LeftButton ) { + QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos())) + - mouseOffset; + s->setRubberband( -1 ); + s->moveSplitter( pos, id() ); + } + } + repaint(); +} + +int KDGanttSplitterHandle::onButton( const QPoint& p ) +{ + QValueList<QPointArray> list = buttonRegions(); + int index = 1; + int add = 12; + for( QValueList<QPointArray>::Iterator it = list.begin(); it != list.end(); ++it ) { + QRect rect = (*it).boundingRect(); + rect.setLeft( rect.left()- add ); + rect.setRight( rect.right() + add); + rect.setTop( rect.top()- add ); + rect.setBottom( rect.bottom() + add); + if ( rect.contains( p ) ) { + return index; + } + index++; + } + return 0; +} + + +QValueList<QPointArray> KDGanttSplitterHandle::buttonRegions() +{ + QValueList<QPointArray> list; + + int sw = 8; + int yyy = 1; + int xxx = 1; + int voffset[] = { (int) -sw*3, (int) sw*3 }; + for ( int i = 0; i < 2; i++ ) { + QPointArray arr; + if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Right || + _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Left) { + int mid = height()/2 + voffset[i]; + arr.setPoints( 3, + 1-xxx, mid - sw + 4, + sw-3-xxx, mid, + 1-xxx, mid + sw -4); + } + else if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Left || + _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Right ) { + int mid = height()/2 + voffset[i]; + arr.setPoints( 3, + sw-4, mid - sw + 4, + 0, mid, + sw-4, mid + sw - 4); + } + else if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Up || + _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Down) { + int mid = width()/2 + voffset[i]; + arr.setPoints( 3, + mid - sw + 4, sw-4, + mid, 0, + mid + sw - 4, sw-4 ); + } + else if ( !_collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Down || + _collapsed && s->minimizeDirection() == KDGanttMinimizeSplitter::Up ) { + int mid = width()/2 + voffset[i]; + arr.setPoints( 3, + mid - sw + 4, 1-yyy, + mid, sw-3-yyy, + mid + sw -4, 1-yyy); + } + list.append( arr ); + } + return list; +} + +void KDGanttSplitterHandle::paintEvent( QPaintEvent * ) +{ + QPixmap buffer( size() ); + QPainter p( &buffer ); + + //LR + // Draw the splitter rectangle + p.setBrush( colorGroup().background() ); + p.setPen( colorGroup().foreground() ); + //p.drawRect( rect() ); + buffer.fill( colorGroup().background() ); + //buffer.fill( backgroundColor() ); + // parentWidget()->style().drawPrimitive( QStyle::PE_Panel, &p, rect(), parentWidget()->colorGroup()); + + int sw = 8; // Hardcoded, given I didn't use styles anymore, I didn't like to use their size + + // arrow color + QColor col; + if ( _activeButton ) + col = colorGroup().background().dark( 250 ); + else + col = colorGroup().background().dark( 150 ); + //QColor col = backgroundColor().dark( 130 ); + p.setBrush( col ); + p.setPen( col ); + + QValueList<QPointArray> list = buttonRegions(); + int index = 1; + if ( mUseOffset ) + p.translate( 0, 1 ); + for ( QValueList<QPointArray>::Iterator it = list.begin(); it != list.end(); ++it ) { + if ( index == _activeButton ) { + + /* + if ( ! _collapsed ) { + p.save(); + // p.translate( parentWidget()->style().pixelMetric( QStyle::PM_ButtonShiftHorizontal ), + // parentWidget()->style().pixelMetric( QStyle::PM_ButtonShiftVertical ) ); + p.translate( -1, 0 ); + p.drawPolygon( *it, true ); + p.restore(); } else + */ + p.drawPolygon( *it, true ); + + } + else { + /* + if ( ! _collapsed ) { + p.save(); + p.translate( -1, 0 ); + p.drawPolygon( *it, true ); + p.restore(); + } else + */ + p.drawPolygon( *it, true ); + + } + index++; + } + + // Draw the lines between the arrows + if ( s->minimizeDirection() == KDGanttMinimizeSplitter::Left || + s->minimizeDirection() == KDGanttMinimizeSplitter::Right ) { + int mid = height()/2; + p.drawLine ( 1, mid - sw, 1, mid + sw ); + p.drawLine ( 3, mid - sw, 3, mid + sw ); + } + else if ( s->minimizeDirection() == KDGanttMinimizeSplitter::Up || + s->minimizeDirection() == KDGanttMinimizeSplitter::Down ) { + int mid = width()/2; + p.drawLine( mid -sw, 1, mid +sw, 1 ); + p.drawLine( mid -sw, 3, mid +sw, 3 ); + } + bitBlt( this, 0, 0, &buffer ); + +} +#endif + +class QSplitterLayoutStruct +{ +public: + KDGanttMinimizeSplitter::ResizeMode mode; + QCOORD sizer; + bool isSplitter; + QWidget *wid; +}; + +class QSplitterData +{ +public: + QSplitterData() : opaque( FALSE ), firstShow( TRUE ) {} + + QPtrList<QSplitterLayoutStruct> list; + bool opaque; + bool firstShow; +}; + +void kdganttGeomCalc( QMemArray<QLayoutStruct> &chain, int start, int count, int pos, + int space, int spacer ); +#endif // DOXYGEN_SKIP_INTERNAL + + +/*! + \class KDGanttMinimizeSplitter KDGanttMinimizeSplitter.h + \brief The KDGanttMinimizeSplitter class implements a splitter + widget with minimize buttons. + + This class (and its documentation) is largely a copy of Qt's + QSplitter; the copying was necessary because QSplitter is not + extensible at all. QSplitter and its documentation are licensed + according to the GPL and the Qt Professional License (if you hold + such a license) and are (C) Trolltech AS. + + A splitter lets the user control the size of child widgets by + dragging the boundary between the children. Any number of widgets + may be controlled. + + To show a QListBox, a QListView and a QTextEdit side by side: + + \code + KDGanttMinimizeSplitter *split = new KDGanttMinimizeSplitter( parent ); + QListBox *lb = new QListBox( split ); + QListView *lv = new QListView( split ); + QTextEdit *ed = new QTextEdit( split ); + \endcode + + In KDGanttMinimizeSplitter, the boundary can be either horizontal or + vertical. The default is horizontal (the children are side by side) + but you can use setOrientation( QSplitter::Vertical ) to set it to + vertical. + + Use setResizeMode() to specify + that a widget should keep its size when the splitter is resized. + + Although KDGanttMinimizeSplitter normally resizes the children only + at the end of a resize operation, if you call setOpaqueResize( TRUE + ) the widgets are resized as often as possible. + + The initial distribution of size between the widgets is determined + by the initial size of each widget. You can also use setSizes() to + set the sizes of all the widgets. The function sizes() returns the + sizes set by the user. + + If you hide() a child, its space will be distributed among the other + children. It will be reinstated when you show() it again. It is also + possible to reorder the widgets within the splitter using + moveToFirst() and moveToLast(). +*/ + + + +static QSize minSize( const QWidget* /*w*/ ) +{ + return QSize(0,0); +} + +// This is the original version of minSize +static QSize minSizeHint( const QWidget* w ) +{ + QSize min = w->minimumSize(); + QSize s; + if ( min.height() <= 0 || min.width() <= 0 ) + s = w->minimumSizeHint(); + if ( min.height() > 0 ) + s.setHeight( min.height() ); + if ( min.width() > 0 ) + s.setWidth( min.width() ); + return s.expandedTo(QSize(0,0)); +} + + + +/*! + Constructs a horizontal splitter with the \a parent and \a + name arguments being passed on to the QFrame constructor. +*/ +KDGanttMinimizeSplitter::KDGanttMinimizeSplitter( QWidget *parent, const char *name ) + :QFrame(parent,name,WPaintUnclipped) +{ + mFirstHandle = 0; +#if QT_VERSION >= 232 + orient = Horizontal; + init(); +#endif +} + +/*! + Constructs a splitter with orientation \a o with the \a parent + and \a name arguments being passed on to the QFrame constructor. +*/ +KDGanttMinimizeSplitter::KDGanttMinimizeSplitter( Orientation o, QWidget *parent, const char *name ) + :QFrame(parent,name,WPaintUnclipped) +{ + mFirstHandle = 0; +#if QT_VERSION >= 232 + orient = o; + init(); +#endif +} + +/*! + Destroys the splitter and any children. +*/ +KDGanttMinimizeSplitter::~KDGanttMinimizeSplitter() +{ +#if QT_VERSION >= 232 + data->list.setAutoDelete( TRUE ); + delete data; +#endif +} + + +#if QT_VERSION >= 232 +void KDGanttMinimizeSplitter::init() +{ + data = new QSplitterData; + if ( orient == Horizontal ) + setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum) ); + else + setSizePolicy( QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Expanding) ); +} +#endif + + + +/*! + \brief the orientation of the splitter + + By default the orientation is horizontal (the widgets are side by side). + The possible orientations are Qt:Vertical and Qt::Horizontal (the default). +*/ +void KDGanttMinimizeSplitter::setOrientation( Orientation o ) +{ +#if QT_VERSION >= 232 + if ( orient == o ) + return; + orient = o; + + if ( orient == Horizontal ) + setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + else + setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) ); + + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->isSplitter ) + ((KDGanttSplitterHandle*)s->wid)->setOrientation( o ); + s = data->list.next(); // ### next at end of loop, no iterator + } + recalc( isVisible() ); +#endif +} + + +#if QT_VERSION >= 232 +/*! + \reimp +*/ +void KDGanttMinimizeSplitter::resizeEvent( QResizeEvent * ) +{ + doResize(); +} + + +/* + Inserts the widget \a w at the end (or at the beginning if \a first + is TRUE) of the splitter's list of widgets. + + It is the responsibility of the caller of this function to make sure + that \a w is not already in the splitter and to call recalcId if + needed. (If \a first is TRUE, then recalcId is very probably + needed.) +*/ +QSplitterLayoutStruct *KDGanttMinimizeSplitter::addWidget( QWidget *w, bool first ) +{ + QSplitterLayoutStruct *s; + KDGanttSplitterHandle *newHandle = 0; + if ( data->list.count() > 0 ) { + s = new QSplitterLayoutStruct; + s->mode = KeepSize; + QString tmp = "qt_splithandle_"; + tmp += w->name(); + newHandle = new KDGanttSplitterHandle( orientation(), this, tmp.latin1() ); + if ( ! mFirstHandle ) + mFirstHandle = newHandle; + s->wid = newHandle; + newHandle->setId(data->list.count()); + s->isSplitter = TRUE; + s->sizer = pick( newHandle->sizeHint() ); + if ( first ) + data->list.insert( 0, s ); + else + data->list.append( s ); + } + s = new QSplitterLayoutStruct; + s->mode = Stretch; + s->wid = w; + if ( !testWState( WState_Resized ) && w->sizeHint().isValid() ) + s->sizer = pick( w->sizeHint() ); + else + s->sizer = pick( w->size() ); + s->isSplitter = FALSE; + if ( first ) + data->list.insert( 0, s ); + else + data->list.append( s ); + if ( newHandle && isVisible() ) + newHandle->show(); //will trigger sending of post events + return s; +} + + +/*! + Tells the splitter that a child widget has been inserted or removed. + The event is passed in \a c. +*/ +void KDGanttMinimizeSplitter::childEvent( QChildEvent *c ) +{ + if ( c->type() == QEvent::ChildInserted ) { + if ( !c->child()->isWidgetType() ) + return; + + if ( ((QWidget*)c->child())->testWFlags( WType_TopLevel ) ) + return; + + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == c->child() ) + return; + s = data->list.next(); + } + addWidget( (QWidget*)c->child() ); + recalc( isVisible() ); + + } else if ( c->type() == QEvent::ChildRemoved ) { + QSplitterLayoutStruct *p = 0; + if ( data->list.count() > 1 ) + p = data->list.at(1); //remove handle _after_ first widget. + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == c->child() ) { + data->list.removeRef( s ); + delete s; + if ( p && p->isSplitter ) { + data->list.removeRef( p ); + delete p->wid; //will call childEvent + delete p; + } + recalcId(); + doResize(); + return; + } + p = s; + s = data->list.next(); + } + } +} + + +/*! + Shows a rubber band at position \a p. If \a p is negative, the + rubber band is removed. +*/ +void KDGanttMinimizeSplitter::setRubberband( int p ) +{ + QPainter paint( this ); + paint.setPen( gray ); + paint.setBrush( gray ); + paint.setRasterOp( XorROP ); + QRect r = contentsRect(); + const int rBord = 3; //Themable???? +#if QT_VERSION >= 300 + int sw = style().pixelMetric(QStyle::PM_SplitterWidth, this); +#else + int sw = style().splitterWidth(); +#endif + if ( orient == Horizontal ) { + if ( opaqueOldPos >= 0 ) + paint.drawRect( opaqueOldPos + sw/2 - rBord , r.y(), + 2*rBord, r.height() ); + if ( p >= 0 ) + paint.drawRect( p + sw/2 - rBord, r.y(), 2*rBord, r.height() ); + } else { + if ( opaqueOldPos >= 0 ) + paint.drawRect( r.x(), opaqueOldPos + sw/2 - rBord, + r.width(), 2*rBord ); + if ( p >= 0 ) + paint.drawRect( r.x(), p + sw/2 - rBord, r.width(), 2*rBord ); + } + opaqueOldPos = p; +} + + +/*! \reimp */ +bool KDGanttMinimizeSplitter::event( QEvent *e ) +{ + if ( e->type() == QEvent::LayoutHint || ( e->type() == QEvent::Show && data->firstShow ) ) { + recalc( isVisible() ); + if ( e->type() == QEvent::Show ) + data->firstShow = FALSE; + } + return QWidget::event( e ); +} + + +/*! + \obsolete + + Draws the splitter handle in the rectangle described by \a x, \a y, + \a w, \a h using painter \a p. + \sa QStyle::drawPrimitive() +*/ +void KDGanttMinimizeSplitter::drawSplitter( QPainter *p, + QCOORD x, QCOORD y, QCOORD w, QCOORD h ) +{ +#if 0 + // LR + style().drawPrimitive(QStyle::PE_Splitter, p, QRect(x, y, w, h), colorGroup(), + (orientation() == Qt::Horizontal ? + QStyle::Style_Horizontal : 0)); +#endif +} + + +/*! + Returns the id of the splitter to the right of or below the widget \a w, + or 0 if there is no such splitter + (i.e. it is either not in this KDGanttMinimizeSplitter or it is at the end). +*/ +int KDGanttMinimizeSplitter::idAfter( QWidget* w ) const +{ + QSplitterLayoutStruct *s = data->list.first(); + bool seen_w = FALSE; + while ( s ) { + if ( s->isSplitter && seen_w ) + return data->list.at(); + if ( !s->isSplitter && s->wid == w ) + seen_w = TRUE; + s = data->list.next(); + } + return 0; +} + + +/*! + Moves the left/top edge of the splitter handle with id \a id as + close as possible to position \a p, which is the distance from the + left (or top) edge of the widget. + + For Arabic and Hebrew the layout is reversed, and using this + function to set the position of the splitter might lead to + unexpected results, since in Arabic and Hebrew the position of + splitter one is to the left of the position of splitter zero. + + \sa idAfter() +*/ +void KDGanttMinimizeSplitter::moveSplitter( QCOORD p, int id ) +{ + p = adjustPos( p, id ); + QSplitterLayoutStruct *s = data->list.at(id); + int oldP = orient == Horizontal ? s->wid->x() : s->wid->y(); + bool upLeft; + if ( false && orient == Horizontal ) { + p += s->wid->width(); + upLeft = p > oldP; + } else + upLeft = p < oldP; + + moveAfter( p, id, upLeft ); + moveBefore( p-1, id-1, upLeft ); + + storeSizes(); +} + + +void KDGanttMinimizeSplitter::setG( QWidget *w, int p, int s, bool isSplitter ) +{ + if ( orient == Horizontal ) { + if ( false && orient == Horizontal && !isSplitter ) + p = contentsRect().width() - p - s; + w->setGeometry( p, contentsRect().y(), s, contentsRect().height() ); + } else + w->setGeometry( contentsRect().x(), p, contentsRect().width(), s ); +} + + +/* + Places the right/bottom edge of the widget at \a id at position \a pos. + + \sa idAfter() +*/ +void KDGanttMinimizeSplitter::moveBefore( int pos, int id, bool upLeft ) +{ + if( id < 0 ) + return; + QSplitterLayoutStruct *s = data->list.at(id); + if ( !s ) + return; + QWidget *w = s->wid; + if ( w->isHidden() ) { + moveBefore( pos, id-1, upLeft ); + } else if ( s->isSplitter ) { + int pos1, pos2; + int dd = s->sizer; + if( false && orient == Horizontal ) { + pos1 = pos; + pos2 = pos + dd; + } else { + pos2 = pos - dd; + pos1 = pos2 + 1; + } + if ( upLeft ) { + setG( w, pos1, dd, TRUE ); + moveBefore( pos2, id-1, upLeft ); + } else { + moveBefore( pos2, id-1, upLeft ); + setG( w, pos1, dd, TRUE ); + } + } else { + int dd, newLeft, nextPos; + if( false && orient == Horizontal ) { + dd = w->geometry().right() - pos; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + newLeft = pos+1; + nextPos = newLeft + dd; + } else { + dd = pos - pick( w->pos() ) + 1; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + newLeft = pos-dd+1; + nextPos = newLeft - 1; + } + setG( w, newLeft, dd, TRUE ); + moveBefore( nextPos, id-1, upLeft ); + } +} + + +/* + Places the left/top edge of the widget at \a id at position \a pos. + + \sa idAfter() +*/ +void KDGanttMinimizeSplitter::moveAfter( int pos, int id, bool upLeft ) +{ + QSplitterLayoutStruct *s = id < int(data->list.count()) ? + data->list.at(id) : 0; + if ( !s ) + return; + QWidget *w = s->wid; + if ( w->isHidden() ) { + moveAfter( pos, id+1, upLeft ); + } else if ( pick( w->pos() ) == pos ) { + //No need to do anything if it's already there. + return; + } else if ( s->isSplitter ) { + int dd = s->sizer; + int pos1, pos2; + if( false && orient == Horizontal ) { + pos2 = pos - dd; + pos1 = pos2 + 1; + } else { + pos1 = pos; + pos2 = pos + dd; + } + if ( upLeft ) { + setG( w, pos1, dd, TRUE ); + moveAfter( pos2, id+1, upLeft ); + } else { + moveAfter( pos2, id+1, upLeft ); + setG( w, pos1, dd, TRUE ); + } + } else { + int left = pick( w->pos() ); + int right, dd,/* newRight,*/ newLeft, nextPos; + if ( false && orient == Horizontal ) { + dd = pos - left + 1; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + newLeft = pos-dd+1; + nextPos = newLeft - 1; + } else { + right = pick( w->geometry().bottomRight() ); + dd = right - pos + 1; + dd = QMAX( pick(minSize(w)), QMIN(dd, pick(w->maximumSize()))); + /*newRight = pos+dd-1;*/ + newLeft = pos; + nextPos = newLeft + dd; + } + setG( w, newLeft, dd, TRUE ); + /*if( right != newRight )*/ + moveAfter( nextPos, id+1, upLeft ); + } +} + + +void KDGanttMinimizeSplitter::expandPos( int id, int* min, int* max ) +{ + QSplitterLayoutStruct *s = data->list.at(id-1); + QWidget* w = s->wid; + *min = pick( w->mapToParent( QPoint(0,0) ) ); + + if ( (uint) id == data->list.count() ) { + pick( size() ); + } + else { + QSplitterLayoutStruct *s = data->list.at(id+1); + QWidget* w = s->wid; + *max = pick( w->mapToParent( QPoint( w->width(), w->height() ) ) ) -8; + } +} + + +/*! + Returns the valid range of the splitter with id \a id in \a *min and \a *max. + + \sa idAfter() +*/ + +void KDGanttMinimizeSplitter::getRange( int id, int *min, int *max ) +{ + int minB = 0; //before + int maxB = 0; + int minA = 0; + int maxA = 0; //after + int n = data->list.count(); + if ( id < 0 || id >= n ) + return; + int i; + for ( i = 0; i < id; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->wid->isHidden() ) { + //ignore + } else if ( s->isSplitter ) { + minB += s->sizer; + maxB += s->sizer; + } else { + minB += pick( minSize(s->wid) ); + maxB += pick( s->wid->maximumSize() ); + } + } + for ( i = id; i < n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->wid->isHidden() ) { + //ignore + } else if ( s->isSplitter ) { + minA += s->sizer; + maxA += s->sizer; + } else { + minA += pick( minSize(s->wid) ); + maxA += pick( s->wid->maximumSize() ); + } + } + QRect r = contentsRect(); + if ( orient == Horizontal && false ) { +#if QT_VERSION >= 300 + int splitterWidth = style().pixelMetric(QStyle::PM_SplitterWidth, this); +#else + int splitterWidth = style().splitterWidth(); +#endif + + if ( min ) + *min = pick(r.topRight()) - QMIN( maxB, pick(r.size())-minA ) - splitterWidth; + if ( max ) + *max = pick(r.topRight()) - QMAX( minB, pick(r.size())-maxA ) - splitterWidth; + } else { + if ( min ) + *min = pick(r.topLeft()) + QMAX( minB, pick(r.size())-maxA ); + if ( max ) + *max = pick(r.topLeft()) + QMIN( maxB, pick(r.size())-minA ); + } +} + + +/*! + Returns the closest legal position to \a p of the splitter with id \a id. + + \sa idAfter() +*/ + +int KDGanttMinimizeSplitter::adjustPos( int p, int id ) +{ + int min = 0; + int max = 0; + getRange( id, &min, &max ); + p = QMAX( min, QMIN( p, max ) ); + + return p; +} + + +void KDGanttMinimizeSplitter::doResize() +{ + QRect r = contentsRect(); + int i; + int n = data->list.count(); + QMemArray<QLayoutStruct> a( n ); + for ( i = 0; i< n; i++ ) { + a[i].init(); + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->wid->isHidden() ) { + a[i].stretch = 0; + a[i].sizeHint = a[i].minimumSize = 0; + a[i].maximumSize = 0; + } else if ( s->isSplitter ) { + a[i].stretch = 0; + a[i].sizeHint = a[i].minimumSize = a[i].maximumSize = s->sizer; + a[i].empty = FALSE; + } else if ( s->mode == KeepSize ) { + a[i].stretch = 0; + a[i].minimumSize = pick( minSize(s->wid) ); + a[i].sizeHint = s->sizer; + a[i].maximumSize = pick( s->wid->maximumSize() ); + a[i].empty = FALSE; + } else if ( s->mode == FollowSizeHint ) { + a[i].stretch = 0; + a[i].minimumSize = a[i].sizeHint = pick( s->wid->sizeHint() ); + a[i].maximumSize = pick( s->wid->maximumSize() ); + a[i].empty = FALSE; + } else { //proportional + a[i].stretch = s->sizer; + a[i].maximumSize = pick( s->wid->maximumSize() ); + a[i].sizeHint = a[i].minimumSize = pick( minSize(s->wid) ); + a[i].empty = FALSE; + } + } + + kdganttGeomCalc( a, 0, n, pick( r.topLeft() ), pick( r.size() ), 0 ); + + for ( i = 0; i< n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + setG( s->wid, a[i].pos, a[i].size ); + } + +} + + +void KDGanttMinimizeSplitter::recalc( bool update ) +{ + int fi = 2*frameWidth(); + int maxl = fi; + int minl = fi; + int maxt = QWIDGETSIZE_MAX; + int mint = fi; + int n = data->list.count(); + bool first = TRUE; + /* + The splitter before a hidden widget is always hidden. + The splitter before the first visible widget is hidden. + The splitter before any other visible widget is visible. + */ + for ( int i = 0; i< n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( !s->isSplitter ) { + QSplitterLayoutStruct *p = (i > 0) ? p = data->list.at( i-1 ) : 0; + if ( p && p->isSplitter ) + if ( first || s->wid->isHidden() ) + p->wid->hide(); //may trigger new recalc + else + p->wid->show(); //may trigger new recalc + if ( !s->wid->isHidden() ) + first = FALSE; + } + } + + bool empty=TRUE; + for ( int j = 0; j< n; j++ ) { + QSplitterLayoutStruct *s = data->list.at(j); + if ( !s->wid->isHidden() ) { + empty = FALSE; + if ( s->isSplitter ) { + minl += s->sizer; + maxl += s->sizer; + } else { + QSize minS = minSize(s->wid); + minl += pick( minS ); + maxl += pick( s->wid->maximumSize() ); + mint = QMAX( mint, trans( minS )); + int tm = trans( s->wid->maximumSize() ); + if ( tm > 0 ) + maxt = QMIN( maxt, tm ); + } + } + } + if ( empty ) { + if ( parentWidget() != 0 && parentWidget()->inherits("KDGanttMinimizeSplitter") ) { + // nested splitters; be nice + maxl = maxt = 0; + } else { + // KDGanttMinimizeSplitter with no children yet + maxl = QWIDGETSIZE_MAX; + } + } else { + maxl = QMIN( maxl, QWIDGETSIZE_MAX ); + } + if ( maxt < mint ) + maxt = mint; + + if ( orient == Horizontal ) { + setMaximumSize( maxl, maxt ); + setMinimumSize( minl, mint ); + } else { + setMaximumSize( maxt, maxl ); + setMinimumSize( mint, minl ); + } + if ( update ) + doResize(); +} + +/*! + Sets resize mode of \a w to \a mode. + + \sa ResizeMode +*/ + +void KDGanttMinimizeSplitter::setResizeMode( QWidget *w, ResizeMode mode ) +{ + processChildEvents(); + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == w ) { + s->mode = mode; + return; + } + s = data->list.next(); + } + s = addWidget( w, TRUE ); + s->mode = mode; +} + + +/*! + Returns TRUE if opaque resize is on; otherwise returns FALSE. + + \sa setOpaqueResize() +*/ + +bool KDGanttMinimizeSplitter::opaqueResize() const +{ + return data->opaque; +} + + +/*! + If \a on is TRUE then opaque resizing is turned on; otherwise + opaque resizing is turned off. + Opaque resizing is initially turned off. + + \sa opaqueResize() +*/ + +void KDGanttMinimizeSplitter::setOpaqueResize( bool on ) +{ + data->opaque = on; +} + + +/*! + Moves widget \a w to the leftmost/top position. +*/ + +void KDGanttMinimizeSplitter::moveToFirst( QWidget *w ) +{ + processChildEvents(); + bool found = FALSE; + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == w ) { + found = TRUE; + QSplitterLayoutStruct *p = data->list.prev(); + if ( p ) { // not already at first place + data->list.take(); //take p + data->list.take(); // take s + data->list.insert( 0, p ); + data->list.insert( 0, s ); + } + break; + } + s = data->list.next(); + } + if ( !found ) + addWidget( w, TRUE ); + recalcId(); +} + + +/*! + Moves widget \a w to the rightmost/bottom position. +*/ + +void KDGanttMinimizeSplitter::moveToLast( QWidget *w ) +{ + processChildEvents(); + bool found = FALSE; + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->wid == w ) { + found = TRUE; + data->list.take(); // take s + QSplitterLayoutStruct *p = data->list.current(); + if ( p ) { // the splitter handle after s + data->list.take(); //take p + data->list.append( p ); + } + data->list.append( s ); + break; + } + s = data->list.next(); + } + if ( !found ) + addWidget( w); + recalcId(); +} + + +void KDGanttMinimizeSplitter::recalcId() +{ + int n = data->list.count(); + for ( int i = 0; i < n; i++ ) { + QSplitterLayoutStruct *s = data->list.at(i); + if ( s->isSplitter ) + ((KDGanttSplitterHandle*)s->wid)->setId(i); + } +} + + +/*!\reimp +*/ +QSize KDGanttMinimizeSplitter::sizeHint() const +{ + constPolish(); + int l = 0; + int t = 0; + if ( children() ) { + const QObjectList * c = children(); + QObjectListIt it( *c ); + QObject * o; + + while( (o=it.current()) != 0 ) { + ++it; + if ( o->isWidgetType() && + !((QWidget*)o)->isHidden() ) { + QSize s = ((QWidget*)o)->sizeHint(); + if ( s.isValid() ) { + l += pick( s ); + t = QMAX( t, trans( s ) ); + } + } + } + } + return orientation() == Horizontal ? QSize( l, t ) : QSize( t, l ); +} + + +/*! +\reimp +*/ + +QSize KDGanttMinimizeSplitter::minimumSizeHint() const +{ + constPolish(); + int l = 0; + int t = 0; + if ( children() ) { + const QObjectList * c = children(); + QObjectListIt it( *c ); + QObject * o; + + while( (o=it.current()) != 0 ) { + ++it; + if ( o->isWidgetType() && + !((QWidget*)o)->isHidden() ) { + QSize s = minSizeHint((QWidget*)o); + if ( s.isValid() ) { + l += pick( s ); + t = QMAX( t, trans( s ) ); + } + } + } + } + return orientation() == Horizontal ? QSize( l, t ) : QSize( t, l ); +} + + +/* + Calculates stretch parameters from current sizes +*/ + +void KDGanttMinimizeSplitter::storeSizes() +{ + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( !s->isSplitter ) + s->sizer = pick( s->wid->size() ); + s = data->list.next(); + } +} + + +#if 0 // ### remove this code ASAP + +/*! + Hides \a w if \a hide is TRUE and updates the splitter. + + \warning Due to a limitation in the current implementation, + calling QWidget::hide() will not work. +*/ + +void KDGanttMinimizeSplitter::setHidden( QWidget *w, bool hide ) +{ + if ( w == w1 ) { + w1show = !hide; + } else if ( w == w2 ) { + w2show = !hide; + } else { +#ifdef QT_CHECK_RANGE + qWarning( "KDGanttMinimizeSplitter::setHidden(), unknown widget" ); +#endif + return; + } + if ( hide ) + w->hide(); + else + w->show(); + recalc( TRUE ); +} + + +/*! + Returns the hidden status of \a w +*/ + +bool KDGanttMinimizeSplitter::isHidden( QWidget *w ) const +{ + if ( w == w1 ) + return !w1show; + else if ( w == w2 ) + return !w2show; +#ifdef QT_CHECK_RANGE + else + qWarning( "KDGanttMinimizeSplitter::isHidden(), unknown widget" ); +#endif + return FALSE; +} +#endif + + +/*! + Returns a list of the size parameters of all the widgets in this + splitter. + + Giving the values to another splitter's setSizes() function will + produce a splitter with the same layout as this one. + + Note that if you want to iterate over the list, you should + iterate over a copy, e.g. + \code + QValueList<int> list = mySplitter.sizes(); + QValueList<int>::Iterator it = list.begin(); + while( it != list.end() ) { + myProcessing( *it ); + ++it; + } + \endcode + + \sa setSizes() +*/ + +QValueList<int> KDGanttMinimizeSplitter::sizes() const +{ + if ( !testWState(WState_Polished) ) { + QWidget* that = (QWidget*) this; + that->polish(); + } + QValueList<int> list; + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( !s->isSplitter ) + list.append( s->sizer ); + s = data->list.next(); + } + return list; +} + + + +/*! + Sets the size parameters to the values given in \a list. + If the splitter is horizontal, the values set the sizes from + left to right. If it is vertical, the sizes are applied from + top to bottom. + Extra values in \a list are ignored. + + If \a list contains too few values, the result is undefined + but the program will still be well-behaved. + + \sa sizes() +*/ + +void KDGanttMinimizeSplitter::setSizes( QValueList<int> list ) +{ + processChildEvents(); + QValueList<int>::Iterator it = list.begin(); + QSplitterLayoutStruct *s = data->list.first(); + while ( s && it != list.end() ) { + if ( !s->isSplitter ) { + s->sizer = *it; + ++it; + } + s = data->list.next(); + } + doResize(); +} + + +/*! + Gets all posted child events, ensuring that the internal state of + the splitter is consistent. +*/ + +void KDGanttMinimizeSplitter::processChildEvents() +{ + QApplication::sendPostedEvents( this, QEvent::ChildInserted ); +} + + +/*! + \reimp +*/ + +void KDGanttMinimizeSplitter::styleChange( QStyle& old ) +{ + +#if QT_VERSION >= 300 + int sw = style().pixelMetric(QStyle::PM_SplitterWidth, this); +#else + int sw = style().splitterWidth(); +#endif + QSplitterLayoutStruct *s = data->list.first(); + while ( s ) { + if ( s->isSplitter ) + s->sizer = sw; + s = data->list.next(); + } + doResize(); + QFrame::styleChange( old ); +} + +#endif + +/*! + Specifies the direction of the minimize buttons. + If the orientation of the splitter is horizontal then with + KDGanttMinimizeSplitter::Left or KDGanttMinimizeSplitter::Right should be used, + otherwise either KDGanttMinimizeSplitter::Up or KDGanttMinimizeSplitter::Down + should be used. +*/ +void KDGanttMinimizeSplitter::setMinimizeDirection( Direction direction ) +{ + _direction = direction; +} + +/*! + Returns the direction of the minimize buttons. +*/ +KDGanttMinimizeSplitter::Direction KDGanttMinimizeSplitter::minimizeDirection() const +{ + return _direction; +} + +/* + This is a copy of qGeomCalc() in qlayoutengine.cpp which + unfortunately isn't exported. +*/ +static inline int toFixed( int i ) { return i * 256; } +static inline int fRound( int i ) { + return ( i % 256 < 128 ) ? i / 256 : 1 + i / 256; +} +void kdganttGeomCalc( QMemArray<QLayoutStruct> &chain, int start, int count, int pos, + int space, int spacer ) +{ + typedef int fixed; + int cHint = 0; + int cMin = 0; + int cMax = 0; + int sumStretch = 0; + int spacerCount = 0; + + bool wannaGrow = FALSE; // anyone who really wants to grow? + // bool canShrink = FALSE; // anyone who could be persuaded to shrink? + + int i; + for ( i = start; i < start + count; i++ ) { + chain[i].done = FALSE; + cHint += chain[i].sizeHint; + cMin += chain[i].minimumSize; + cMax += chain[i].maximumSize; + sumStretch += chain[i].stretch; + if ( !chain[i].empty ) + spacerCount++; + wannaGrow = wannaGrow || chain[i].expansive; + } + + int extraspace = 0; + if ( spacerCount ) + spacerCount--; // only spacers between things + if ( space < cMin + spacerCount * spacer ) { + // qDebug("not enough space"); + for ( i = start; i < start+count; i++ ) { + chain[i].size = chain[i].minimumSize; + chain[i].done = TRUE; + } + } else if ( space < cHint + spacerCount*spacer ) { + // Less space than sizeHint, but more than minimum. + // Currently take space equally from each, like in Qt 2.x. + // Commented-out lines will give more space to stretchier items. + int n = count; + int space_left = space - spacerCount*spacer; + int overdraft = cHint - space_left; + //first give to the fixed ones: + for ( i = start; i < start+count; i++ ) { + if ( !chain[i].done && chain[i].minimumSize >= chain[i].sizeHint) { + chain[i].size = chain[i].sizeHint; + chain[i].done = TRUE; + space_left -= chain[i].sizeHint; + // sumStretch -= chain[i].stretch; + n--; + } + } + bool finished = n == 0; + while ( !finished ) { + finished = TRUE; + fixed fp_over = toFixed( overdraft ); + fixed fp_w = 0; + + for ( i = start; i < start+count; i++ ) { + if ( chain[i].done ) + continue; + // if ( sumStretch <= 0 ) + fp_w += fp_over / n; + // else + // fp_w += (fp_over * chain[i].stretch) / sumStretch; + int w = fRound( fp_w ); + chain[i].size = chain[i].sizeHint - w; + fp_w -= toFixed( w ); //give the difference to the next + if ( chain[i].size < chain[i].minimumSize ) { + chain[i].done = TRUE; + chain[i].size = chain[i].minimumSize; + finished = FALSE; + overdraft -= chain[i].sizeHint - chain[i].minimumSize; + // sumStretch -= chain[i].stretch; + n--; + break; + } + } + } + } else { //extra space + int n = count; + int space_left = space - spacerCount*spacer; + // first give to the fixed ones, and handle non-expansiveness + for ( i = start; i < start + count; i++ ) { + if ( !chain[i].done && (chain[i].maximumSize <= chain[i].sizeHint + || wannaGrow && !chain[i].expansive) ) { + chain[i].size = chain[i].sizeHint; + chain[i].done = TRUE; + space_left -= chain[i].sizeHint; + sumStretch -= chain[i].stretch; + n--; + } + } + extraspace = space_left; + /* + Do a trial distribution and calculate how much it is off. + If there are more deficit pixels than surplus pixels, give + the minimum size items what they need, and repeat. + Otherwise give to the maximum size items, and repeat. + + I have a wonderful mathematical proof for the correctness + of this principle, but unfortunately this comment is too + small to contain it. + */ + int surplus, deficit; + do { + surplus = deficit = 0; + fixed fp_space = toFixed( space_left ); + fixed fp_w = 0; + for ( i = start; i < start+count; i++ ) { + if ( chain[i].done ) + continue; + extraspace = 0; + if ( sumStretch <= 0 ) + fp_w += fp_space / n; + else + fp_w += (fp_space * chain[i].stretch) / sumStretch; + int w = fRound( fp_w ); + chain[i].size = w; + fp_w -= toFixed( w ); // give the difference to the next + if ( w < chain[i].sizeHint ) { + deficit += chain[i].sizeHint - w; + } else if ( w > chain[i].maximumSize ) { + surplus += w - chain[i].maximumSize; + } + } + if ( deficit > 0 && surplus <= deficit ) { + // give to the ones that have too little + for ( i = start; i < start+count; i++ ) { + if ( !chain[i].done && + chain[i].size < chain[i].sizeHint ) { + chain[i].size = chain[i].sizeHint; + chain[i].done = TRUE; + space_left -= chain[i].sizeHint; + sumStretch -= chain[i].stretch; + n--; + } + } + } + if ( surplus > 0 && surplus >= deficit ) { + // take from the ones that have too much + for ( i = start; i < start+count; i++ ) { + if ( !chain[i].done && + chain[i].size > chain[i].maximumSize ) { + chain[i].size = chain[i].maximumSize; + chain[i].done = TRUE; + space_left -= chain[i].maximumSize; + sumStretch -= chain[i].stretch; + n--; + } + } + } + } while ( n > 0 && surplus != deficit ); + if ( n == 0 ) + extraspace = space_left; + } + + // as a last resort, we distribute the unwanted space equally + // among the spacers (counting the start and end of the chain). + + //### should do a sub-pixel allocation of extra space + int extra = extraspace / ( spacerCount + 2 ); + int p = pos + extra; + for ( i = start; i < start+count; i++ ) { + chain[i].pos = p; + p = p + chain[i].size; + if ( !chain[i].empty ) + p += spacer+extra; + } +} + +#endif + +/*! + \enum KDGanttMinimizeSplitter::Direction + + The values of this enumeration describe into which direction the + splitter will collapse its child widgets. By extension, it also + specifies the orientation of the splitter; collapsing to the left or + to the right results in a horizontal splitter, collapsing to the top + or bottom in a vertical splitter. +*/ + +/*! + \fn Orientation KDGanttMinimizeSplitter::orientation() const + + Returns the orientation of the splitter. +*/ + +/*! \enum KDGanttMinimizeSplitter::ResizeMode + + This enum type describes how KDGanttMinimizeSplitter will resize each of its child widgets. The currently defined values are: + + Stretch: the widget will be resized when the splitter + itself is resized. + + KeepSize: KDGanttMinimizeSplitter will try to keep this widget's size + unchanged. + + FollowSizeHint: KDGanttMinimizeSplitter will resize the widget when the + widget's size hint changes. +*/ + diff --git a/microkde/KDGanttMinimizeSplitter.h b/microkde/KDGanttMinimizeSplitter.h new file mode 100644 index 0000000..75e0443 --- a/dev/null +++ b/microkde/KDGanttMinimizeSplitter.h @@ -0,0 +1,186 @@ +/* -*- Mode: C++ -*- + $Id$ +*/ + +/**************************************************************************** + ** Copyright (C) 2001-2004 Klarälvdalens Datakonsult AB. All rights reserved. + ** + ** This file is part of the KDGantt library. + ** + ** This file may be distributed and/or modified under the terms of the + ** GNU General Public License version 2 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. + ** + ** Licensees holding valid commercial KDGantt licenses may use this file in + ** accordance with the KDGantt Commercial License Agreement provided with + ** the Software. + ** + ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + ** + ** See http://www.klaralvdalens-datakonsult.se/Public/products/ for + ** information about KDGantt Commercial License Agreements. + ** + ** Contact info@klaralvdalens-datakonsult.se if any conditions of this + ** licensing are not clear to you. + ** + ** As a special exception, permission is given to link this program + ** with any edition of Qt, and distribute the resulting executable, + ** without including the source code for Qt in the source distribution. + ** + **********************************************************************/ + +#ifndef KDGANTTMINIMIZESPLITTER_H +#define KDGANTTMINIMIZESPLITTER_H + +#ifndef QT_H +#include "qframe.h" +#include "qvaluelist.h" +#endif // QT_H + +#ifndef QT_NO_SPLITTER___ +class QSplitterData; +class QSplitterLayoutStruct; +class KDGanttSplitterHandle; +class KDGanttMinimizeSplitter : public QFrame +{ + Q_OBJECT + // Q_ENUMS( Direction ) + // Q_PROPERTY( Orientation orientation READ orientation WRITE setOrientation ) + // Q_PROPERTY( Direction minimizeDirection READ minimizeDirection WRITE setMinimizeDirection ) + +public: + enum ResizeMode { Stretch, KeepSize, FollowSizeHint }; + enum Direction { Left, Right, Up, Down }; + + KDGanttMinimizeSplitter( QWidget* parent=0, const char* name=0 ); + KDGanttMinimizeSplitter( Orientation, QWidget* parent=0, const char* name=0 ); + ~KDGanttMinimizeSplitter(); + + virtual void setOrientation( Orientation ); + Orientation orientation() const { return orient; } + + void setMinimizeDirection( Direction ); + Direction minimizeDirection() const; + +#if QT_VERSION >= 232 + virtual void setResizeMode( QWidget *w, ResizeMode ); + virtual void setOpaqueResize( bool = TRUE ); + bool opaqueResize() const; + + void moveToFirst( QWidget * ); + void moveToLast( QWidget * ); + + void refresh() { recalc( TRUE ); } + QSize sizeHint() const; + QSize minimumSizeHint() const; + + QValueList<int> sizes() const; + void setSizes( QValueList<int> ); + KDGanttSplitterHandle* firstHandle(){ return mFirstHandle;} + void expandPos( int id, int* min, int* max ); +protected: + void childEvent( QChildEvent * ); + + bool event( QEvent * ); + void resizeEvent( QResizeEvent * ); + + int idAfter( QWidget* ) const; + + void moveSplitter( QCOORD pos, int id ); + virtual void drawSplitter( QPainter*, QCOORD x, QCOORD y, + QCOORD w, QCOORD h ); + void styleChange( QStyle& ); + int adjustPos( int , int ); + virtual void setRubberband( int ); + void getRange( int id, int*, int* ); + +private: + void init(); + void recalc( bool update = FALSE ); + void doResize(); + void storeSizes(); + void processChildEvents(); + QSplitterLayoutStruct *addWidget( QWidget*, bool first = FALSE ); + void recalcId(); + void moveBefore( int pos, int id, bool upLeft ); + void moveAfter( int pos, int id, bool upLeft ); + void setG( QWidget *w, int p, int s, bool isSplitter = FALSE ); + + QCOORD pick( const QPoint &p ) const + { return orient == Horizontal ? p.x() : p.y(); } + QCOORD pick( const QSize &s ) const + { return orient == Horizontal ? s.width() : s.height(); } + + QCOORD trans( const QPoint &p ) const + { return orient == Vertical ? p.x() : p.y(); } + QCOORD trans( const QSize &s ) const + { return orient == Vertical ? s.width() : s.height(); } + KDGanttSplitterHandle* mFirstHandle; + QSplitterData *data; +#endif + +private: + Orientation orient; + Direction _direction; +#ifndef DOXYGEN_SKIP_INTERNAL + friend class KDGanttSplitterHandle; +#endif +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + KDGanttMinimizeSplitter( const KDGanttMinimizeSplitter & ); + KDGanttMinimizeSplitter& operator=( const KDGanttMinimizeSplitter & ); +#endif +}; + +#ifndef DOXYGEN_SKIP_INTERNAL +// This class was continued from a verbatim copy of the +// QSplitterHandle pertaining to the Qt Enterprise License and the +// GPL. It has only been renamed to KDGanttSplitterHandler in order to +// avoid a symbol clash on some platforms. +class KDGanttSplitterHandle : public QWidget +{ + Q_OBJECT +#if QT_VERSION >= 232 +public: + KDGanttSplitterHandle( Qt::Orientation o, + KDGanttMinimizeSplitter *parent, const char* name=0 ); + void setOrientation( Qt::Orientation o ); + Qt::Orientation orientation() const { return orient; } + + bool opaque() const { return s->opaqueResize(); } + + QSize sizeHint() const; + void toggle(); + + int id() const { return myId; } // data->list.at(id())->wid == this + void setId( int i ) { myId = i; } + +protected: + QValueList<QPointArray> buttonRegions(); + void paintEvent( QPaintEvent * ); + void mouseMoveEvent( QMouseEvent * ); + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + int onButton( const QPoint& p ); + void updateCursor( const QPoint& p ); + +private: + QSize mSizeHint; + bool mUseOffset; + Qt::Orientation orient; + bool opaq; + int myId; + + KDGanttMinimizeSplitter *s; + int _activeButton; + bool _collapsed; + int _origPos; +#endif +}; +#endif + +#endif // QT_NO_SPLITTER + +#endif // KDGANTTMINIMIZESPLITTER_H diff --git a/microkde/kapplication.cpp b/microkde/kapplication.cpp new file mode 100644 index 0000000..a1d00a8 --- a/dev/null +++ b/microkde/kapplication.cpp @@ -0,0 +1,26 @@ +#include <stdlib.h> + +#include "kapplication.h" + +int KApplication::random() +{ + return rand(); +} + +//US +QString KApplication::randomString(int length) +{ + if (length <=0 ) return QString::null; + + QString str; + while (length--) + { + int r=random() % 62; + r+=48; + if (r>57) r+=7; + if (r>90) r+=6; + str += char(r); + // so what if I work backwards? + } + return str; +} diff --git a/microkde/kapplication.h b/microkde/kapplication.h new file mode 100644 index 0000000..47e64e7 --- a/dev/null +++ b/microkde/kapplication.h @@ -0,0 +1,21 @@ +#ifndef MINIKDE_KAPPLICATION_H +#define MINIKDE_KAPPLICATION_H + +#include "qstring.h" + +class KApplication +{ + public: + static int random(); + +//US + /** + * Generates a random string. It operates in the range [A-Za-z0-9] + * @param length Generate a string of this length. + * @return the random string + */ + static QString randomString(int length); +}; + + +#endif diff --git a/microkde/kaudioplayer.h b/microkde/kaudioplayer.h new file mode 100644 index 0000000..ff196cf --- a/dev/null +++ b/microkde/kaudioplayer.h @@ -0,0 +1,10 @@ +#ifndef MICROKDE_KAUDIOPLAYER_H +#define MICROKDE_KAUDIOPLAYER_H + +class KAudioPlayer +{ + public: + static void play( const QString & ) {} +}; + +#endif diff --git a/microkde/kcalendarsystem.cpp b/microkde/kcalendarsystem.cpp new file mode 100644 index 0000000..530010d --- a/dev/null +++ b/microkde/kcalendarsystem.cpp @@ -0,0 +1,52 @@ +/* + Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> + Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// Gregorian calendar system implementation factory for creation of kde calendar +// systems. +// Also default gregorian and factory classes + +#include <kglobal.h> + +#include "kcalendarsystem.h" + +class KCalendarSystemPrivate +{ +public: + const KLocale * locale; +}; + +KCalendarSystem::KCalendarSystem(const KLocale * locale) + : d(new KCalendarSystemPrivate) +{ + d->locale = locale; +} + +KCalendarSystem::~KCalendarSystem() +{ + delete d; +} + +const KLocale * KCalendarSystem::locale() const +{ + if ( d->locale ) + return d->locale; + + return KGlobal::locale(); +} diff --git a/microkde/kcalendarsystem.h b/microkde/kcalendarsystem.h new file mode 100644 index 0000000..37af33e --- a/dev/null +++ b/microkde/kcalendarsystem.h @@ -0,0 +1,297 @@ +/* + Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> + Copyright (c) 2002-2003 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KCALENDARSYSTEM_H +#define KCALENDARSYSTEM_H + +#include <qdatetime.h> +#include <qstring.h> + +class KLocale; + +class KCalendarSystemPrivate; + +/** + * CalendarSystem abstract class, default derived kde gregorian class and + * factory class. Provides support for different calendar types for kde + * calendar widget and related stuff. + * + * Derived classes must be created through KCalendarFactory class + * + * @author Carlos Moro <cfmoro@correo.uniovi.es> + * @licence GNU-GPL v.2 + * @version $Id$ + * @since 3.2 + */ +class KCalendarSystem +{ +public: + /** + * Constructor of abstract calendar class. This will be called by the derived classes. + * + * @param locale It will use this locale for translations, 0 means global. + */ + KCalendarSystem(const KLocale * locale = 0); + + /** + * Descructor. + */ + virtual ~KCalendarSystem(); + + /** + * Gets specific calendar type year for a given gregorian date + * + * @param date gregorian date + * @return year + */ + virtual int year (const QDate & date) const = 0; + + /** + * Gets specific calendar type month for a given gregorian date + * + * @param date gregorian date + * @return month number + */ + virtual int month (const QDate & date) const = 0; + + /** + * Gets specific calendar type day number of month for a given date + * + * @param date gregorian date equivalent to the specific one + * @return day of the month + */ + virtual int day (const QDate & date) const = 0; + + /** + * Gets specific calendar type number of day of week number for a given + * date + * + * @param date gregorian date + * @return day of week + */ + virtual int dayOfWeek (const QDate & date) const = 0; + + /** + * Gets specific calendar type day number of year for a given date + * + * @param date gregorian date equivalent to the specific one + * @return day number + */ + virtual int dayOfYear (const QDate & date) const = 0; + + /** + * Changes the date's year, month and day. The range of the year, month + * and day depends on which calendar is being used. + * + * @param date Date to change + * @param y Year + * @param m Month number + * @param d Day of month + * @return TRUE if the date is valid; otherwise returns FALSE. + */ + virtual bool setYMD(QDate & date, int y, int m, int d) const = 0; + + /** + * Returns a QDate object containing a date nyears later. + * + * @param date The old date + * @param nyears The number of years to add + * @return The new date + */ + virtual QDate addYears(const QDate & date, int nyears) const = 0; + + /** + * Returns a QDate object containing a date nmonths later. + * + * @param date The old date + * @param nmonths The number of months to add + * @return The new date + */ + virtual QDate addMonths(const QDate & date, int nmonths) const = 0; + + /** + * Returns a QDate object containing a date ndays later. + * + * @param date The old date + * @param ndays The number of days to add + * @return The new date + */ + virtual QDate addDays(const QDate & date, int ndays) const = 0; + + /** + * Gets specific calendar type number of month for a given year + * + * @param date The date whose year to use + * @return The number of months in that year + */ + virtual int monthsInYear (const QDate & date) const = 0; + + /** + * Gets the number of days in date whose years specified. + * + * @param date Gregorian date equivalent to the specific one + * @return The number of days in year + */ + virtual int daysInYear (const QDate & date) const = 0; + + /** + * Gets specific calendar type number of days in month for a given date + * + * @param date gregorian date + * @return number of days for month in date + */ + virtual int daysInMonth (const QDate & date) const = 0; + + /** + * Gets the number of weeks in year + * + * @param year the year + * @return number of weeks in year + */ + virtual int weeksInYear(int year) const = 0; + + /** + * Gets specific calendar type week number for a given date + * + * @param date gregorian date + * @return week number + */ + virtual int weekNumber(const QDate& date, int * yearNum = 0) const = 0; + + /** + * Gets specific calendar type month name for a given month number + * If an invalid month is specified, QString::null is returned. + * + * @param month The month number + * @param shortName Specifies if the short month name should be used + * @return The name of the month + */ + virtual QString monthName (int month, bool shortName = false) const = 0; + + /** + * Gets specific calendar type month name for a given gregorian date + * + * @param date Gregorian date + * @param shortName Specifies if the short month name should be used + * @return The name of the month + */ + virtual QString monthName (const QDate & date, bool shortName = false ) const = 0; + + /** + * Returns a string containing the possessive form of the month name. + * ("of January", "of February", etc.) + * It's needed in long format dates in some languages. + * If an invalid month is specified, QString::null is returned. + * + * @param month The month number + * @param shortName Specifies if the short month name should be used + * + * @return The possessive form of the name of the month + */ + virtual QString monthNamePossessive(int month, bool shortName = false) const = 0; + + /** + * Returns a string containing the possessive form of the month name. + * ("of January", "of February", etc.) + * It's needed in long format dates in some languages. + * + * @param date Gregorian date + * @param shortName Specifies if the short month name should be used + * + * @return The possessive form of the name of the month + */ + virtual QString monthNamePossessive(const QDate & date, bool shortName = false) const = 0; + + /** + * Gets specific calendar type week day name + * If an invalid week day is specified, QString::null is returned. + * + * @param weekDay number of day in week (1 -> Monday) + * @param shortName short or complete day name + * @return day name + */ + virtual QString weekDayName (int weekDay, bool shortName = false) const = 0; + + /** + * Gets specific calendar type week day name + * + * @param date the date + * @param shortName short or complete day name + * @return day name + */ + virtual QString weekDayName (const QDate & date, bool shortName = false) const = 0; + + /** + * Gets the first year value supported by specific calendar type + * algorithms. + * + * @return first year supported + */ + virtual int minValidYear () const = 0; + + /** + * Gets the maximum year value supported by specific calendar type + * algorithms (QDate, 8000) + * + * @return maximum year supported + */ + virtual int maxValidYear () const = 0; + + /** + * Gets the day of the week traditionaly associated with pray + * + * @return day number + */ + virtual int weekDayOfPray () const = 0; + + /** + * Gets the string representing the calendar + */ + virtual QString calendarName() const = 0; + + /** + * Gets if the calendar is lunar based + * + * @return if the calendar is lunar based + */ + virtual bool isLunar() const = 0; + + /** + * Gets if the calendar is lunisolar based + * + * @return if the calendar is lunisolar based + */ + virtual bool isLunisolar() const = 0; + + /** + * Gets if the calendar is solar based + * + * @return if the calendar is solar based + */ + virtual bool isSolar() const = 0; + +protected: + const KLocale * locale() const; + +private: + KCalendarSystemPrivate * d; +}; + +#endif diff --git a/microkde/kcalendarsystemgregorian.cpp b/microkde/kcalendarsystemgregorian.cpp new file mode 100644 index 0000000..7c5b62a --- a/dev/null +++ b/microkde/kcalendarsystemgregorian.cpp @@ -0,0 +1,359 @@ +/* + Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> + Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// Derived gregorian kde calendar class +// Just a schema. + +#include <qdatetime.h> +#include <qstring.h> + +#include <klocale.h> +#include <kdebug.h> + +#include "kcalendarsystemgregorian.h" + +KCalendarSystemGregorian::KCalendarSystemGregorian(const KLocale * locale) + : KCalendarSystem(locale) +{ + kdDebug(5400) << "Created gregorian calendar" << endl; +} + +KCalendarSystemGregorian::~KCalendarSystemGregorian() +{ +} + +int KCalendarSystemGregorian::year(const QDate& date) const +{ +// kdDebug(5400) << "Gregorian year..." << endl; + return date.year(); +} + +int KCalendarSystemGregorian::monthsInYear( const QDate & ) const +{ +// kdDebug(5400) << "Gregorian monthsInYear" << endl; + + return 12; +} + +int KCalendarSystemGregorian::weeksInYear(int year) const +{ +#if QT_VERSION >= 300 + QDate temp; + temp.setYMD(year, 12, 31); + + // If the last day of the year is in the first week, we have to check the + // week before + if ( temp.weekNumber() == 1 ) + temp.addDays(-7); + + return temp.weekNumber(); +#else + return 52; +#endif +} + +int KCalendarSystemGregorian::weekNumber(const QDate& date, + int * yearNum) const +{ +#if QT_VERSION >= 300 + return date.weekNumber(yearNum); +#else + return 1; +#endif +} + +QString KCalendarSystemGregorian::monthName(const QDate& date, + bool shortName) const +{ + return monthName(month(date), shortName); +} + +QString KCalendarSystemGregorian::monthNamePossessive(const QDate& date, bool shortName) const +{ + return monthNamePossessive(month(date), shortName); +} + +QString KCalendarSystemGregorian::monthName(int month, bool shortName) const +{ +// kdDebug(5400) << "Gregorian getMonthName" << endl; + + if ( shortName ) + switch ( month ) + { + case 1: + return locale()->translate("January", "Jan"); + case 2: + return locale()->translate("February", "Feb"); + case 3: + return locale()->translate("March", "Mar"); + case 4: + return locale()->translate("April", "Apr"); + case 5: + return locale()->translate("May short", "May"); + case 6: + return locale()->translate("June", "Jun"); + case 7: + return locale()->translate("July", "Jul"); + case 8: + return locale()->translate("August", "Aug"); + case 9: + return locale()->translate("September", "Sep"); + case 10: + return locale()->translate("October", "Oct"); + case 11: + return locale()->translate("November", "Nov"); + case 12: + return locale()->translate("December", "Dec"); + } + else + switch ( month ) + { + case 1: + return locale()->translate("January"); + case 2: + return locale()->translate("February"); + case 3: + return locale()->translate("March"); + case 4: + return locale()->translate("April"); + case 5: + return locale()->translate("May long", "May"); + case 6: + return locale()->translate("June"); + case 7: + return locale()->translate("July"); + case 8: + return locale()->translate("August"); + case 9: + return locale()->translate("September"); + case 10: + return locale()->translate("October"); + case 11: + return locale()->translate("November"); + case 12: + return locale()->translate("December"); + } + + return QString::null; +} + +QString KCalendarSystemGregorian::monthNamePossessive(int month, + bool shortName) const +{ +// kdDebug(5400) << "Gregorian getMonthName" << endl; + + if ( shortName ) + switch ( month ) + { + case 1: + return locale()->translate("of January", "of Jan"); + case 2: + return locale()->translate("of February", "of Feb"); + case 3: + return locale()->translate("of March", "of Mar"); + case 4: + return locale()->translate("of April", "of Apr"); + case 5: + return locale()->translate("of May short", "of May"); + case 6: + return locale()->translate("of June", "of Jun"); + case 7: + return locale()->translate("of July", "of Jul"); + case 8: + return locale()->translate("of August", "of Aug"); + case 9: + return locale()->translate("of September", "of Sep"); + case 10: + return locale()->translate("of October", "of Oct"); + case 11: + return locale()->translate("of November", "of Nov"); + case 12: + return locale()->translate("of December", "of Dec"); + } + else + switch ( month ) + { + case 1: + return locale()->translate("of January"); + case 2: + return locale()->translate("of February"); + case 3: + return locale()->translate("of March"); + case 4: + return locale()->translate("of April"); + case 5: + return locale()->translate("of May long", "of May"); + case 6: + return locale()->translate("of June"); + case 7: + return locale()->translate("of July"); + case 8: + return locale()->translate("of August"); + case 9: + return locale()->translate("of September"); + case 10: + return locale()->translate("of October"); + case 11: + return locale()->translate("of November"); + case 12: + return locale()->translate("of December"); + } + + return QString::null; +} + +bool KCalendarSystemGregorian::setYMD(QDate & date, int y, int m, int d) const +{ + // We don't want Qt to add 1900 to them + if ( y >= 0 && y <= 99 ) + return false; + + // QDate supports gregorian internally + return date.setYMD(y, m, d); +} + +QDate KCalendarSystemGregorian::addYears(const QDate & date, int nyears) const +{ +#if QT_VERSION >= 300 + return date.addYears(nyears); +#else + int year = date.year() + nyears; + int month = date.month(); + int day = date.day(); + QDate newDate( year, month, 1 ); + if ( day > newDate.daysInMonth() ) day = newDate.daysInMonth(); + return QDate( year, month, day ); +#endif +} + +QDate KCalendarSystemGregorian::addMonths(const QDate & date, int nmonths) const +{ +#if QT_VERSION >= 300 + return date.addMonths(nmonths); +#else + int month = date.month(); + int nyears; + if ( nmonths >= 0 ) { + month += nmonths; + nyears = ( month - 1 ) / 12; + month = ( ( month - 1 ) % 12 ) + 1; + } else { + nyears = nmonths / 12; + // nmonths += nyears * 12; + nmonths = nmonths % 12; + month += nmonths; + if ( month <= 0 ) { + month += 12; + --nyears; + } + } + int year = date.year() + nyears; + int day = date.day(); + QDate newDate( year, month, 1 ); + if ( day > newDate.daysInMonth() ) day = newDate.daysInMonth(); + return QDate( year, month, day ); +#endif +} + +QDate KCalendarSystemGregorian::addDays(const QDate & date, int ndays) const +{ + return date.addDays(ndays); +} + +QString KCalendarSystemGregorian::weekDayName(int col, bool shortName) const +{ + // ### Should this really be different to each calendar system? Or are we + // only going to support weeks with 7 days? + + //kdDebug(5400) << "Gregorian wDayName" << endl; + return locale()->weekDayName(col, shortName); +} + +QString KCalendarSystemGregorian::weekDayName(const QDate& date, bool shortName) const +{ + return weekDayName(dayOfWeek(date), shortName); +} + + +int KCalendarSystemGregorian::dayOfWeek(const QDate& date) const +{ + return date.dayOfWeek(); +} + +int KCalendarSystemGregorian::dayOfYear(const QDate & date) const +{ + return date.dayOfYear(); +} + +int KCalendarSystemGregorian::daysInMonth(const QDate& date) const +{ +// kdDebug(5400) << "Gregorian daysInMonth" << endl; + return date.daysInMonth(); +} + +int KCalendarSystemGregorian::minValidYear() const +{ + return 1753; // QDate limit +} + +int KCalendarSystemGregorian::maxValidYear() const +{ + return 8000; // QDate limit +} + +int KCalendarSystemGregorian::day(const QDate& date) const +{ + return date.day(); +} + +int KCalendarSystemGregorian::month(const QDate& date) const +{ + return date.month(); +} + +int KCalendarSystemGregorian::daysInYear(const QDate& date) const +{ + return date.daysInYear(); +} + +int KCalendarSystemGregorian::weekDayOfPray() const +{ + return 7; // sunday +} + +QString KCalendarSystemGregorian::calendarName() const +{ + return QString::fromLatin1("gregorian"); +} + +bool KCalendarSystemGregorian::isLunar() const +{ + return false; +} + +bool KCalendarSystemGregorian::isLunisolar() const +{ + return false; +} + +bool KCalendarSystemGregorian::isSolar() const +{ + return true; +} diff --git a/microkde/kcalendarsystemgregorian.h b/microkde/kcalendarsystemgregorian.h new file mode 100644 index 0000000..2eff625 --- a/dev/null +++ b/microkde/kcalendarsystemgregorian.h @@ -0,0 +1,90 @@ +/* + Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> + Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KCALENDARSYSTEMGREGORIAN_H +#define KCALENDARSYSTEMGREGORIAN_H + +#include <qdatetime.h> +#include <qstring.h> + +#include "kcalendarsystem.h" + +class KCalendarSystemGregorianPrivate; + +/** + * This is the Gregorian calendar implementation. + * + * The Gregorian calender is the most used calendar today. The first year in + * the calendar is set to the birth of Christ. + * + * @see KLocale,KCalendarSystem,KCalendarSystemFactory + * + * @author Carlos Moro <cfmoro@correo.uniovi.es> + * @licence GNU-GPL v.2 + * @version $Id$ + * @since 3.2 + */ +class KCalendarSystemGregorian: public KCalendarSystem +{ +public: + KCalendarSystemGregorian (const KLocale * locale = 0); + virtual ~KCalendarSystemGregorian (); + + virtual int year (const QDate & date) const; + virtual int month (const QDate & date) const; + virtual int day (const QDate & date) const; + virtual int dayOfWeek (const QDate & date) const; + virtual int dayOfYear (const QDate & date) const; + + virtual bool setYMD(QDate & date, int y, int m, int d) const; + + virtual QDate addYears(const QDate & date, int nyears) const; + virtual QDate addMonths(const QDate & date, int nmonths) const; + virtual QDate addDays(const QDate & date, int ndays) const; + + virtual int monthsInYear (const QDate & date) const; + + virtual int daysInYear (const QDate & date) const; + virtual int daysInMonth (const QDate & date) const; + virtual int weeksInYear(int year) const; + virtual int weekNumber(const QDate& date, int * yearNum = 0) const; + + virtual QString monthName (int month, bool shortName = false) const; + virtual QString monthName (const QDate & date, bool shortName = false ) const; + virtual QString monthNamePossessive(int month, bool shortName = false) const; + virtual QString monthNamePossessive(const QDate & date, bool shortName = false ) const; + virtual QString weekDayName (int weekDay, bool shortName = false) const; + virtual QString weekDayName (const QDate & date, bool shortName = false) const; + + virtual int minValidYear () const; + virtual int maxValidYear () const; + virtual int weekDayOfPray () const; + + virtual QString calendarName() const; + + virtual bool isLunar() const; + virtual bool isLunisolar() const; + virtual bool isSolar() const; + +private: + KCalendarSystemGregorianPrivate * d; +}; + +#endif diff --git a/microkde/kcolorbutton.cpp b/microkde/kcolorbutton.cpp new file mode 100644 index 0000000..433f909 --- a/dev/null +++ b/microkde/kcolorbutton.cpp @@ -0,0 +1,36 @@ +#include "kcolorbutton.h" +#include "kcolordialog.h" +#include "qapplication.h" + + +#include "qlayout.h" + +void KColorButton:: edit() +{ + + KColorDialog* k = new KColorDialog( this ); + k->setColor( mColor ); + int res = k->exec(); + if ( res ) { + mColor = k->getColor(); + setColor ( mColor ); + emit changed ( mColor ); + } + delete k; +} +KColorButton::KColorButton( QWidget *p ):QPushButton( p ) +{ + int size = 24; + if( QApplication::desktop()->width() < 480 ) + size = 18; + setFixedSize( size,size ); + connect ( this, SIGNAL( clicked() ), this ,SLOT (edit() )); + +} +void KColorButton::setColor ( const QColor & c) +{ + mColor = c; + QPixmap pix ( height() - 4, width() - 4 ); + pix.fill( c ); + setPixmap ( pix ); +} diff --git a/microkde/kcolorbutton.h b/microkde/kcolorbutton.h new file mode 100644 index 0000000..88b3774 --- a/dev/null +++ b/microkde/kcolorbutton.h @@ -0,0 +1,26 @@ +#ifndef MICROKDE_KCOLORBUTTON_H +#define MICROKDE_KCOLORBUTTON_H + +#include <qpushbutton.h> +#include <qcolor.h> +#include <kglobal.h> +#include <qpixmap.h> +#include <qlabel.h> + + +class KColorButton : public QPushButton +{ +Q_OBJECT +public: + KColorButton( QWidget *p ); + void setColor ( const QColor &); + QColor color() const { return mColor ; } + signals: + void changed(const QColor &); +private slots: + void edit(); + private: + QColor mColor; +}; + +#endif diff --git a/microkde/kcolordialog.cpp b/microkde/kcolordialog.cpp new file mode 100644 index 0000000..9a76e5e --- a/dev/null +++ b/microkde/kcolordialog.cpp @@ -0,0 +1,92 @@ +#include "kcolordialog.h" +#include <qdialog.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qslider.h> +#include <qhbox.h> +#include <qapplication.h> +#include <qpushbutton.h> + +#include <kglobal.h> +QColor KColorDialog::getColor( ) const +{ + QColor c ( r->value(), g->value(), b->value() ); + lar->setText ( "R: " + QString::number ( c.red() ) ); + lag->setText ( "G: " + QString::number ( c.green() ) ); + lab->setText ( "B: " + QString::number ( c.blue() ) ); + return c; +} +void KColorDialog::setColor( const QColor & d ) +{ + r->setValue(d.red() ); + g->setValue(d.green() ); + b->setValue(d.blue() ); + old_color->setPalette( QPalette( d.dark(), d ) ); + lar->setText ( "R: " + QString::number ( d.red() ) ); + lag->setText ( "G: " + QString::number ( d.green() ) ); + lab->setText ( "B: " + QString::number ( d.blue() ) ); + +} +KColorDialog::KColorDialog( QWidget *p ):QDialog( p, "input-dialog", true ) +{ + setCaption( i18n("Choose Color") ); + + setMaximumSize( QApplication::desktop()->width() - 20, QApplication::desktop()->height() - 40 ); // for zaurus 5500er. + QGridLayout* lay = new QGridLayout ( this, 4, 2 ); + lay->setSpacing( 6 ); + lay->setMargin( 11 ); + + old_color = new QLabel("Old color",this); + old_color->setFrameStyle( QFrame::Panel | QFrame::Plain ); + old_color->setLineWidth( 1 ); + lay->addWidget(old_color, 0, 0); + + new_color = new QLabel("New color", this); + new_color->setFrameStyle( QFrame::Panel | QFrame::Plain ); + new_color->setLineWidth( 1 ); + lay->addWidget(new_color, 0, 1); + new_color->setAlignment( AlignCenter ); + + QHBox* hb = new QHBox ( this ); + lar = new QLabel( hb ); + lag = new QLabel( hb ); + lab = new QLabel( hb ); + lay->addMultiCellWidget( hb,1,1, 0,1 ); + + QLabel* lr = new QLabel ( "Red:", this ); + lay->addWidget( lr,2,0 ); + r = new QSlider ( 0, 255, 1, 1, Horizontal, this ); + lay->addWidget(r ,2,1 ); + + QLabel* lg = new QLabel( "Green:",this ); + lay->addWidget(lg ,3,0 ); + g = new QSlider ( 0, 255, 1, 1, Horizontal, this ); + lay->addWidget( g ,3,1 ); + + QLabel* lb = new QLabel ( "Blue:",this ); + lay->addWidget( lb,4,0 ); + b = new QSlider ( 0, 255, 1, 1, Horizontal, this ); + lay->addWidget(b ,4,1 ); + + QColor d = backgroundColor(); + r->setValue(d.red() ); + g->setValue(d.green() ); + b->setValue(d.blue() ); + old_color->setPalette( QPalette( d.dark() , d ) ); + // kannst du wieder reinnehmen, aber es geht auch so. + QPushButton * ok = new QPushButton (i18n(" OK "), this ); + QPushButton * cancel = new QPushButton (i18n(" Cancel "), this ); + + lay->addWidget(ok ,5,0 ); + lay->addWidget(cancel ,5,1 ); + connect (ok, SIGNAL( clicked() ), this ,SLOT (accept() )); + connect (cancel, SIGNAL( clicked() ), this ,SLOT (reject() )); + connect (r, SIGNAL( valueChanged ( int ) ), this ,SLOT (updateColor( int ) )); + connect (g, SIGNAL( valueChanged ( int ) ), this ,SLOT (updateColor( int ) )); + connect (b, SIGNAL( valueChanged ( int ) ), this ,SLOT (updateColor( int ) )); +} +void KColorDialog::updateColor( int ) +{ + QColor c = getColor( ) ; + new_color->setPalette( QPalette( c.dark(), c ) ); +} diff --git a/microkde/kcolordialog.h b/microkde/kcolordialog.h new file mode 100644 index 0000000..bb2045d --- a/dev/null +++ b/microkde/kcolordialog.h @@ -0,0 +1,25 @@ +#ifndef MINIKDE_KCOLORDIALOG_H +#define MINIKDE_KCOLORDIALOG_H + +#include <qcolor.h> + +#include <qdialog.h> +#include <qslider.h> +#include <qlabel.h> +class KColorDialog : public QDialog +{ +Q_OBJECT + public: + KColorDialog( QWidget *p ); + QColor getColor( ) const; + void setColor( const QColor &); + private: + QSlider *r, *g, *b; + QLabel * old_color, *new_color; + QLabel *lar, *lag, *lab; +private slots: + void updateColor( int ); +}; + + +#endif diff --git a/microkde/kcombobox.h b/microkde/kcombobox.h new file mode 100644 index 0000000..1a21344 --- a/dev/null +++ b/microkde/kcombobox.h @@ -0,0 +1,12 @@ +#ifndef MICROKDE_KCOMBOBOX_H +#define MICROKDE_KCOMBOBOX_H + +#include <qcombobox.h> + +class KComboBox : public QComboBox +{ + public: + KComboBox( QWidget *parent ) : QComboBox( parent ) {} +}; + +#endif diff --git a/microkde/kconfig.cpp b/microkde/kconfig.cpp new file mode 100644 index 0000000..3f23ed2 --- a/dev/null +++ b/microkde/kconfig.cpp @@ -0,0 +1,467 @@ +#include <qfile.h> +#include <qtextstream.h> +#include <qwidget.h> + +#include "kdebug.h" + +#include "kurl.h" +#include "kstandarddirs.h" +#include "kconfig.h" + +QString KConfig::mGroup = ""; +//QString KConfig::mGroup = "General"; + +KConfig::KConfig( const QString &fileName ) + : mFileName( fileName ), mDirty( false ) +{ + kdDebug() << "KConfig::KConfig(): '" << fileName << "'" << endl; + + load(); + +} + + +KConfig::~KConfig() +{ + sync(); +} + +void KConfig::setGroup( const QString &group ) +{ + kdDebug() << "KConfig::setGroup(): '" << group << "'" << endl; + + mGroup = group; + + if ( mGroup.right( 1 ) != "/" ) mGroup += "/"; +} + +//US +QString KConfig::group() const { + return mGroup; +} + +//US added method +QValueList<int> KConfig::readIntListEntry( const QString & key) +{ +// qDebug("KConfig::readIntListEntry key=%s:", key.latin1()); + + QValueList<int> result; + + QMap<QString,QString>::ConstIterator mit = mStringMap.find( mGroup + key ); + + if ( mit == mStringMap.end() ) { + return result; + } + + QStringList valuesAsStrings = QStringList::split(":", *mit ); + bool ok = false; + bool ok2 = true; + int val; + + for ( QStringList::Iterator sit = valuesAsStrings.begin(); sit != valuesAsStrings.end(); ++sit ) { + val = (*sit).toInt(&ok); + result << val; + if (ok == false) { + qDebug("KConfig::readIntListEntry str=%s , int=%n:", (*sit).latin1(), &val); + ok2 = false; + } + } + + if (ok2 == false) + { + kdDebug() << "KConfig::readIntListEntry: error while reading one of the intvalues." << endl; + qDebug("KConfig::readIntListEntry: error while reading one of the intvalues."); + } + + return result; +} + +int KConfig::readNumEntry( const QString & key, int def ) +{ + QString res = readEntry(key, QString::number(def ) ); + bool ok = false; + int result = res.toInt(&ok); + if ( ok ) + return result; + return def; +} + +QString KConfig::readEntry( const QString &key, const QString &def ) +{ + QMap<QString,QString>::ConstIterator it = mStringMap.find( mGroup + key ); + + if ( it == mStringMap.end() ) { + return def; + } + + return *it; +} + +QStringList KConfig::readListEntry( const QString &key ) +{ + QMap<QString,QString>::ConstIterator it = mStringMap.find( mGroup + key ); + + if ( it == mStringMap.end() ) { + return QStringList(); + } + return QStringList::split(":", *it ); + +} + +bool KConfig::readBoolEntry( const QString &key, bool def ) +{ + QMap<QString,bool>::ConstIterator it = mBoolMap.find( mGroup + key ); + + if ( it == mBoolMap.end() ) { + return def; + } + + return *it; +} + +QColor KConfig::readColorEntry( const QString & e, QColor *def ) +{ + + QStringList l; + l = readListEntry( e ); + if (l.count() != 3 ) { + if ( def ) + return *def; + else + return QColor(); + } + QColor c ( l[0].toInt(), l[1].toInt(), l[2].toInt() ); + return c; +} + +QFont KConfig::readFontEntry( const QString & e, QFont *def ) +{ + QStringList font = readListEntry( e ); + if ( font.isEmpty() ) + return *def; + QFont f; + f.setFamily( font[0]); + f.setBold ( font[1] == "bold"); + f.setPointSize ( font[2].toInt()); + f.setItalic( font[1] == "italic" ); + return f; +} + +QDateTime KConfig::readDateTimeEntry( const QString &key, const QDateTime *def ) +{ + QMap<QString,QDateTime>::ConstIterator it = mDateTimeMap.find( mGroup + key ); + + if ( it == mDateTimeMap.end() ) { + if ( def ) return *def; + else return QDateTime(); + } + + return *it; +} + +//US added method +void KConfig::writeEntry( const QString &key, const QValueList<int> &value) +{ + QStringList valuesAsStrings; + + QValueList<int>::ConstIterator it; + + for( it = value.begin(); it != value.end(); ++it ) + { + valuesAsStrings << QString::number(*it); + } + + mStringMap.insert( mGroup + key, valuesAsStrings.join(":") ); + mDirty = true; +} + +void KConfig::writeEntry( const QString & key , int num ) +{ + writeEntry( key, QString::number ( num ) ); +} + +void KConfig::writeEntry( const QString &key, const QString &value ) +{ + mStringMap.insert( mGroup + key, value ); + + mDirty = true; +} + +void KConfig::writeEntry( const QString &key, const QStringList &value ) +{ + mStringMap.insert( mGroup + key, value.join(":") ); + + mDirty = true; +} + +void KConfig::writeEntry( const QString &key, bool value) +{ + mBoolMap.insert( mGroup + key, value ); + + mDirty = true; +} + +void KConfig::writeEntry( const QString & e, const QColor & c ) +{ + QStringList l; + l.append( QString::number ( c.red() ) ); + l.append( QString::number ( c.green() ) ); + l.append( QString::number ( c.blue() ) ); + writeEntry( e, l ); +} + +void KConfig::writeEntry( const QString & e , const QFont & f ) +{ + QStringList font; + font.append( f.family()); + font.append( (!f.bold ()?"nonbold":"bold") ); + font.append( QString::number ( f.pointSize () ) ); + font.append( !f.italic ()?"nonitalic":"italic" ); + writeEntry( e, font ); +} + +void KConfig::writeEntry( const QString &key, const QDateTime &dt ) +{ + mDateTimeMap.insert( mGroup + key, dt ); +} + +void KConfig::load() +{ + kdDebug() << "KConfig::load(): " << mFileName << endl; + + QFile f( mFileName ); + if ( !f.open( IO_ReadOnly ) ) { + qDebug("KConfig: could not open file %s ",mFileName.latin1() ); + return; + } + + mBoolMap.clear(); + mStringMap.clear(); + + QTextStream t( &f ); + + QString line = t.readLine(); + + while ( !line.isNull() ) { + QStringList tokens = QStringList::split( ",", line ); + if ( tokens[0] == "bool" ) { + bool value = false; + if ( tokens[2] == "1" ) value = true; + mBoolMap.insert( tokens[1], value ); + } else if ( tokens[0] == "QString" ) { + QString value = tokens[2]; + mStringMap.insert( tokens[1], value ); + } else if ( tokens[0] == "QDateTime" ) { +#if 0 + int year = tokens[2].toInt(); + QDateTime dt( QDate( year, + tokens[3].toInt(), + tokens[4].toInt() ), + QTime( tokens[5].toInt(), tokens[6].toInt(), + tokens[7].toInt() ) ); + mDateTimeMap.insert( tokens[1], dt ); +#endif + } + + line = t.readLine(); + } +} + +void KConfig::sync() +{ + + if ( !mDirty ) return; + //qDebug("KConfig::sync() %s ",mFileName.latin1() ); + //kdDebug() << "KConfig::sync(): " << mFileName << endl; + +//US I took the following code from a newer version of KDE + // Create the containing dir if needed + KURL path; + path.setPath(mFileName); + QString dir=path.directory(); + KStandardDirs::makeDir(dir); + + QFile f( mFileName ); + if ( !f.open( IO_WriteOnly ) ) { + + qDebug("KConfig::sync() Can't open file %s ",mFileName.latin1() ); + + return; + } + + QTextStream t( &f ); + + QMap<QString,bool>::ConstIterator itBool; + for( itBool = mBoolMap.begin(); itBool != mBoolMap.end(); ++itBool ) { + t << "bool," << itBool.key() << "," << ( *itBool ? "1" : "0" ) << endl; + } + + QMap<QString,QString>::ConstIterator itString; + for( itString = mStringMap.begin(); itString != mStringMap.end(); ++itString ) { + t << "QString," << itString.key() << "," << (*itString ) << endl; + } + + QMap<QString,QDateTime>::ConstIterator itDateTime; + for( itDateTime = mDateTimeMap.begin(); itDateTime != mDateTimeMap.end(); ++itDateTime ) { + QDateTime dt = *itDateTime; + t << "QDateTime," << itDateTime.key() << "," + << dt.date().year() << "," + << dt.date().month() << "," + << dt.date().day() << "," + << dt.time().hour() << "," + << dt.time().minute() << "," + << dt.time().second() << endl; + } + + f.close(); + + mDirty = false; +} + + +//US I took the following deleteGroup method from a newer version from KDE. +/** + * Deletes a configuration entry group + * + * If the group is not empty and bDeep is false, nothing gets + * deleted and false is returned. + * If this group is the current group and it is deleted, the + * current group is undefined and should be set with setGroup() + * before the next operation on the configuration object. + * + * @param group The name of the group + * returns true if we deleted at least one entry. + */ +bool KConfig::deleteGroup( const QString& group) +{ + bool dirty = false; + int pos; + + QMap<QString,bool>::Iterator itBool; + for( itBool = mBoolMap.begin(); itBool != mBoolMap.end(); ++itBool ) + { + pos = itBool.key().find( group ); + if (pos == 0) { + mBoolMap.remove(itBool); + dirty = true; + } + } + + QMap<QString,QString>::Iterator itString; + for( itString = mStringMap.begin(); itString != mStringMap.end(); ++itString ) + { + pos = itString.key().find( group ); + if (pos == 0) { + mStringMap.remove(itString); + dirty = true; + } + } + + QMap<QString,QDateTime>::Iterator itDateTime; + for( itDateTime = mDateTimeMap.begin(); itDateTime != mDateTimeMap.end(); ++itDateTime ) + { + pos = itDateTime.key().find( group ); + if (pos == 0) { + mDateTimeMap.remove(itDateTime); + dirty = true; + } + } + + if (dirty) + mDirty = true; + + return dirty; + +} + +//US I took the following hasGroup method from a newer version from KDE. + /** + * Returns true if the specified group is known about. + * + * @param group The group to search for. + * @return Whether the group exists. + */ +bool KConfig::hasGroup(const QString &group) const +{ + QMap<QString,bool>::ConstIterator itBool; + for( itBool = mBoolMap.begin(); itBool != mBoolMap.end(); ++itBool ) + { + if (itBool.key().find( group ) == 0) { + return true; + } + } + + QMap<QString,QString>::ConstIterator itString; + for( itString = mStringMap.begin(); itString != mStringMap.end(); ++itString ) + { + if (itString.key().find( group ) == 0) { + return true; + } + } + + QMap<QString,QDateTime>::ConstIterator itDateTime; + for( itDateTime = mDateTimeMap.begin(); itDateTime != mDateTimeMap.end(); ++itDateTime ) + { + if (itDateTime.key().find( group ) == 0) { + return true; + } + } + + return false; +} + +void KConfig::deleteEntry( const QString &key) +{ + bool dirty = false; + + QMap<QString,bool>::Iterator itBool = mBoolMap.find( mGroup + key ); + if ( itBool != mBoolMap.end() ) { + mBoolMap.remove(itBool); + dirty = true; + } + + + QMap<QString,QString>::Iterator itString = mStringMap.find( mGroup + key ); + if ( itString != mStringMap.end() ) { + mStringMap.remove(itString); + dirty = true; + } + + + QMap<QString,QDateTime>::Iterator itDateTime = mDateTimeMap.find( mGroup + key ); + if ( itDateTime != mDateTimeMap.end() ) { + mDateTimeMap.remove(itDateTime); + dirty = true; + } + + if (dirty) + mDirty = true; + +} + +//US +QString KConfig::getFileName() +{ + return mFileName; +} + +bool KConfig::hasKey( const QString &key) +{ + QMap<QString,bool>::Iterator itBool = mBoolMap.find( mGroup + key ); + if ( itBool != mBoolMap.end() ) { + return true; + } + + QMap<QString,QString>::Iterator itString = mStringMap.find( mGroup + key ); + if ( itString != mStringMap.end() ) { + return true; + } + + QMap<QString,QDateTime>::Iterator itDateTime = mDateTimeMap.find( mGroup + key ); + if ( itDateTime != mDateTimeMap.end() ) { + return true; + } + + return false; +} + diff --git a/microkde/kconfig.h b/microkde/kconfig.h new file mode 100644 index 0000000..bfedf53 --- a/dev/null +++ b/microkde/kconfig.h @@ -0,0 +1,100 @@ +#ifndef MINIKDE_KCONFIG_H +#define MINIKDE_KCONFIG_H + +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> +#include <qcolor.h> +#include <qfont.h> +#include <qmap.h> +#include <qdatetime.h> + +class KConfig +{ + public: + KConfig( const QString & ); + ~KConfig(); + + void setGroup( const QString & ); + +//US + /** + * Returns the name of the group in which we are + * searching for keys and from which we are retrieving entries. + * + * @return The current group. + */ + QString group() const; + +//US I took the following deleteGroup method from a newer version from KDE. +/** + * Deletes a configuration entry group + * + * If the group is not empty and bDeep is false, nothing gets + * deleted and false is returned. + * If this group is the current group and it is deleted, the + * current group is undefined and should be set with setGroup() + * before the next operation on the configuration object. + * + * @param group The name of the group + * returns true if we deleted at least one entry. + */ + bool deleteGroup( const QString& group); + +//US I took the following hasGroup method from a newer version from KDE. + /** + * Returns true if the specified group is known about. + * + * @param group The group to search for. + * @return Whether the group exists. + */ + bool hasGroup(const QString &group) const; + + + QString getFileName(); + +//US added method readIntListEntry + QValueList<int> readIntListEntry( const QString &); + + int readNumEntry( const QString &, int def=0 ); + QString readEntry( const QString &, const QString &def=QString::null ); + QStringList readListEntry( const QString & ); + bool readBoolEntry( const QString &, bool def=false ); + QColor readColorEntry( const QString &, QColor * ); + QFont readFontEntry( const QString &, QFont * ); + QDateTime readDateTimeEntry( const QString &, const QDateTime *pDefault = 0 ); + + bool hasKey( const QString &); + + void writeEntry( const QString &, const QValueList<int>& ); + void writeEntry( const QString &, int ); + void writeEntry( const QString &key , unsigned int value) { writeEntry( key, int( value ) ); } + void writeEntry( const char *key , unsigned int value) { writeEntry( QString( key ), value ); } + void writeEntry( const char *key, int value ) { writeEntry( QString( key ), value ); } + void writeEntry( const QString &, const QString & ); + void writeEntry( const char *key, const QString &value ) { writeEntry( QString( key ), value ); } + void writeEntry( const QString &, const QStringList & ); + void writeEntry( const QString &, bool ); + void writeEntry( const char *key, bool value ) { writeEntry( QString( key ), value ); } + void writeEntry( const QString &, const QColor & ); + void writeEntry( const QString &, const QFont & ); + void writeEntry( const QString &, const QDateTime & ); + + void deleteEntry( const QString &); + + void load(); + void sync(); + + private: + static QString mGroup; + + QString mFileName; + + QMap<QString,bool> mBoolMap; + QMap<QString,QString> mStringMap; + QMap<QString,QDateTime> mDateTimeMap; + + bool mDirty; +}; + +#endif diff --git a/microkde/kconfigtest.cpp b/microkde/kconfigtest.cpp new file mode 100644 index 0000000..373d674 --- a/dev/null +++ b/microkde/kconfigtest.cpp @@ -0,0 +1,14 @@ +#include "kconfig.h" +#include "kdebug.h" + +#include <qdatetime.h> + +int main() +{ + QDateTime dt = QDateTime::currentDateTime(); + kdDebug() << "Before: " << dt.toString() << endl; + KConfig cfg( "huhu" ); + cfg.writeEntry( "123", dt ); + QDateTime newDt = cfg.readDateTimeEntry( "123" ); + kdDebug() << "After: " << newDt.toString() << endl; +} diff --git a/microkde/kdatepickernew.cpp b/microkde/kdatepickernew.cpp new file mode 100644 index 0000000..f60a422 --- a/dev/null +++ b/microkde/kdatepickernew.cpp @@ -0,0 +1,485 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qlayout.h> +#include <qframe.h> +#include <qpainter.h> +#include <qdialog.h> +#include <qstyle.h> +#include <qtoolbutton.h> +#include <qcombobox.h> +#include <qtooltip.h> +#include <qfont.h> +#include <qvalidator.h> +#include <qpopupmenu.h> + +#include "kdatepicker.h" +#include <kglobal.h> +#include <kapplication.h> +#include <klocale.h> +#include <kiconloader.h> +#include <ktoolbar.h> +#include <klineedit.h> +#include <kdebug.h> +#include <knotifyclient.h> +#include <kcalendarsystem.h> + +#include "kdatetbl.h" +#include "kdatepicker.moc" + +class KDatePicker::KDatePickerPrivate +{ +public: + KDatePickerPrivate() : closeButton(0L), selectWeek(0L), todayButton(0), navigationLayout(0) {} + + void fillWeeksCombo(const QDate &date); + + KToolBar *tb; + QToolButton *closeButton; + QComboBox *selectWeek; + QToolButton *todayButton; + QBoxLayout *navigationLayout; +}; + +void KDatePicker::fillWeeksCombo(const QDate &date) +{ + // every year can have a different number of weeks + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + int i, weeks = calendar->weeksInYear(calendar->year(date)); + + if ( d->selectWeek->count() == weeks ) return; // we already have the correct number + + d->selectWeek->clear(); + + for (i = 1; i <= weeks; i++) + d->selectWeek->insertItem(i18n("Week %1").arg(i)); +} + +KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name) + : QFrame(parent,name) +{ + init( dt ); +} + +KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name, WFlags f) + : QFrame(parent,name, f) +{ + init( dt ); +} + +KDatePicker::KDatePicker( QWidget *parent, const char *name ) + : QFrame(parent,name) +{ + init( QDate::currentDate() ); +} + +void KDatePicker::init( const QDate &dt ) +{ + d = new KDatePickerPrivate(); + + d->tb = new KToolBar(this); + + yearBackward = new QToolButton(d->tb); + monthBackward = new QToolButton(d->tb); + selectMonth = new QToolButton(d->tb); + selectYear = new QToolButton(d->tb); + monthForward = new QToolButton(d->tb); + yearForward = new QToolButton(d->tb); + line = new KLineEdit(this); + val = new KDateValidator(this); + table = new KDateTable(this); + fontsize = 12;//KGlobalSettings::generalFont().pointSize(); + + + fontsize++; // Make a little bigger + + d->selectWeek = new QComboBox(false, this); // read only week selection + d->todayButton = new QToolButton(this); + d->todayButton->setIconSet(SmallIconSet("today")); + + QToolTip::add(yearForward, i18n("Next year")); + QToolTip::add(yearBackward, i18n("Previous year")); + QToolTip::add(monthForward, i18n("Next month")); + QToolTip::add(monthBackward, i18n("Previous month")); + QToolTip::add(d->selectWeek, i18n("Select a week")); + QToolTip::add(selectMonth, i18n("Select a month")); + QToolTip::add(selectYear, i18n("Select a year")); + QToolTip::add(d->todayButton, i18n("Select the current day")); + + // ----- + setFontSize(fontsize); + line->setValidator(val); + line->installEventFilter( this ); +// yearForward->setIconSet(BarIconSet(QString::fromLatin1("2rightarrow"))); +// yearBackward->setIconSet(BarIconSet(QString::fromLatin1("2leftarrow"))); +// monthForward->setIconSet(BarIconSet(QString::fromLatin1("1rightarrow"))); +// monthBackward->setIconSet(BarIconSet(QString::fromLatin1("1leftarrow"))); + setDate(dt); // set button texts + connect(table, SIGNAL(dateChanged(QDate)), SLOT(dateChangedSlot(QDate))); + connect(table, SIGNAL(tableClicked()), SLOT(tableClickedSlot())); + connect(monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked())); + connect(monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked())); + connect(yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked())); + connect(yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked())); + connect(d->selectWeek, SIGNAL(activated(int)), SLOT(weekSelected(int))); + connect(d->todayButton, SIGNAL(clicked()), SLOT(todayButtonClicked())); + connect(selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked())); + connect(selectYear, SIGNAL(clicked()), SLOT(selectYearClicked())); + connect(line, SIGNAL(returnPressed()), SLOT(lineEnterPressed())); + table->setFocus(); + + QBoxLayout * topLayout = new QVBoxLayout(this); + + d->navigationLayout = new QHBoxLayout(topLayout); + d->navigationLayout->addWidget(d->tb); + + topLayout->addWidget(table); + + QBoxLayout * bottomLayout = new QHBoxLayout(topLayout); + bottomLayout->addWidget(d->todayButton); + bottomLayout->addWidget(line); + bottomLayout->addWidget(d->selectWeek); +} + +KDatePicker::~KDatePicker() +{ + delete d; +} + +bool +KDatePicker::eventFilter(QObject *o, QEvent *e ) +{ + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent *k = (QKeyEvent *)e; + + if ( (k->key() == Qt::Key_Prior) || + (k->key() == Qt::Key_Next) || + (k->key() == Qt::Key_Up) || + (k->key() == Qt::Key_Down) ) + { + QApplication::sendEvent( table, e ); + table->setFocus(); + return true; // eat event + } + } + return QFrame::eventFilter( o, e ); +} + +void +KDatePicker::resizeEvent(QResizeEvent* e) +{ + QWidget::resizeEvent(e); +} + +void +KDatePicker::dateChangedSlot(QDate date) +{ + kdDebug(298) << "KDatePicker::dateChangedSlot: date changed (" << date.year() << "/" << date.month() << "/" << date.day() << ")." << endl; + + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + + line->setText(KGlobal::locale()->formatDate(date, true)); + selectMonth->setText(calendar->monthName(date, false)); + fillWeeksCombo(date); + d->selectWeek->setCurrentItem(calendar->weekNumber(date) - 1); + selectYear->setText(calendar->yearString(date, false)); + + emit(dateChanged(date)); +} + +void +KDatePicker::tableClickedSlot() +{ + kdDebug(298) << "KDatePicker::tableClickedSlot: table clicked." << endl; + emit(dateSelected(table->getDate())); + emit(tableClicked()); +} + +const QDate& +KDatePicker::getDate() const +{ + return table->getDate(); +} + +const QDate & +KDatePicker::date() const +{ + return table->getDate(); +} + +bool +KDatePicker::setDate(const QDate& date) +{ + if(date.isValid()) + { + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + + table->setDate(date); + fillWeeksCombo(date); + d->selectWeek->setCurrentItem(calendar->weekNumber(date) - 1); + selectMonth->setText(calendar->monthName(date, false)); + selectYear->setText(calendar->yearString(date, true)); + line->setText(KGlobal::locale()->formatDate(date, true)); + return true; + } + else + { + kdDebug(298) << "KDatePicker::setDate: refusing to set invalid date." << endl; + return false; + } +} + +void +KDatePicker::monthForwardClicked() +{ + QDate temp; + temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), 1 ); + + setDate( temp ); +} + +void +KDatePicker::monthBackwardClicked() +{ + QDate temp; + temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), -1 ); + + setDate( temp ); +} + +void +KDatePicker::yearForwardClicked() +{ + QDate temp; + temp = KGlobal::locale()->calendar()->addYears( table->getDate(), 1 ); + + setDate( temp ); +} + +void +KDatePicker::yearBackwardClicked() +{ + QDate temp; + temp = KGlobal::locale()->calendar()->addYears( table->getDate(), -1 ); + + setDate( temp ); +} + +void KDatePicker::selectWeekClicked() {} // ### in 3.2 obsolete; kept for binary compatibility + +void +KDatePicker::weekSelected(int week) +{ + week++; // week number starts with 1 + + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + + QDate date = table->getDate(); + int year = calendar->year(date); + + calendar->setYMD(date, year, 1, 1); + date = calendar->addDays(date, -7); + while (calendar->weekNumber(date) != 1) + date = calendar->addDays(date, 1); + + // date is now first day in week 1 some day in week 1 + date = calendar->addDays(date, (week - calendar->weekNumber(date)) * 7); + + setDate(date); +} + +void +KDatePicker::selectMonthClicked() +{ + // every year can have different month names (in some calendar systems) + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + QDate date = table->getDate(); + int i, month, months = calendar->monthsInYear(date); + + QPopupMenu popup(selectMonth); + + for (i = 1; i <= months; i++) + popup.insertItem(calendar->monthName(i, calendar->year(date)), i); + + popup.setActiveItem(calendar->month(date) - 1); + + if ( (month = popup.exec(selectMonth->mapToGlobal(QPoint(0, 0)), calendar->month(date) - 1)) == -1 ) return; // canceled + + int day = calendar->day(date); + // ----- construct a valid date in this month: + //date.setYMD(date.year(), month, 1); + //date.setYMD(date.year(), month, QMIN(day, date.daysInMonth())); + calendar->setYMD(date, calendar->year(date), month, + QMIN(day, calendar->daysInMonth(date))); + // ----- set this month + setDate(date); +} + +void +KDatePicker::selectYearClicked() +{ + const KCalendarSystem * calendar = KGlobal::locale()->calendar(); + + int year; + KPopupFrame* popup = new KPopupFrame(this); + KDateInternalYearSelector* picker = new KDateInternalYearSelector(popup); + // ----- + picker->resize(picker->sizeHint()); + popup->setMainWidget(picker); + connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int))); + picker->setFocus(); + if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height())))) + { + QDate date; + int day; + // ----- + year=picker->getYear(); + date=table->getDate(); + day=calendar->day(date); + // ----- construct a valid date in this month: + //date.setYMD(year, date.month(), 1); + //date.setYMD(year, date.month(), QMIN(day, date.daysInMonth())); + calendar->setYMD(date, year, calendar->month(date), + QMIN(day, calendar->daysInMonth(date))); + // ----- set this month + setDate(date); + } else { + KNotifyClient::beep(); + } + delete popup; +} + +void +KDatePicker::setEnabled(bool enable) +{ + QWidget *widgets[]= { + yearForward, yearBackward, monthForward, monthBackward, + selectMonth, selectYear, + line, table, d->selectWeek, d->todayButton }; + const int Size=sizeof(widgets)/sizeof(widgets[0]); + int count; + // ----- + for(count=0; count<Size; ++count) + { + widgets[count]->setEnabled(enable); + } +} + +void +KDatePicker::lineEnterPressed() +{ + QDate temp; + // ----- + if(val->date(line->text(), temp)==QValidator::Acceptable) + { + kdDebug(298) << "KDatePicker::lineEnterPressed: valid date entered." << endl; + emit(dateEntered(temp)); + setDate(temp); + } else { + KNotifyClient::beep(); + kdDebug(298) << "KDatePicker::lineEnterPressed: invalid date entered." << endl; + } +} + +void +KDatePicker::todayButtonClicked() +{ + setDate(QDate::currentDate()); +} + +QSize +KDatePicker::sizeHint() const +{ + return QWidget::sizeHint(); +} + +void +KDatePicker::setFontSize(int s) +{ + QWidget *buttons[]= { + // yearBackward, + // monthBackward, + selectMonth, + selectYear, + // monthForward, + // yearForward + }; + const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]); + int count; + QFont font; + QRect r; + // ----- + fontsize=s; + for(count=0; count<NoOfButtons; ++count) + { + font=buttons[count]->font(); + font.setPointSize(s); + buttons[count]->setFont(font); + } + QFontMetrics metrics(selectMonth->fontMetrics()); + + for (int i = 1; ; ++i) + { + QString str = KGlobal::locale()->calendar()->monthName(i, + KGlobal::locale()->calendar()->year(table->getDate()), false); + if (str.isNull()) break; + r=metrics.boundingRect(str); + maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width())); + maxMonthRect.setHeight(QMAX(r.height(), maxMonthRect.height())); + } + + QSize metricBound = style().sizeFromContents(QStyle::CT_ToolButton, + selectMonth, + maxMonthRect); + selectMonth->setMinimumSize(metricBound); + + table->setFontSize(s); +} + +void +KDatePicker::setCloseButton( bool enable ) +{ + if ( enable == (d->closeButton != 0L) ) + return; + + if ( enable ) { + d->closeButton = new QToolButton( d->tb ); + d->navigationLayout->addWidget(d->closeButton); + QToolTip::add(d->closeButton, i18n("Close")); + d->closeButton->setPixmap( SmallIcon("remove") ); + connect( d->closeButton, SIGNAL( clicked() ), + topLevelWidget(), SLOT( close() ) ); + } + else { + delete d->closeButton; + d->closeButton = 0L; + } + + updateGeometry(); +} + +bool KDatePicker::hasCloseButton() const +{ + return (d->closeButton != 0L); +} + +void KDatePicker::virtual_hook( int /*id*/, void* /*data*/ ) +{ /*BASE::virtual_hook( id, data );*/ } + diff --git a/microkde/kdatepickernew.h b/microkde/kdatepickernew.h new file mode 100644 index 0000000..9ea909d --- a/dev/null +++ b/microkde/kdatepickernew.h @@ -0,0 +1,253 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KDATEPICKER_H +#define KDATEPICKER_H +#include <qdatetime.h> +#include <qframe.h> +#include <kdemacros.h> + +class QLineEdit; +class QToolButton; +class KDateValidator; +class KDateTable; + +/** + * Provides a widget for calendar date input. + * + * Different from the + * previous versions, it now emits two types of signals, either + * dateSelected() or dateEntered() (see documentation for both + * signals). + * + * A line edit has been added in the newer versions to allow the user + * to select a date directly by entering numbers like 19990101 + * or 990101. + * + * \image html kdatepicker.png "KDE Date Widget" + * + * @version $Id$ + * @author Tim Gilman, Mirko Boehm + * + * @short A date selection widget. + **/ +class KDatePicker: public QFrame +{ + Q_OBJECT + Q_PROPERTY( QDate date READ date WRITE setDate) + Q_PROPERTY( bool closeButton READ hasCloseButton WRITE setCloseButton ) + Q_PROPERTY( int fontSize READ fontSize WRITE setFontSize ) + +public: + /** The usual constructor. The given date will be displayed + * initially. + **/ + KDatePicker(QWidget *parent=0, + QDate=QDate::currentDate(), + const char *name=0); + + /** The usual constructor. The given date will be displayed + * initially. + * @since 3.1 + **/ + KDatePicker(QWidget *parent, + QDate, + const char *name, + WFlags f); // ### KDE 4.0: Merge + + /** + * Standard qt widget constructor. The initial date will be the + * current date. + * @since 3.1 + */ + KDatePicker( QWidget *parent, const char *name ); + + /** + * The destructor. + **/ + virtual ~KDatePicker(); + + /** The size hint for date pickers. The size hint recommends the + * minimum size of the widget so that all elements may be placed + * without clipping. This sometimes looks ugly, so when using the + * size hint, try adding 28 to each of the reported numbers of + * pixels. + **/ + QSize sizeHint() const; + + /** + * Sets the date. + * + * @returns @p false and does not change anything + * if the date given is invalid. + **/ + bool setDate(const QDate&); + + /** + * Returns the selected date. + * @deprecated + **/ + const QDate& getDate() const KDE_DEPRECATED; + + /** + * @returns the selected date. + */ + const QDate &date() const; + + /** + * Enables or disables the widget. + **/ + void setEnabled(bool); + + /** + * @returns the KDateTable widget child of this KDatePicker + * widget. + * @since 3.2 + */ + KDateTable *dateTable() const { return table; }; + + /** + * Sets the font size of the widgets elements. + **/ + void setFontSize(int); + /** + * Returns the font size of the widget elements. + */ + int fontSize() const + { return fontsize; } + + /** + * By calling this method with @p enable = true, KDatePicker will show + * a little close-button in the upper button-row. Clicking the + * close-button will cause the KDatePicker's topLevelWidget()'s close() + * method being called. This is mostly useful for toplevel datepickers + * without a window manager decoration. + * @see hasCloseButton + * @since 3.1 + */ + void setCloseButton( bool enable ); + + /** + * @returns true if a KDatePicker shows a close-button. + * @see setCloseButton + * @since 3.1 + */ + bool hasCloseButton() const; + +protected: + /// to catch move keyEvents when QLineEdit has keyFocus + virtual bool eventFilter(QObject *o, QEvent *e ); + /// the resize event + virtual void resizeEvent(QResizeEvent*); + /// the year forward button + QToolButton *yearForward; + /// the year backward button + QToolButton *yearBackward; + /// the month forward button + QToolButton *monthForward; + /// the month backward button + QToolButton *monthBackward; + /// the button for selecting the month directly + QToolButton *selectMonth; + /// the button for selecting the year directly + QToolButton *selectYear; + /// the line edit to enter the date directly + QLineEdit *line; + /// the validator for the line edit: + KDateValidator *val; + /// the date table + KDateTable *table; + /// the size calculated during resize events + // QSize sizehint; + /// the widest month string in pixels: + QSize maxMonthRect; +protected slots: + void dateChangedSlot(QDate); + void tableClickedSlot(); + void monthForwardClicked(); + void monthBackwardClicked(); + void yearForwardClicked(); + void yearBackwardClicked(); + /** + * @since 3.1 + * @deprecated in 3.2 + */ + void selectWeekClicked() KDE_DEPRECATED; + /** + * @since 3.1 + */ + void selectMonthClicked(); + /** + * @since 3.1 + */ + void selectYearClicked(); + /** + * @since 3.1 + */ + void lineEnterPressed(); + /** + * @since 3.2 + */ + void todayButtonClicked(); + /** + * @since 3.2 + */ + void weekSelected(int); + +signals: + // ### KDE 4.0 Make all QDate parameters const references + + /** This signal is emitted each time the selected date is changed. + * Usually, this does not mean that the date has been entered, + * since the date also changes, for example, when another month is + * selected. + * @see dateSelected + */ + void dateChanged(QDate); + /** This signal is emitted each time a day has been selected by + * clicking on the table (hitting a day in the current month). It + * has the same meaning as dateSelected() in older versions of + * KDatePicker. + */ + void dateSelected(QDate); + /** This signal is emitted when enter is pressed and a VALID date + * has been entered before into the line edit. Connect to both + * dateEntered() and dateSelected() to receive all events where the + * user really enters a date. + */ + void dateEntered(QDate); + /** This signal is emitted when the day has been selected by + * clicking on it in the table. + */ + void tableClicked(); + +private: + /// the font size for the widget + int fontsize; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + void init( const QDate &dt ); + void fillWeeksCombo(const QDate &date); + class KDatePickerPrivate; + KDatePickerPrivate *d; +}; + +#endif // KDATEPICKER_H diff --git a/microkde/kdatetbl.cpp b/microkde/kdatetbl.cpp new file mode 100644 index 0000000..0a2d1f5 --- a/dev/null +++ b/microkde/kdatetbl.cpp @@ -0,0 +1,735 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/////////////////// KDateTable widget class ////////////////////// +// +// Copyright (C) 1997 Tim D. Gilman +// (C) 1998-2001 Mirko Boehm +// Written using Qt (http://www.troll.no) for the +// KDE project (http://www.kde.org) +// +// This is a support class for the KDatePicker class. It just +// draws the calender table without titles, but could theoretically +// be used as a standalone. +// +// When a date is selected by the user, it emits a signal: +// dateSelected(QDate) + +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kapplication.h> +#include <klocale.h> +#include <kdebug.h> +#include <knotifyclient.h> +#include "kdatetbl.h" +#include <qdatetime.h> +#include <qstring.h> +#include <qpen.h> +#include <qpainter.h> +#include <qdialog.h> +#include <assert.h> +#include <qapplication.h> + +KDateValidator::KDateValidator(QWidget* parent, const char* name) + : QValidator(parent, name) +{ +} + +QValidator::State +KDateValidator::validate(QString& text, int&) const +{ + QDate temp; + // ----- everything is tested in date(): + return date(text, temp); +} + +QValidator::State +KDateValidator::date(const QString& text, QDate& d) const +{ + QDate tmp = KGlobal::locale()->readDate(text); + if (!tmp.isNull()) + { + d = tmp; + return Acceptable; + } else + return Valid; +} + +void +KDateValidator::fixup( QString& ) const +{ + +} + +KDateTable::KDateTable(QWidget *parent, QDate date_, const char* name, WFlags f) + : QGridView(parent, name, f) +{ + setFontSize(10); + if(!date_.isValid()) + { + date_=QDate::currentDate(); + } + setFocusPolicy( QWidget::StrongFocus ); + setNumRows(7); // 6 weeks max + headline + setNumCols(7); // 7 days a week + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); + viewport()->setBackgroundColor(QColor(220,245,255)); +#if 0 + viewport()->setEraseColor(lightGray); +#endif + setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth +} + +void +KDateTable::paintCell(QPainter *painter, int row, int col) +{ + QRect rect; + QString text; + QPen pen; + int w=cellWidth(); + int h=cellHeight(); + int pos; + QBrush brushBlue(blue); + QBrush brushLightblue(QColor(220,245,255)); + QFont font=KGlobalSettings::generalFont(); + // ----- + font.setPointSize(fontsize); + if(row==0) + { // we are drawing the headline + font.setBold(true); + painter->setFont(font); + bool normalday = true; + QString daystr; + if (KGlobal::locale()->weekStartsMonday()) + { + daystr = KGlobal::locale()->weekDayName(col+1, true); + if (col == 5 || col == 6) + normalday = false; + } else { + daystr = KGlobal::locale()->weekDayName(col==0? 7 : col, true); + if (col == 0 || col == 6) + normalday = false; + } + if (!normalday) + { + painter->setPen(QColor(220,245,255)); + painter->setBrush(brushLightblue); + painter->drawRect(0, 0, w, h); + painter->setPen(blue); + } else { + painter->setPen(blue); + painter->setBrush(brushBlue); + painter->drawRect(0, 0, w, h); + painter->setPen(white); + } + painter->drawText(0, 0, w, h-1, AlignCenter, + daystr, -1, &rect); + painter->setPen(black); + painter->moveTo(0, h-1); + painter->lineTo(w-1, h-1); + // ----- draw the weekday: + } else { + painter->setFont(font); + pos=7*(row-1)+col; + if (KGlobal::locale()->weekStartsMonday()) + pos++; + if(pos<firstday || (firstday+numdays<=pos)) + { // we are either + // ° painting a day of the previous month or + // ° painting a day of the following month + if(pos<firstday) + { // previous month + text.setNum(numDaysPrevMonth+pos-firstday+1); + } else { // following month + text.setNum(pos-firstday-numdays+1); + } + painter->setPen(gray); + } else { // paint a day of the current month + text.setNum(pos-firstday+1); + painter->setPen(black); + } + + pen=painter->pen(); + if(firstday+date.day()-1==pos) + { + if(hasFocus()) + { // draw the currently selected date + painter->setPen(red); + painter->setBrush(darkRed); + pen=white; + } else { + painter->setPen(darkGray); + painter->setBrush(darkGray); + pen=white; + } + } else { + painter->setBrush(QColor(220,245,255)); + painter->setPen(QColor(220,245,255)); + } + painter->drawRect(0, 0, w, h); + painter->setPen(pen); + painter->drawText(0, 0, w, h, AlignCenter, text, -1, &rect); + } + if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width()); + if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height()); +} + +void +KDateTable::keyPressEvent( QKeyEvent *e ) +{ + /* + // not working properly + if ( e->key() == Qt::Key_Prior ) { + if ( date.month() == 1 ) { + KNotifyClient::beep(); + return; + } + int day = date.day(); + if ( day > 27 ) + while ( !QDate::isValid( date.year(), date.month()-1, day ) ) + day--; + setDate(QDate(date.year(), date.month()-1, day)); + return; + } + if ( e->key() == Qt::Key_Next ) { + if ( date.month() == 12 ) { + KNotifyClient::beep(); + return; + } + int day = date.day(); + if ( day > 27 ) + while ( !QDate::isValid( date.year(), date.month()+1, day ) ) + day--; + setDate(QDate(date.year(), date.month()+1, day)); + return; + } + */ + int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0; + + int temp=firstday+date.day()-dayoff; + int pos = temp; + bool irgnore = true; + if ( e->state() != Qt::ControlButton ) { + if ( e->key() == Qt::Key_Up ) { + pos -= 7; + irgnore = false; + } + if ( e->key() == Qt::Key_Down ) { + pos += 7; + irgnore = false; + } + if ( e->key() == Qt::Key_Left ) { + pos--; + irgnore = false; + } + if ( e->key() == Qt::Key_Right ) { + pos++; + irgnore = false; + } + } + if ( irgnore ) + e->ignore(); + + if(pos+dayoff<=firstday) + { // this day is in the previous month + KNotifyClient::beep(); + return; + } + if(firstday+numdays<pos+dayoff) + { // this date is in the next month + KNotifyClient::beep(i18n( "Month not long enough" )); + return; + } + + if ( pos == temp ) + return; + + setDate(QDate(date.year(), date.month(), pos-firstday+dayoff)); + updateCell(temp/7+1, temp%7); // Update the previously selected cell + updateCell(pos/7+1, pos%7); // Update the selected cell + assert(QDate(date.year(), date.month(), pos-firstday+dayoff).isValid()); + + +} + +void +KDateTable::viewportResizeEvent(QResizeEvent * e) +{ + QGridView::viewportResizeEvent(e); + + setCellWidth(viewport()->width()/7); + setCellHeight(viewport()->height()/7); +} + +void +KDateTable::setFontSize(int size) +{ + int count; + QRect rect; + // ----- store rectangles: + fontsize=size; + QFont font = KGlobalSettings::generalFont(); + font.setPointSize(fontsize); + font.setBold( true ); + QFontMetrics metrics(font); + + // ----- find largest day name: + maxCell.setWidth(0); + maxCell.setHeight(0); + for(count=0; count<7; ++count) + { + rect=metrics.boundingRect(KGlobal::locale()->weekDayName(count+1, true)); + maxCell.setWidth(QMAX(maxCell.width(), rect.width())); + maxCell.setHeight(QMAX(maxCell.height(), rect.height())); + } + // ----- compare with a real wide number and add some space: + rect=metrics.boundingRect(QString::fromLatin1("88")); + maxCell.setWidth(QMAX(maxCell.width()+2, rect.width())); + maxCell.setHeight(QMAX(maxCell.height()+4, rect.height())); + if ( maxCell.width() * 1000 / maxCell.height() > 1900 ) + maxCell.setHeight(maxCell.width() * 1000 / 1900 ); +} + +void +KDateTable::contentsMousePressEvent(QMouseEvent *e) +{ + if(e->type()!=QEvent::MouseButtonPress) + { // the KDatePicker only reacts on mouse press events: + return; + } + if(!isEnabled()) + { + KNotifyClient::beep(); + return; + } + + int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0; + // ----- + int row, col, pos, temp; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + if(row<0 || col<0) + { // the user clicked on the frame of the table + return; + } + pos=7*(row-1)+col+1; + if(pos+dayoff<=firstday) + { // this day is in the previous month + KNotifyClient::beep(); + return; + } + if(firstday+numdays<pos+dayoff) + { // this date is in the next month + KNotifyClient::beep(); + return; + } + temp=firstday+date.day()-dayoff-1; + setDate(QDate(date.year(), date.month(), pos-firstday+dayoff)); + updateCell(temp/7+1, temp%7); // Update the previously selected cell + updateCell(row, col); // Update the selected cell + // assert(QDate(date.year(), date.month(), pos-firstday+dayoff).isValid()); + emit(tableClicked()); +} + +bool +KDateTable::setDate(const QDate& date_) +{ + bool changed=false; + QDate temp; + // ----- + if(!date_.isValid()) + { + kdDebug() << "KDateTable::setDate: refusing to set invalid date." << endl; + return false; + } + if(date!=date_) + { + date=date_; + changed=true; + } + temp.setYMD(date.year(), date.month(), 1); + firstday=temp.dayOfWeek(); + if(firstday==1) firstday=8; + numdays=date.daysInMonth(); + if(date.month()==1) + { // set to december of previous year + temp.setYMD(date.year()-1, 12, 1); + } else { // set to previous month + temp.setYMD(date.year(), date.month()-1, 1); + } + numDaysPrevMonth=temp.daysInMonth(); + if(changed) + { + repaintContents(false); + } + emit(dateChanged(date)); + return true; +} + +const QDate& +KDateTable::getDate() const +{ + return date; +} + +void KDateTable::focusInEvent( QFocusEvent *e ) +{ + repaintContents(false); + QGridView::focusInEvent( e ); +} + +void KDateTable::focusOutEvent( QFocusEvent *e ) +{ + repaintContents(false); + QGridView::focusOutEvent( e ); +} + +QSize +KDateTable::sizeHint() const +{ + if(maxCell.height()>0 && maxCell.width()>0) + { + return QSize((maxCell.width()+2)*numCols()+2*frameWidth(), + (maxCell.height()+4)*numRows()+2*frameWidth()); + } else { + return QSize(-1, -1); + } +} + +KDateInternalMonthPicker::KDateInternalMonthPicker +(int fontsize, QWidget* parent, const char* name) + : QGridView(parent, name), + result(0) // invalid +{ + QRect rect; + QFont font; + // ----- + activeCol = -1; + activeRow = -1; + font=KGlobalSettings::generalFont(); + font.setPointSize(fontsize); + setFont(font); + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); + setFrameStyle(QFrame::NoFrame); + setNumRows(4); + setNumCols(3); + // enable to find drawing failures: + // setTableFlags(Tbl_clipCellPainting); +#if 0 + viewport()->setEraseColor(lightGray); // for consistency with the datepicker +#endif + // ----- find the preferred size + // (this is slow, possibly, but unfortunatly it is needed here): + QFontMetrics metrics(font); + for(int i=1; i <= 12; ++i) + { + rect=metrics.boundingRect(KGlobal::locale()->monthName(i, false)); + if(max.width()<rect.width()) max.setWidth(rect.width()); + if(max.height()<rect.height()) max.setHeight(rect.height()); + } + +} + +QSize +KDateInternalMonthPicker::sizeHint() const +{ + return QSize((max.width()+6)*numCols()+2*frameWidth(), + (max.height()+6)*numRows()+2*frameWidth()); +} + +int +KDateInternalMonthPicker::getResult() const +{ + return result; +} + +void +KDateInternalMonthPicker::setupPainter(QPainter *p) +{ + p->setPen(black); +} + +void +KDateInternalMonthPicker::viewportResizeEvent(QResizeEvent*) +{ + setCellWidth(width()/3); + setCellHeight(height()/4); +} + +void +KDateInternalMonthPicker::paintCell(QPainter* painter, int row, int col) +{ + int index; + QString text; + // ----- find the number of the cell: + index=3*row+col+1; + text=KGlobal::locale()->monthName(index, false); + painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text); + if ( activeCol == col && activeRow == row ) + painter->drawRect( 0, 0, cellWidth(), cellHeight() ); +} + +void +KDateInternalMonthPicker::contentsMousePressEvent(QMouseEvent *e) +{ + if(!isEnabled() || e->button() != LeftButton) + { + KNotifyClient::beep(); + return; + } + // ----- + int row, col; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + + if(row<0 || col<0) + { // the user clicked on the frame of the table + activeCol = -1; + activeRow = -1; + } else { + activeCol = col; + activeRow = row; + updateCell( row, col /*, false */ ); + } +} + +void +KDateInternalMonthPicker::contentsMouseMoveEvent(QMouseEvent *e) +{ + if (e->state() & LeftButton) + { + int row, col; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + int tmpRow = -1, tmpCol = -1; + if(row<0 || col<0) + { // the user clicked on the frame of the table + if ( activeCol > -1 ) + { + tmpRow = activeRow; + tmpCol = activeCol; + } + activeCol = -1; + activeRow = -1; + } else { + bool differentCell = (activeRow != row || activeCol != col); + if ( activeCol > -1 && differentCell) + { + tmpRow = activeRow; + tmpCol = activeCol; + } + if ( differentCell) + { + activeRow = row; + activeCol = col; + updateCell( row, col /*, false */ ); // mark the new active cell + } + } + if ( tmpRow > -1 ) // repaint the former active cell + updateCell( tmpRow, tmpCol /*, true */ ); + } +} + +void +KDateInternalMonthPicker::contentsMouseReleaseEvent(QMouseEvent *e) +{ + if(!isEnabled()) + { + return; + } + // ----- + int row, col, pos; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + if(row<0 || col<0) + { // the user clicked on the frame of the table + emit(closeMe(0)); + } + pos=3*row+col+1; + result=pos; + emit(closeMe(1)); +} + + + +KDateInternalYearSelector::KDateInternalYearSelector +(int fontsize, QWidget* parent, const char* name) + : QLineEdit(parent, name), + val(new QIntValidator(this)), + result(0) +{ + QFont font; + // ----- + font=KGlobalSettings::generalFont(); + font.setPointSize(fontsize); + setFont(font); +#if 0 + setFrameStyle(QFrame::NoFrame); +#endif + // we have to respect the limits of QDate here, I fear: + val->setRange(0, 8000); + setValidator(val); + connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot())); +} + +void +KDateInternalYearSelector::yearEnteredSlot() +{ + bool ok; + int year; + QDate date; + // ----- check if this is a valid year: + year=text().toInt(&ok); + if(!ok) + { + KNotifyClient::beep(); + return; + } + date.setYMD(year, 1, 1); + if(!date.isValid()) + { + KNotifyClient::beep(); + return; + } + result=year; + emit(closeMe(1)); +} + +int +KDateInternalYearSelector::getYear() +{ + return result; +} + +void +KDateInternalYearSelector::setYear(int year) +{ + QString temp; + // ----- + temp.setNum(year); + setText(temp); +} + +KPopupFrame::KPopupFrame(QWidget* parent, const char* name) + : QFrame(parent, name, WType_Popup), + result(0), // rejected + main(0) +{ + setFrameStyle(QFrame::Box|QFrame::Raised); + setMidLineWidth(2); +} + +void +KPopupFrame::keyPressEvent(QKeyEvent* e) +{ + if(e->key()==Key_Escape) + { + result=0; // rejected + qApp->exit_loop(); + } +} + +void +KPopupFrame::close(int r) +{ + result=r; + qApp->exit_loop(); +} + +void +KPopupFrame::setMainWidget(QWidget* m) +{ + main=m; + if(main!=0) + { + resize(main->width()+2*frameWidth(), main->height()+2*frameWidth()); + } +} + +void +KPopupFrame::resizeEvent(QResizeEvent*) +{ + if(main!=0) + { + main->setGeometry(frameWidth(), frameWidth(), + width()-2*frameWidth(), height()-2*frameWidth()); + } +} + +void +KPopupFrame::popup(const QPoint &pos) +{ + // Make sure the whole popup is visible. + QRect d = QApplication::desktop()->frameGeometry(); + int x = pos.x(); + int y = pos.y(); + int w = width(); + int h = height(); + if (x+w > d.x()+d.width()) + x = d.width() - w; + if (y+h > d.y()+d.height()) + y = d.height() - h; + if (x < d.x()) + x = 0; + if (y < d.y()) + y = 0; + + // Pop the thingy up. + move(x, y); + show(); +} + +int +KPopupFrame::exec(QPoint pos) +{ + popup(pos); + repaint(); + qApp->enter_loop(); + hide(); + return result; +} + +int +KPopupFrame::exec(int x, int y) +{ + return exec(QPoint(x, y)); +} + +void KPopupFrame::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDateTable::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//#include "kdatetbl.moc" diff --git a/microkde/kdatetbl.h b/microkde/kdatetbl.h new file mode 100644 index 0000000..df7b7ef --- a/dev/null +++ b/microkde/kdatetbl.h @@ -0,0 +1,308 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KDATETBL_H +#define KDATETBL_H + +#include <qvalidator.h> +#include <qgridview.h> +#include <qlineedit.h> +#include <qdatetime.h> + +/** +* A table containing month names. It is used to pick a month directly. +* @internal +* @version $Id$ +* @author Tim Gilman, Mirko Boehm +*/ +class KDateInternalMonthPicker : public QGridView +{ + Q_OBJECT +protected: + /** + * Store the month that has been clicked [1..12]. + */ + int result; + /** + * the cell under mouse cursor when LBM is pressed + */ + short int activeCol; + short int activeRow; + /** + * Contains the largest rectangle needed by the month names. + */ + QRect max; +signals: + /** + * This is send from the mouse click event handler. + */ + void closeMe(int); +public: + /** + * The constructor. + */ + KDateInternalMonthPicker(int fontsize, QWidget* parent, const char* name=0); + /** + * The size hint. + */ + QSize sizeHint() const; + /** + * Return the result. 0 means no selection (reject()), 1..12 are the + * months. + */ + int getResult() const; +protected: + /** + * Set up the painter. + */ + void setupPainter(QPainter *p); + /** + * The resize event. + */ + void viewportResizeEvent(QResizeEvent*); + /** + * Paint a cell. This simply draws the month names in it. + */ + virtual void paintCell(QPainter* painter, int row, int col); + /** + * Catch mouse click and move events to paint a rectangle around the item. + */ + void contentsMousePressEvent(QMouseEvent *e); + void contentsMouseMoveEvent(QMouseEvent *e); + /** + * Emit monthSelected(int) when a cell has been released. + */ + void contentsMouseReleaseEvent(QMouseEvent *e); + +private: + class KDateInternalMonthPrivate; + KDateInternalMonthPrivate *d; +}; + +/** Year selection widget. +* @internal +* @version $Id$ +* @author Tim Gilman, Mirko Boehm +*/ +class KDateInternalYearSelector : public QLineEdit +{ + Q_OBJECT +protected: + QIntValidator *val; + int result; +public slots: + void yearEnteredSlot(); +signals: + void closeMe(int); +public: + KDateInternalYearSelector(int fontsize, + QWidget* parent=0, + const char* name=0); + int getYear(); + void setYear(int year); + +private: + class KDateInternalYearPrivate; + KDateInternalYearPrivate *d; +}; + +/** + * Frame with popup menu behaviour. + * @author Tim Gilman, Mirko Boehm + * @version $Id$ + */ +class KPopupFrame : public QFrame +{ + Q_OBJECT +protected: + /** + * The result. It is returned from exec() when the popup window closes. + */ + int result; + /** + * Catch key press events. + */ + void keyPressEvent(QKeyEvent* e); + /** + * The only subwidget that uses the whole dialog window. + */ + QWidget *main; +public slots: + /** + * Close the popup window. This is called from the main widget, usually. + * @p r is the result returned from exec(). + */ + void close(int r); +public: + /** + * The contructor. Creates a dialog without buttons. + */ + KPopupFrame(QWidget* parent=0, const char* name=0); + /** + * Set the main widget. You cannot set the main widget from the constructor, + * since it must be a child of the frame itselfes. + * Be careful: the size is set to the main widgets size. It is up to you to + * set the main widgets correct size before setting it as the main + * widget. + */ + void setMainWidget(QWidget* m); + /** + * The resize event. Simply resizes the main widget to the whole + * widgets client size. + */ + void resizeEvent(QResizeEvent*); + /** + * Open the popup window at position pos. + */ + void popup(const QPoint &pos); + /** + * Execute the popup window. + */ + int exec(QPoint p); + /** + * Dito. + */ + int exec(int x, int y); + +private: + + virtual bool close(bool alsoDelete) { return QFrame::close(alsoDelete); } +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KPopupFramePrivate; + KPopupFramePrivate *d; +}; + +/** +* Validates user-entered dates. +*/ +class KDateValidator : public QValidator +{ +public: + KDateValidator(QWidget* parent=0, const char* name=0); + virtual State validate(QString&, int&) const; + virtual void fixup ( QString & input ) const; + State date(const QString&, QDate&) const; +}; + +/** + * Date selection table. + * This is a support class for the KDatePicker class. It just + * draws the calender table without titles, but could theoretically + * be used as a standalone. + * + * When a date is selected by the user, it emits a signal: + * dateSelected(QDate) + * + * @internal + * @version $Id$ + * @author Tim Gilman, Mirko Boehm + */ +class KDateTable : public QGridView +{ + Q_OBJECT +public: + /** + * The constructor. + */ + KDateTable(QWidget *parent=0, + QDate date=QDate::currentDate(), + const char* name=0, WFlags f=0); + /** + * Returns a recommended size for the widget. + * To save some time, the size of the largest used cell content is + * calculated in each paintCell() call, since all calculations have + * to be done there anyway. The size is stored in maxCell. The + * sizeHint() simply returns a multiple of maxCell. + */ + virtual QSize sizeHint() const; + /** + * Set the font size of the date table. + */ + void setFontSize(int size); + /** + * Select and display this date. + */ + bool setDate(const QDate&); + const QDate& getDate() const; + + +protected: + /** + * Paint a cell. + */ + virtual void paintCell(QPainter*, int, int); + /** + * Handle the resize events. + */ + virtual void viewportResizeEvent(QResizeEvent *); + /** + * React on mouse clicks that select a date. + */ + virtual void contentsMousePressEvent(QMouseEvent *); + virtual void keyPressEvent( QKeyEvent *e ); + virtual void focusInEvent( QFocusEvent *e ); + virtual void focusOutEvent( QFocusEvent *e ); + /** + * The font size of the displayed text. + */ + int fontsize; + /** + * The currently selected date. + */ + QDate date; + /** + * The day of the first day in the month [1..7]. + */ + int firstday; + /** + * The number of days in the current month. + */ + int numdays; + /** + * The number of days in the previous month. + */ + int numDaysPrevMonth; + /** + * unused + */ + bool unused_hasSelection; + /** + * Save the size of the largest used cell content. + */ + QRect maxCell; +signals: + /** + * The selected date changed. + */ + void dateChanged(QDate); + /** + * A date has been selected by clicking on the table. + */ + void tableClicked(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDateTablePrivate; + KDateTablePrivate *d; +}; + +#endif // KDATETBL_H diff --git a/microkde/kdebug.h b/microkde/kdebug.h new file mode 100644 index 0000000..bb9cfe3 --- a/dev/null +++ b/microkde/kdebug.h @@ -0,0 +1,92 @@ +#ifndef MINIKDE_KDEBUG_H +#define MINIKDE_KDEBUG_H + +#include <stdio.h> + +#include <qstring.h> + + + +class kdbgstream; +typedef kdbgstream & (*KDBGFUNC)(kdbgstream &); // manipulator function + +class kdbgstream { + public: + kdbgstream(unsigned int _area, unsigned int _level, bool _print = true) : + area(_area), level(_level), print( _print ) { print = false; } + /* kdbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print = false) : + output(QString::fromLatin1(initialString)), area(_area), level(_level), print(_print) { print = false; }*/ + ~kdbgstream() + { + // if (!output.isEmpty()) { + // fprintf(stderr,"ASSERT: debug output not ended with \\n\n"); + //*this << "\n"; + //} + } + kdbgstream &operator<<(bool) { + + return *this; + } + kdbgstream &operator<<(short) { + + return *this; + } + kdbgstream &operator<<(unsigned short) { + + return *this; + } + kdbgstream &operator<<(char) { + + return *this; + } + kdbgstream &operator<<(unsigned char) { + + return *this; + } + + kdbgstream &operator<<(int) { + + return *this; + } + kdbgstream &operator<<(unsigned int) { + + return *this; + } + kdbgstream &operator<<(long) { + return *this; + } + kdbgstream &operator<<(unsigned long) { + return *this; + } + kdbgstream &operator<<(const QString&) { + return *this; + } + kdbgstream &operator<<(const char*) { + return *this; + } + kdbgstream &operator<<(const QCString&) { + return *this; + } + kdbgstream& operator<<(KDBGFUNC f) { + return (*f)(*this); + } + kdbgstream& operator<<(double) { + if (!print) return *this; + return *this; + } + void flush() { + return; + } + private: + QString output; + unsigned int area, level; + bool print; +}; + +inline kdbgstream &endl( kdbgstream &s) { s << "\n"; return s; } + +inline kdbgstream kdDebug(int area = 0) { return kdbgstream(area, 0); } +inline kdbgstream kdWarning(int area = 0) { return kdbgstream(area, 0); } +inline kdbgstream kdError(int area = 0) { return kdbgstream(area, 0); } + +#endif diff --git a/microkde/kdecore/kcatalogue.cpp b/microkde/kdecore/kcatalogue.cpp new file mode 100644 index 0000000..97ac326 --- a/dev/null +++ b/microkde/kdecore/kcatalogue.cpp @@ -0,0 +1,131 @@ +/* This file is part of the KDE libraries + Copyright (c) 2001 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//US #include <config.h> + +#include <qfile.h> + +#include <kdebug.h> + +#include "kcatalogue.h" + +char *k_nl_find_msg(struct kde_loaded_l10nfile *domain_file, + const char *msgid); +void k_nl_unload_domain (struct loaded_domain *domain); + +#ifndef KDE_USE_FINAL // with --enable-final, we're getting this from libintl.cpp +struct kde_loaded_l10nfile +{ + const char *filename; + int decided; + + const void *data; + + kde_loaded_l10nfile() : filename(0), decided(0), data(0) {} +}; +#endif + +class KCataloguePrivate +{ +public: + QString name; + + kde_loaded_l10nfile domain; +}; + +KCatalogue::KCatalogue(const QString & name) + : d( new KCataloguePrivate ) +{ + d->name = name; +} + +KCatalogue::KCatalogue(const KCatalogue & rhs) + : d( new KCataloguePrivate ) +{ + *this = rhs; +} + +KCatalogue & KCatalogue::operator=(const KCatalogue & rhs) +{ + d->name = rhs.d->name; + setFileName( rhs.fileName() ); + + return *this; +} + +KCatalogue::~KCatalogue() +{ + doUnload(); + + delete d; +} + +QString KCatalogue::name() const +{ + return d->name; +} + +void KCatalogue::setFileName( const QString & fileName ) +{ + // nothing to do if the file name is already the same + if ( this->fileName() == fileName ) return; + + doUnload(); + + QCString newFileName = QFile::encodeName( fileName ); + + if ( !fileName.isEmpty() ) + { + // set file name + char *filename = new char[ newFileName.length() + 1 ]; + ::qstrcpy( filename, newFileName ); + d->domain.filename = filename; + } +} + +QString KCatalogue::fileName() const +{ + return QFile::decodeName( d->domain.filename ); +} + +const char * KCatalogue::translate(const char * msgid) const +{ + qDebug("KCatalogue::translate has to be fixed %s",msgid ); +//US return ::k_nl_find_msg( &d->domain, msgid ); + return msgid; + +} + +void KCatalogue::doUnload() +{ + // use gettext's unloader + if ( d->domain.data ) + { +//US ::k_nl_unload_domain( (struct loaded_domain *)d->domain.data ); + qDebug("KCatalogue::doUnload has to be fixed" ); + + } + d->domain.data = 0; + + // free name + delete [] const_cast<char *>(d->domain.filename); + d->domain.filename = 0; + + d->domain.decided = 0; +} diff --git a/microkde/kdecore/kcatalogue.h b/microkde/kdecore/kcatalogue.h new file mode 100644 index 0000000..e229cc8 --- a/dev/null +++ b/microkde/kdecore/kcatalogue.h @@ -0,0 +1,104 @@ +/* This file is part of the KDE libraries + Copyright (c) 2001 Hans Petter Bieker <bieker@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KCATALOGUE_H +#define KCATALOGUE_H + +#include <qstring.h> + +struct kde_loaded_l10nfile; + +class KCataloguePrivate; + +/** + * This class abstracts a gettext message catalogue. It will take care of + * opening the file and reading the catalogue. + * + * @see KLocale + */ +//REVISED: hausmann +class KCatalogue +{ +public: + /** + * Constructor. + * + * @param name The name of the catalogue + */ + explicit KCatalogue(const QString & name = QString::null); + + /** + * Copy constructor. + */ + KCatalogue(const KCatalogue & rhs); + + /** + * Assignment operator. + */ + KCatalogue & operator = ( const KCatalogue & rhs); + + /** + * Destructor. + */ + virtual ~KCatalogue(); + + /** + * Returns the name of the catalogue. + * + * @return The name of the catalogue + */ + QString name() const; + + /** + * Changes the current file name. + * + * @param fileName The new file name + */ + + void setFileName( const QString & fileName ); + + /** + * Retrieves a translation of the specified message id. + * + * Do not pass 0 or "" strings as message ids. + * + * @param msgid The message id + * + * @return The translated message, in utf8 encoding, or 0 if not found + */ + const char * translate( const char * msgid ) const; + +private: + /** + * @internal Retrieves the current file name. + * + * @return The current file name, if any. + */ + QString fileName() const; + + /** + * @internal Unloads the current file. + */ + void doUnload(); + +private: + KCataloguePrivate * d; +}; + +#endif diff --git a/microkde/kdecore/kconfigbase.h b/microkde/kdecore/kconfigbase.h new file mode 100644 index 0000000..7e56d11 --- a/dev/null +++ b/microkde/kdecore/kconfigbase.h @@ -0,0 +1,102 @@ +/* + This file is part of the KDE libraries + Copyright (c) 1999 Preston Brown <pbrown@kde.org> + Copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org> + Copyright (c) 2001 Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// $Id$ + +#ifndef _KCONFIGBASE_H +#define _KCONFIGBASE_H + +#include "kconfig.h" + +/** + * Helper class to facilitate working with @ref KConfig / @ref KSimpleConfig + * groups. + * + * Careful programmers always set the group of a + * @ref KConfig @ref KSimpleConfig object to the group they want to read from + * and set it back to the old one of afterwards. This is usually + * written as: + * <pre> + * + * QString oldgroup config->group(); + * config->setGroup( "TheGroupThatIWant" ); + * ... + * config->writeEntry( "Blah", "Blubb" ); + * + * config->setGroup( oldgroup ); + * </pre> + * + * In order to facilitate this task, you can use + * KConfigGroupSaver. Simply construct such an object ON THE STACK + * when you want to switch to a new group. Then, when the object goes + * out of scope, the group will automatically be restored. If you + * want to use several different groups within a function or method, + * you can still use KConfigGroupSaver: Simply enclose all work with + * one group (including the creation of the KConfigGroupSaver object) + * in one block. + * + * @author Matthias Kalle Dalheimer <kalle@kde.org> + * @version $Id$ + * @see KConfigBase, KConfig, KSimpleConfig + * @short Helper class for easier use of KConfig/KSimpleConfig groups + */ +//US I converted the class in a way that it can be used with KConfig objects of microkde + +class KConfigGroupSaver +{ +public: + /** + * Constructor. You pass a pointer to the KConfigBase-derived + * object you want to work with and a string indicating the _new_ + * group. + * + * @param config The KConfigBase-derived object this + * KConfigGroupSaver works on. + * @param group The new group that the config object should switch to. + */ + KConfigGroupSaver( KConfig* config, QString group ) + /* KDE 4 : make the second parameter const QString & */ + : _config(config), _oldgroup(config->group()) + { _config->setGroup( group ); } + + KConfigGroupSaver( KConfig* config, const char *group ) + : _config(config), _oldgroup(config->group()) + { _config->setGroup( group ); } + + KConfigGroupSaver( KConfig* config, const QCString &group ) + : _config(config), _oldgroup(config->group()) + { _config->setGroup( group ); } + + ~KConfigGroupSaver() { _config->setGroup( _oldgroup ); } + + KConfig* config() { return _config; }; + +private: + KConfig* _config; + QString _oldgroup; + + KConfigGroupSaver(const KConfigGroupSaver&); + KConfigGroupSaver& operator=(const KConfigGroupSaver&); + +}; + +#endif diff --git a/microkde/kdecore/klibloader.cpp b/microkde/kdecore/klibloader.cpp new file mode 100644 index 0000000..1410308 --- a/dev/null +++ b/microkde/kdecore/klibloader.cpp @@ -0,0 +1,626 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Torben Weis <weis@kde.org> + Copyright (C) 2000 Michael Matz <matz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//US #include <config.h> +#include <qclipboard.h> +#include <qfile.h> +#include <qtimer.h> +#include <qobjectdict.h> +#include <qwidgetlist.h> +#include <qwidget.h> + +#include "kapplication.h" +#include "klibloader.h" +#include "kstandarddirs.h" +#include "kdebug.h" +#include "klocale.h" + +//US #include "ltdl.h" + +//US do everything through qlibrary +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#include <qtopia/qlibrary.h> +#endif + +/*US +#ifdef Q_WS_X11 +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#endif +*/ +template class QAsciiDict<KLibrary>; + +#include <stdlib.h> //getenv + +/*US +#if HAVE_DLFCN_H +# include <dlfcn.h> +#endif + +#ifdef RTLD_GLOBAL +# define LT_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_GLOBAL DL_GLOBAL +# endif +#endif +#ifndef LT_GLOBAL +# define LT_GLOBAL 0 +#endif +*/ + +/*US +extern "C" { +extern int lt_dlopen_flag; +} +*/ + +KLibFactory::KLibFactory( QObject* parent, const char* name ) + : QObject( parent, name ) +{ +} + +KLibFactory::~KLibFactory() +{ +// kdDebug(150) << "Deleting KLibFactory " << this << endl; +} + +QObject* KLibFactory::create( QObject* parent, const char* name, const char* classname, const QStringList &args ) +{ + QObject* obj = createObject( parent, name, classname, args ); + if ( obj ) + emit objectCreated( obj ); + return obj; +} + + +QObject* KLibFactory::createObject( QObject*, const char*, const char*, const QStringList &) +{ + return 0; +} + + +// ----------------------------------------------- + +//US KLibrary::KLibrary( const QString& libname, const QString& filename, void * handle ) +KLibrary::KLibrary( const QString& libname, const QString& filename, QLibrary* handle ) +{ + /* Make sure, we have a KLibLoader */ + (void) KLibLoader::self(); + m_libname = libname; + m_filename = filename; + m_handle = handle; + m_factory = 0; + m_timer = 0; +} + +KLibrary::~KLibrary() +{ +// kdDebug(150) << "Deleting KLibrary " << this << " " << m_libname << endl; + if ( m_timer && m_timer->isActive() ) + m_timer->stop(); + + // If any object is remaining, delete + if ( m_objs.count() > 0 ) + { + QPtrListIterator<QObject> it( m_objs ); + for ( ; it.current() ; ++it ) + { + kdDebug(150) << "Factory still has object " << it.current() << " " << it.current()->name () << " Library = " << m_libname << endl; + disconnect( it.current(), SIGNAL( destroyed() ), + this, SLOT( slotObjectDestroyed() ) ); + } + m_objs.setAutoDelete(true); + m_objs.clear(); + } + + if ( m_factory ) { +// kdDebug(150) << " ... deleting the factory " << m_factory << endl; + delete m_factory; + } +} + +QString KLibrary::name() const +{ + return m_libname; +} + +QString KLibrary::fileName() const +{ + return m_filename; +} + +KLibFactory* KLibrary::factory() +{ + if ( m_factory ) + return m_factory; + + QCString symname; + symname.sprintf("init_%s", name().latin1() ); + + void* sym = symbol( symname ); + if ( !sym ) + { + kdWarning(150) << "KLibrary: The library " << name() << " does not offer an init_" << name() << " function" << endl; + return 0; + } + + typedef KLibFactory* (*t_func)(); + t_func func = (t_func)sym; + m_factory = func(); + + if( !m_factory ) + { + kdWarning(150) << "KLibrary: The library " << name() << " does not offer a KDE compatible factory" << endl; + return 0; + } + + connect( m_factory, SIGNAL( objectCreated( QObject * ) ), + this, SLOT( slotObjectCreated( QObject * ) ) ); + + return m_factory; +} + +void* KLibrary::symbol( const char* symname ) const +{ +//US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname ); + void* sym = m_handle->resolve( symname ); + if ( !sym ) + { +//US kdWarning(150) << "KLibrary: " << lt_dlerror() << endl; + kdWarning(150) << "KLibrary: " << m_libname << ", symbol:" << symname << " not found " << endl; + return 0; + } + + return sym; +} + +bool KLibrary::hasSymbol( const char* symname ) const +{ +//US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname ); + void* sym = m_handle->resolve( symname ); + return (sym != 0L ); +} + +void KLibrary::unload() const +{ + if (KLibLoader::s_self) + KLibLoader::s_self->unloadLibrary(QFile::encodeName(name())); +} + +void KLibrary::slotObjectCreated( QObject *obj ) +{ + if ( !obj ) + return; + + if ( m_timer && m_timer->isActive() ) + m_timer->stop(); + + if ( m_objs.containsRef( obj ) ) + return; // we know this object already + + connect( obj, SIGNAL( destroyed() ), + this, SLOT( slotObjectDestroyed() ) ); + + m_objs.append( obj ); +} + +void KLibrary::slotObjectDestroyed() +{ + m_objs.removeRef( sender() ); + + if ( m_objs.count() == 0 ) + { +// kdDebug(150) << "KLibrary: shutdown timer for " << name() << " started!" +// << endl; + + if ( !m_timer ) + { + m_timer = new QTimer( this, "klibrary_shutdown_timer" ); + connect( m_timer, SIGNAL( timeout() ), + this, SLOT( slotTimeout() ) ); + } + + // as long as it's not stable make the timeout short, for debugging + // pleasure (matz) + //m_timer->start( 1000*60, true ); + m_timer->start( 1000*10, true ); + } +} + +void KLibrary::slotTimeout() +{ + if ( m_objs.count() != 0 ) + return; + + /* Don't go through KLibLoader::unloadLibrary(), because that uses the + ref counter, but this timeout means to unconditionally close this library + The destroyed() signal will take care to remove us from all lists. + */ + delete this; +} + +// ------------------------------------------------- + +/* This helper class is needed, because KLibraries can go away without + being unloaded. So we need some info about KLibraries even after its + death. */ +class KLibWrapPrivate +{ +public: +//US KLibWrapPrivate(KLibrary *l, lt_dlhandle h); + KLibWrapPrivate(KLibrary *l, QLibrary* h); + + KLibrary *lib; + enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode; + int ref_count; +//US lt_dlhandle handle; + QLibrary *handle; + QString name; + QString filename; +}; + +//US KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, lt_dlhandle h) +KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, QLibrary* h) + : lib(l), ref_count(1), handle(h), name(l->name()), filename(l->fileName()) +{ + unload_mode = UNKNOWN; +/*US + if (lt_dlsym(handle, "__kde_do_not_unload") != 0) { +// kdDebug(150) << "Will not unload " << name << endl; + unload_mode = DONT_UNLOAD; + } else if (lt_dlsym(handle, "__kde_do_unload") != 0) { + unload_mode = UNLOAD; + } +*/ +//US use instead: + if (h->resolve("__kde_do_not_unload") != 0) { +// kdDebug(150) << "Will not unload " << name << endl; + unload_mode = DONT_UNLOAD; + } else if (h->resolve("__kde_do_unload") != 0) { + unload_mode = UNLOAD; + } +} + +class KLibLoaderPrivate +{ +public: + QPtrList<KLibWrapPrivate> loaded_stack; + QPtrList<KLibWrapPrivate> pending_close; + enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode; + + QString errorMessage; +}; + +KLibLoader* KLibLoader::s_self = 0; + +KLibLoader* KLibLoader::self() +{ + if ( !s_self ) + s_self = new KLibLoader; + return s_self; +} + +void KLibLoader::cleanUp() +{ + if ( !s_self ) + return; + + delete s_self; + s_self = 0; +} + +KLibLoader::KLibLoader( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + s_self = this; + d = new KLibLoaderPrivate; +//US lt_dlinit(); + d->unload_mode = KLibLoaderPrivate::UNKNOWN; + if (getenv("KDE_NOUNLOAD") != 0) + d->unload_mode = KLibLoaderPrivate::DONT_UNLOAD; + else if (getenv("KDE_DOUNLOAD") != 0) + d->unload_mode = KLibLoaderPrivate::UNLOAD; + d->loaded_stack.setAutoDelete( true ); +} + +KLibLoader::~KLibLoader() +{ +// kdDebug(150) << "Deleting KLibLoader " << this << " " << name() << endl; + + QAsciiDictIterator<KLibWrapPrivate> it( m_libs ); + for (; it.current(); ++it ) + { + kdDebug(150) << "The KLibLoader contains the library " << it.current()->name + << " (" << it.current()->lib << ")" << endl; + d->pending_close.append(it.current()); + } + + close_pending(0); + + delete d; +} + +//static +QString KLibLoader::findLibrary( const char * name/*US , const KInstance * instance*/ ) +{ + QCString libname( name ); + + // only append ".la" if there is no extension + // this allows to load non-libtool libraries as well + // (mhk, 20000228) + int pos = libname.findRev('/'); + if (pos < 0) + pos = 0; + if (libname.find('.', pos) < 0) + libname += ".la"; + + // only look up the file if it is not an absolute filename + // (mhk, 20000228) + QString libfile; + if (libname[0] == '/') + libfile = libname; + else + { +//US libfile = instance->dirs()->findResource( "module", libname ); + libfile = KGlobal::dirs()->findResource( "module", libname ); + if ( libfile.isEmpty() ) + { +//US libfile = instance->dirs()->findResource( "lib", libname ); + libfile = KGlobal::dirs()->findResource( "lib", libname ); +#ifndef NDEBUG + if ( !libfile.isEmpty() && libname.left(3) == "lib" ) // don't warn for kdeinit modules + kdDebug(150) << "library " << libname << " not found under 'module' but under 'lib'" << endl; +#endif + } + if ( libfile.isEmpty() ) + { +#ifndef NDEBUG + kdDebug(150) << "library=" << libname << ": No file names " << libname.data() << " found in paths." << endl; +#endif + self()->d->errorMessage = i18n("Library files for \"%1\" not found in paths").arg(libname); + } + else + self()->d->errorMessage = QString::null; + } + return libfile; +} + + +KLibrary* KLibLoader::globalLibrary( const char *name ) +{ +KLibrary *tmp; +/*US +int olt_dlopen_flag = lt_dlopen_flag; + + lt_dlopen_flag |= LT_GLOBAL; + kdDebug(150) << "Loading the next library global with flag " + << lt_dlopen_flag + << "." << endl; +*/ + tmp = library(name); +/*US + lt_dlopen_flag = olt_dlopen_flag; +*/ +return tmp; +} + + +KLibrary* KLibLoader::library( const char *name ) +{ + if (!name) + return 0; + + KLibWrapPrivate* wrap = m_libs[name]; + if (wrap) { + /* Nothing to do to load the library. */ + wrap->ref_count++; + return wrap->lib; + } + + /* Test if this library was loaded at some time, but got + unloaded meanwhile, whithout being dlclose()'ed. */ + QPtrListIterator<KLibWrapPrivate> it(d->loaded_stack); + for (; it.current(); ++it) { + if (it.current()->name == name) + wrap = it.current(); + } + + if (wrap) { + d->pending_close.removeRef(wrap); + if (!wrap->lib) { + /* This lib only was in loaded_stack, but not in m_libs. */ + wrap->lib = new KLibrary( name, wrap->filename, wrap->handle ); + } + wrap->ref_count++; + } else { + QString libfile = findLibrary( name ); + if ( libfile.isEmpty() ) + return 0; + + const QString & qpeDir = QPEApplication::qpeDir(); + libfile = qpeDir + libfile; +//US QLibrary *lib = new QLibrary( qpeDir + "/plugins/korganizer/libopiekabc.so", QLibrary::Immediately ); + QLibrary *qlib = new QLibrary( libfile.latin1(), QLibrary::Immediately ); + +//US lt_dlhandle handle = lt_dlopen( libfile.latin1() ); +//US if ( !handle ) + if ( !qlib ) + { +//US const char* errmsg = lt_dlerror(); + char* errmsg; + sprintf(errmsg, "KLibLoader::library could not load library: %s", libfile.latin1()); + qDebug(errmsg); + + if(errmsg) + d->errorMessage = QString::fromLatin1(errmsg); + else + d->errorMessage = QString::null; + kdWarning(150) << "library=" << name << ": file=" << libfile << ": " << d->errorMessage << endl; + return 0; + } + else + d->errorMessage = QString::null; + + KLibrary *lib = new KLibrary( name, libfile, qlib ); + wrap = new KLibWrapPrivate(lib, qlib); + d->loaded_stack.prepend(wrap); + } + m_libs.insert( name, wrap ); + + connect( wrap->lib, SIGNAL( destroyed() ), + this, SLOT( slotLibraryDestroyed() ) ); + + return wrap->lib; +} + +QString KLibLoader::lastErrorMessage() const +{ + return d->errorMessage; +} + +void KLibLoader::unloadLibrary( const char *libname ) +{ + KLibWrapPrivate *wrap = m_libs[ libname ]; + if (!wrap) + return; + if (--wrap->ref_count) + return; + +// kdDebug(150) << "closing library " << libname << endl; + + m_libs.remove( libname ); + + disconnect( wrap->lib, SIGNAL( destroyed() ), + this, SLOT( slotLibraryDestroyed() ) ); + close_pending( wrap ); +} + +KLibFactory* KLibLoader::factory( const char* name ) +{ + KLibrary* lib = library( name ); + if ( !lib ) + return 0; + + return lib->factory(); +} + +void KLibLoader::slotLibraryDestroyed() +{ + const KLibrary *lib = static_cast<const KLibrary *>( sender() ); + + QAsciiDictIterator<KLibWrapPrivate> it( m_libs ); + for (; it.current(); ++it ) + if ( it.current()->lib == lib ) + { + KLibWrapPrivate *wrap = it.current(); + wrap->lib = 0; /* the KLibrary object is already away */ + m_libs.remove( it.currentKey() ); + close_pending( wrap ); + return; + } +} + +void KLibLoader::close_pending(KLibWrapPrivate *wrap) +{ + if (wrap && !d->pending_close.containsRef( wrap )) + d->pending_close.append( wrap ); + + /* First delete all KLibrary objects in pending_close, but _don't_ unload + the DSO behind it. */ + QPtrListIterator<KLibWrapPrivate> it(d->pending_close); + for (; it.current(); ++it) { + wrap = it.current(); + if (wrap->lib) { + disconnect( wrap->lib, SIGNAL( destroyed() ), + this, SLOT( slotLibraryDestroyed() ) ); + delete wrap->lib; + wrap->lib = 0; + } + } + + if (d->unload_mode == KLibLoaderPrivate::DONT_UNLOAD) return; + + bool deleted_one = false; + while ((wrap = d->loaded_stack.first())) { + /* Let's first see, if we want to try to unload this lib. + If the env. var KDE_DOUNLOAD is set, we try to unload every lib. + If not, we look at the lib itself, and unload it only, if it exports + the symbol __kde_do_unload. */ + if (d->unload_mode != KLibLoaderPrivate::UNLOAD + && wrap->unload_mode != KLibWrapPrivate::UNLOAD) + break; + + /* Now ensure, that the libs are only unloaded in the reverse direction + they were loaded. */ + if (!d->pending_close.containsRef( wrap )) { + if (!deleted_one) + /* Only diagnose, if we really haven't deleted anything. */ +// kdDebug(150) << "try to dlclose " << wrap->name << ": not yet" << endl; + break; + } + +// kdDebug(150) << "try to dlclose " << wrap->name << ": yes, done." << endl; + +#ifndef Q_WS_QWS + if ( !deleted_one ) { + /* Only do the hack once in this loop. + WABA: *HACK* + We need to make sure to clear the clipboard before unloading a DSO + because the DSO could have defined an object derived from QMimeSource + and placed that on the clipboard. */ + /*kapp->clipboard()->clear();*/ + + /* Well.. let's do something more subtle... convert the clipboard context + to text. That should be safe as it only uses objects defined by Qt. */ + + QWidgetList *widgetlist = QApplication::topLevelWidgets(); + QWidget *co = widgetlist->first(); + while (co) { + if (qstrcmp(co->name(), "internal clipboard owner") == 0) { + if (XGetSelectionOwner(co->x11Display(), XA_PRIMARY) == co->winId()) + kapp->clipboard()->setText(kapp->clipboard()->text()); + + break; + } + co = widgetlist->next(); + } + delete widgetlist; + } +#else + // FIXME(E): Implement in Qt Embedded +#endif + + deleted_one = true; +//US lt_dlclose(wrap->handle); + wrap->handle->unload(); + + d->pending_close.removeRef(wrap); + /* loaded_stack is AutoDelete, so wrap is freed */ + d->loaded_stack.remove(); + } +} + +void KLibLoader::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KLibFactory::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "klibloader.moc" diff --git a/microkde/kdecore/klibloader.h b/microkde/kdecore/klibloader.h new file mode 100644 index 0000000..ed57109 --- a/dev/null +++ b/microkde/kdecore/klibloader.h @@ -0,0 +1,405 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Torben Weis <weis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KLIBLOADER_H +#define KLIBLOADER_H + +#include <qobject.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qasciidict.h> +#include <qptrlist.h> +#include <kglobal.h> + +#include <stdlib.h> // For backwards compatibility + +class KInstance; +class QTimer; +class KLibrary; +class KLibFactory; +class KLibFactoryPrivate; +class KLibLoaderPrivate; +class KLibraryPrivate; + +class QLibrary; + +#define K_EXPORT_COMPONENT_FACTORY( libname, factory ) \ + extern "C" { void *init_##libname() { return new factory; } } + +/** + * @short Represents a dynamically loaded library. + * + * KLibrary allows you to look up symbols of the shared library. + * Use @ref KLibLoader to create a new instance of KLibrary. + * + * @see KLibLoader + * @author Torben Weis <weis@kde.org> + */ +class KLibrary : public QObject +{ + friend class KLibLoader; + friend class QAsciiDict<KLibrary>; + + Q_OBJECT +public: + /** + * @internal + * Don't create KLibrary objects on your own. Instead use @ref KLibLoader. + */ +//US KLibrary( const QString& libname, const QString& filename, void * handle ); + KLibrary( const QString& libname, const QString& filename, QLibrary* handle ); + + /** + * Returns the name of the library. + * @return The name of the library like "libkspread". + */ + QString name() const; + + /** + * Returns the file name of the library. + * @return The filename of the library, for example "/opt/kde2&/lib/libkspread.la" + */ + QString fileName() const; + + /** + * Returns the factory of the library. + * @return The factory of the library if there is any, otherwise 0 + */ + KLibFactory* factory(); + + /** + * Looks up a symbol from the library. This is a very low level + * function that you usually don't want to use. Usually you should + * check using @ref hasSymbol() whether the symbol actually exists, + * otherwise a warning will be printed. + * @param name the name of the symbol to look up + * @return the address of the symbol, or 0 if it does not exist + * @see #hasSymbol + */ + void* symbol( const char* name ) const; + + /** + * Looks up a symbol from the library. This is a very low level + * function that you usually don't want to use. + * Unlike @ref symbol(), this method doesn't warn if the symbol doesn't exist, + * so if the symbol might or might not exist, better use hasSymbol() before symbol(). + * @param name the name of the symbol to check + * @return true if the symbol exists + * @since 3.1 + */ + bool hasSymbol( const char* name ) const; + + /** + * Unloads the library. + * This typically results in the deletion of this object. You should + * not reference its pointer after calling this function. + */ + void unload() const; + +private slots: + void slotObjectCreated( QObject *obj ); + void slotObjectDestroyed(); + void slotTimeout(); + +private: + /** + * @internal + * Don't destruct KLibrary objects yourself. Instead use @ref unload() instead. + */ + ~KLibrary(); + + QString m_libname; + QString m_filename; + KLibFactory* m_factory; +//US void * m_handle; + QLibrary* m_handle; + QPtrList<QObject> m_objs; + QTimer *m_timer; + KLibraryPrivate *d; +}; + +class KLibWrapPrivate; + +/** + * The KLibLoader allows you to load libraries dynamically at runtime. + * Dependent libraries are loaded automatically. + * + * KLibLoader follows the singleton pattern. You can not create multiple + * instances. Use @ref self() to get a pointer to the loader. + * + * @see KLibrary + * @author Torben Weis <weis@kde.org> + */ +class KLibLoader : public QObject +{ + friend class KLibrary; + + Q_OBJECT +public: + /** + * You should NEVER destruct an instance of KLibLoader + * until you know what you are doing. This will release + * the loaded libraries. + */ + ~KLibLoader(); + + /** + * Loads and initializes a library. Loading a library multiple times is + * handled gracefully. + * + * This is a convenience function that returns the factory immediately + * @param libname This is the library name without extension. Usually that is something like + * "libkspread". The function will then search for a file named + * "libkspread.la" in the KDE library paths. + * The *.la files are created by libtool and contain + * important information especially about the libraries dependencies + * on other shared libs. Loading a "libfoo.so" could not solve the + * dependencies problem. + * + * You can, however, give a library name ending in ".so" + * (or whatever is used on your platform), and the library + * will be loaded without resolving dependencies. USE WITH CARE :) + * @return the @ref KLibFactory, or 0 if the library does not exist or it does + * not have a factory + * @see #library + */ + KLibFactory* factory( const char* libname ); + + /** + * Loads and initializes a library. Loading a library multiple times is + * handled gracefully. + * + * @param libname This is the library name without extension. Usually that is something like + * "libkspread". The function will then search for a file named + * "libkspread.la" in the KDE library paths. + * The *.la files are created by libtool and contain + * important information especially about the libraries dependencies + * on other shared libs. Loading a "libfoo.so" could not solve the + * dependencies problem. + * + * You can, however, give a library name ending in ".so" + * (or whatever is used on your platform), and the library + * will be loaded without resolving dependencies. USE WITH CARE :) + * @return @ref KLibrary is invalid (0) when the library couldn't be dlopened. in such + * a case you can retrieve the error message by calling KLibLoader::lastErrorMessage() + * + * @see #factory + */ + virtual KLibrary* library( const char* libname ); + + /** + * Loads and initializes a library. Loading a library multiple times is + * handled gracefully. The library is loaded such that the symbols are + * globally accessible so libraries with dependencies can be loaded + * sequentially. + * + * @param name This is the library name without extension. Usually that is something like + * "libkspread". The function will then search for a file named + * "libkspread.la" in the KDE library paths. + * The *.la files are created by libtool and contain + * important information especially about the libraries dependencies + * on other shared libs. Loading a "libfoo.so" could not solve the + * dependencies problem. + * + * You can, however, give a library name ending in ".so" + * (or whatever is used on your platform), and the library + * will be loaded without resolving dependencies. USE WITH CARE :) + * @return KLibrariy is invalid (0) when the library couldn't be dlopened. in such + * a case you can retrieve the error message by calling KLibLoader::lastErrorMessage() + * + * @see #factory + */ + KLibrary* globalLibrary( const char *name ); + + /* + * Returns an error message that can be useful to debug the problem. + * Returns QString::null if the last call to @ref #library() was successful. + * You can call this function more than once. The error message is only + * reset by a new call to library(). + * @return the last error message, or QString::null if there was no error + */ + QString lastErrorMessage() const; + + /** + * Unloads the library with the given name. + * @param libname This is the library name without extension. Usually that is something like + * "libkspread". The function will then search for a file named + * "libkspread.la" in the KDE library paths. + * The *.la files are created by libtool and contain + * important information especially about the libraries dependencies + * on other shared libs. Loading a "libfoo.so" could not solve the + * dependencies problem. + * + * You can, however, give a library name ending in ".so" + * (or whatever is used on your platform), and the library + * will be loaded without resolving dependencies. USE WITH CARE :) + */ + virtual void unloadLibrary( const char *libname ); + + /** + * Returns a pointer to the factory. Use this function to get an instance + * of KLibLoader. + * @return a pointer to the loader. If no loader exists until now + * then one is created. + */ + static KLibLoader* self(); + + /** + * @internal + * Internal Method, called by the KApplication destructor. + * Do not call it. + * This is what makes it possible to rely on ~KLibFactory + * being called in all cases, whether the library is unloaded + * while the application is running or when exiting. + */ + static void cleanUp(); + + /** + * Helper method which looks for a library in the standard paths + * ("module" and "lib" resources). + * Made public for code that doesn't use KLibLoader itself, but still + * wants to open modules. + * @param name of the library. If it is not a path, the function searches in + * the "module" and "lib" resources. If there is no extension, + * ".la" will be appended. + * @param instance a KInstance used to get the standard paths + */ + static QString findLibrary( const char * name/*US , const KInstance * instance = KGlobal::instance()*/ ); + +protected: + KLibLoader( QObject* parent = 0, const char* name = 0 ); + +private slots: + void slotLibraryDestroyed(); +private: + void close_pending( KLibWrapPrivate * ); + QAsciiDict<KLibWrapPrivate> m_libs; + + static KLibLoader* s_self; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KLibLoaderPrivate *d; +}; + +/** + * If you develop a library that is to be loaded dynamically at runtime, then + * you should return a pointer to your factory. The K_EXPORT_COMPONENT_FACTORY + * macro is provided for this purpose: + * <pre> + * K_EXPORT_COMPONENT_FACTORY( libkspread, KSpreadFactory ) + * </pre> + * + * The first macro argument is the name of your library, the second specifies the name + * of your factory. + * + * In the constructor of your factory you should create an instance of @ref KInstance + * like this: + * <pre> + * s_global = new KInstance( "kspread" ); + * </pre> + * This @ref KInstance is comparable to @ref KGlobal used by normal applications. + * It allows you to find resource files (images, XML, sound etc.) belonging + * to the library. + * + * If you want to load a library, use @ref KLibLoader. You can query @ref KLibLoader + * directly for a pointer to the libraries factory by using the @ref KLibLoader::factory() + * function. + * + * The KLibFactory is used to create the components, the library has to offer. + * The factory of KSpread for example will create instances of KSpreadDoc, + * while the Konqueror factory will create KonqView widgets. + * All objects created by the factory must be derived from @ref QObject, since @ref QObject + * offers type safe casting. + * + * KLibFactory is an abstract class. Reimplement the @ref + * createObject() method to give it functionality. + * + * @author Torben Weis <weis@kde.org> + */ +class KLibFactory : public QObject +{ + Q_OBJECT +public: + /** + * Create a new factory. + * @param parent the parent of the QObject, 0 for no parent + * @param name the name of the QObject, 0 for no name + */ + KLibFactory( QObject* parent = 0, const char* name = 0 ); + virtual ~KLibFactory(); + + /** + * Creates a new object. The returned object has to be derived from + * the requested classname. + * + * It is valid behavior to create different kinds of objects + * depending on the requested @p classname. For example a koffice + * library may usually return a pointer to KoDocument. But + * if asked for a "QWidget", it could create a wrapper widget, + * that encapsulates the Koffice specific features. + * + * create() automatically emits a signal @ref objectCreated to tell + * the library about its newly created object. This is very + * important for reference counting, and allows unloading the + * library automatically once all its objects have been destroyed. + * + * @param parent the parent of the QObject, 0 for no parent + * @param name the name of the QObject, 0 for no name + * @param classname the name of the class + * @param args a list of arguments + */ + + QObject* create( QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList() ); + +signals: + /** + * Emitted in #create + * @param obj the new object + */ + void objectCreated( QObject *obj ); + + +protected: + + /** + * Creates a new object. The returned object has to be derived from + * the requested classname. + * + * It is valid behavior to create different kinds of objects + * depending on the requested @p classname. For example a koffice + * library may usually return a pointer to KoDocument. But + * if asked for a "QWidget", it could create a wrapper widget, + * that encapsulates the Koffice specific features. + * + * This function is called by #create() + * @param parent the parent of the QObject, 0 for no parent + * @param name the name of the QObject, 0 for no name + * @param classname the name of the class + * @param args a list of arguments + */ + virtual QObject* createObject( QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList() ) = 0; + + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KLibFactoryPrivate *d; +}; + +#endif diff --git a/microkde/kdecore/klocale.cpp b/microkde/kdecore/klocale.cpp new file mode 100644 index 0000000..d77e251 --- a/dev/null +++ b/microkde/kdecore/klocale.cpp @@ -0,0 +1,881 @@ +#include <qregexp.h> +#include <qapplication.h> + +#include "kdebug.h" +#include "kcalendarsystemgregorian.h" + +#include "klocale.h" + + +QDict<QString> *mLocaleDict = 0; +void setLocaleDict( QDict<QString> * dict ) +{ + mLocaleDict = dict; + +} +QString i18n(const char *text) +{ + if ( ! mLocaleDict ) + return QString( text ); + else { + QString* ret = mLocaleDict->find(QString(text)) ; + if ( ret == 0 ) { + return QString( text ); + } + else { + if ( (*ret).isEmpty() ) + return QString( text ); + else + return (*ret); + } + } + +} + +QString i18n(const char *,const char *text) +{ + return i18n( text ); +} + +QString i18n(const char *text1, const char *textn, int num) +{ + if ( num == 1 ) return i18n( text1 ); + else { + QString text = i18n( textn ); + int pos = text.find( "%n" ); + if ( pos >= 0 ) text.replace( pos, 2, QString::number( num ) ); + return text; + } +} + +inline void put_it_in( QChar *buffer, uint& index, const QString &s ) +{ + for ( uint l = 0; l < s.length(); l++ ) + buffer[index++] = s.at( l ); +} + +inline void put_it_in( QChar *buffer, uint& index, int number ) +{ + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; +} + +static int readInt(const QString &str, uint &pos) +{ + if (!str.at(pos).isDigit()) return -1; + int result = 0; + for (; str.length() > pos && str.at(pos).isDigit(); pos++) + { + result *= 10; + result += str.at(pos).digitValue(); + } + + return result; +} + +KLocale::KLocale() : mCalendarSystem( 0 ) +{ + + m_decimalSymbol = "."; + m_positiveSign = ""; + m_negativeSign = "-"; + m_thousandsSeparator = ","; + + + + + mWeekStartsMonday = true; + mHourF24Format = true; + mIntDateFormat = 0; + mLanguage = 0; + mDateFormat = "%a %Y %b %d"; + mDateFormatShort = "%Y-%m-%d"; + mTimeZoneList << i18n ("-11:00 US/Samoa") + << i18n ("-10:00 US/Hawaii") + << i18n ("-09:00 US/Alaska") + << i18n ("-08:00 US/Pacific") + << i18n ("-07:00 US/Mountain") + << i18n ("-06:00 US/Central") + << i18n ("-05:00 US/Eastern") + << i18n ("-04:00 Brazil/West") + << i18n ("-03:00 Brazil/East") + << i18n ("-02:00 Brazil/DeNoronha") + << i18n ("-01:00 Atlantic/Azores") + << i18n (" 00:00 Europe/London(UTC)") + << i18n ("+01:00 Europe/Oslo(CET)") + << i18n ("+02:00 Europe/Helsinki") + << i18n ("+03:00 Europe/Moscow") + << i18n ("+04:00 Indian/Mauritius") + << i18n ("+05:00 Indian/Maldives") + << i18n ("+06:00 Indian/Chagos") + << i18n ("+07:00 Asia/Bangkok") + << i18n ("+08:00 Asia/Hongkong") + << i18n ("+09:00 Asia/Tokyo") + << i18n ("+10:00 Asia/Vladivostok") + << i18n ("+11:00 Asia/Magadan") + << i18n ("+12:00 Asia/Kamchatka") + // << i18n (" xx:xx User defined offset") + << i18n (" Local Time"); + mSouthDaylight = false; + mTimeZoneOffset = 0; + daylightEnabled = false; +} + +void KLocale::setDateFormat( QString s ) +{ + mDateFormat = s; +} + +void KLocale::setDateFormatShort( QString s ) +{ + mDateFormatShort = s; +} + +void KLocale::setHore24Format ( bool b ) +{ + mHourF24Format = b; +} +void KLocale::setWeekStartMonday( bool b ) +{ + mWeekStartsMonday = b; +} +int KLocale::getIntDateFormat( ) +{ + return mIntDateFormat ; + +} +void KLocale::setIntDateFormat( int i ) +{ + mIntDateFormat = i; +} +void KLocale::setLanguage( int i ) +{ + mLanguage = i; +} +QString KLocale::translate( const char *index ) const +{ + return i18n( index ); +} + +QString KLocale::translate( const char *, const char *fallback) const +{ + return i18n( fallback ); +} + +QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const +{ + const QString rst = timeFormat(); + + // only "pm/am" here can grow, the rest shrinks, but + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 30]; + + uint index = 0; + bool escape = false; + int number = 0; + + for ( uint format_index = 0; format_index < rst.length(); format_index++ ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'H': + put_it_in( buffer, index, pTime.hour() ); + break; + case 'I': + put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 ); + break; + case 'M': + put_it_in( buffer, index, pTime.minute() ); + break; + case 'S': + if (includeSecs) + put_it_in( buffer, index, pTime.second() ); + else + { + // we remove the seperator sign before the seconds and + // assume that works everywhere + --index; + break; + } + break; + case 'k': + number = pTime.hour(); + case 'l': + // to share the code + if ( rst.at( format_index ).unicode() == 'l' ) + number = (pTime.hour() + 11) % 12 + 1; + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'p': + { + QString s; + if ( pTime.hour() >= 12 ) + put_it_in( buffer, index, i18n("pm") ); + else + put_it_in( buffer, index, i18n("am") ); + break; + } + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const +{ + const QString rst = shortFormat?dateFormatShort():dateFormat(); + + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 50]; + + unsigned int index = 0; + bool escape = false; + int number = 0; + + for ( uint format_index = 0; format_index < rst.length(); ++format_index ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'Y': + put_it_in( buffer, index, pDate.year() / 100 ); + case 'y': + put_it_in( buffer, index, pDate.year() % 100 ); + break; + case 'n': + number = pDate.month(); + case 'e': + // to share the code + if ( rst.at( format_index ).unicode() == 'e' ) + number = pDate.day(); + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'm': + put_it_in( buffer, index, pDate.month() ); + break; + case 'b': + put_it_in( buffer, index, monthName(pDate.month(), true) ); + break; + case 'B': + put_it_in( buffer, index, monthName(pDate.month(), false) ); + break; + case 'd': + put_it_in( buffer, index, pDate.day() ); + break; + case 'a': + put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), true) ); + break; + case 'A': + put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), false) ); + break; + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +QString KLocale::formatDateTime(const QDateTime &pDateTime, + bool shortFormat, + bool includeSeconds) const +{ + return QString( "%1 %2") + .arg( formatDate( pDateTime.date(), shortFormat ) ) + .arg( formatTime( pDateTime.time(), includeSeconds ) ); +} + +QString KLocale::formatDateTime(const QDateTime &pDateTime) const +{ + return formatDateTime(pDateTime, true); +} + +QDate KLocale::readDate(const QString &intstr, bool* ok) const +{ + QDate date; + date = readDate(intstr, true, ok); + if (date.isValid()) return date; + return readDate(intstr, false, ok); +} + +QDate KLocale::readDate(const QString &intstr, bool shortFormat, bool* ok) const +{ + QString fmt = (shortFormat ? dateFormatShort() : dateFormat()).simplifyWhiteSpace(); + return readDate( intstr, fmt, ok ); +} + +QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const +{ + //kdDebug(173) << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl; + QString str = intstr.simplifyWhiteSpace().lower(); + int day = -1, month = -1; + // allow the year to be omitted if not in the format + int year = QDate::currentDate().year(); + uint strpos = 0; + uint fmtpos = 0; + + while (fmt.length() > fmtpos || str.length() > strpos) + { + if ( !(fmt.length() > fmtpos && str.length() > strpos) ) + goto error; + + QChar c = fmt.at(fmtpos++); + + if (c != '%') { + if (c.isSpace()) + strpos++; + else if (c != str.at(strpos++)) + goto error; + continue; + } + + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = fmt.at(fmtpos++); + switch (c) + { + case 'a': + case 'A': + // this will just be ignored + { // Cristian Tache: porting to Win: Block added because of "j" redefinition + for (int j = 1; j < 8; j++) { + QString s = weekDayName(j, c == 'a').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + strpos += len; + } + break; + } + case 'b': + case 'B': + { // Cristian Tache: porting to Win: Block added because of "j" redefinition + for (int j = 1; j < 13; j++) { + QString s = monthName(j, c == 'b').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) { + month = j; + strpos += len; + } + } + break; + } + case 'd': + case 'e': + day = readInt(str, strpos); + if (day < 1 || day > 31) + goto error; + + break; + + case 'n': + case 'm': + month = readInt(str, strpos); + if (month < 1 || month > 12) + goto error; + + break; + + case 'Y': + case 'y': + year = readInt(str, strpos); + if (year < 0) + goto error; + // Qt treats a year in the range 0-100 as 1900-1999. + // It is nicer for the user if we treat 0-68 as 2000-2068 + if (year < 69) + year += 2000; + else if (c == 'y') + year += 1900; + + break; + } + } + //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl; + if ( year != -1 && month != -1 && day != -1 ) + { + if (ok) *ok = true; + return QDate(year, month, day); + } + error: + if (ok) *ok = false; + return QDate(); // invalid date +} + +QTime KLocale::readTime(const QString &intstr, bool *ok) const +{ + QTime _time; + _time = readTime(intstr, true, ok); + if (_time.isValid()) return _time; + return readTime(intstr, false, ok); +} + +QTime KLocale::readTime(const QString &intstr, bool seconds, bool *ok) const +{ + QString str = intstr.simplifyWhiteSpace().lower(); + QString Format = timeFormat().simplifyWhiteSpace(); + if (!seconds) + Format.replace(QRegExp(QString::fromLatin1(".%S")), QString::null); + + int hour = -1, minute = -1, second = seconds ? -1 : 0; // don't require seconds + bool g_12h = false; + bool pm = false; + uint strpos = 0; + uint Formatpos = 0; + + while (Format.length() > Formatpos || str.length() > strpos) + { + if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error; + + QChar c = Format.at(Formatpos++); + + if (c != '%') + { + if (c.isSpace()) + strpos++; + else if (c != str.at(strpos++)) + goto error; + continue; + } + + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = Format.at(Formatpos++); + switch (c) + { + case 'p': + { + QString s; + s = i18n("pm").lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + { + pm = true; + strpos += len; + } + else + { + s = i18n("am").lower(); + len = s.length(); + if (str.mid(strpos, len) == s) { + pm = false; + strpos += len; + } + else + goto error; + } + } + break; + + case 'k': + case 'H': + g_12h = false; + hour = readInt(str, strpos); + if (hour < 0 || hour > 23) + goto error; + + break; + + case 'l': + case 'I': + g_12h = true; + hour = readInt(str, strpos); + if (hour < 1 || hour > 12) + goto error; + + break; + + case 'M': + minute = readInt(str, strpos); + if (minute < 0 || minute > 59) + goto error; + + break; + + case 'S': + second = readInt(str, strpos); + if (second < 0 || second > 59) + goto error; + + break; + } + } + if (g_12h) + { + hour %= 12; + if (pm) hour += 12; + } + + if (ok) *ok = true; + return QTime(hour, minute, second); + + error: + if (ok) *ok = false; + return QTime(-1, -1, -1); // return invalid date if it didn't work + // This will be removed in the near future, since it gives a warning on stderr. + // The presence of the bool* (since KDE-3.0) removes the need for an invalid QTime. +} + +bool KLocale::use12Clock() const +{ + return !mHourF24Format ;; +} + +bool KLocale::weekStartsMonday() const +{ + return mWeekStartsMonday; +} + +int KLocale::weekStartDay() const +{ + if ( mWeekStartsMonday ) + return 1; + return 7; +} + +QString KLocale::weekDayName(int i,bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return i18n("Monday", "Mon"); + case 2: return i18n("Tuesday", "Tue"); + case 3: return i18n("Wednesday", "Wed"); + case 4: return i18n("Thursday", "Thu"); + case 5: return i18n("Friday", "Fri"); + case 6: return i18n("Saturday", "Sat"); + case 7: return i18n("Sunday", "Sun"); + } + else + switch ( i ) + { + case 1: return i18n("Monday"); + case 2: return i18n("Tuesday"); + case 3: return i18n("Wednesday"); + case 4: return i18n("Thursday"); + case 5: return i18n("Friday"); + case 6: return i18n("Saturday"); + case 7: return i18n("Sunday"); + } + + return QString::null; +} + +QString KLocale::monthName(int i,bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return i18n("January", "Jan"); + case 2: return i18n("February", "Feb"); + case 3: return i18n("March", "Mar"); + case 4: return i18n("April", "Apr"); + case 5: return i18n("May short", "May"); + case 6: return i18n("June", "Jun"); + case 7: return i18n("July", "Jul"); + case 8: return i18n("August", "Aug"); + case 9: return i18n("September", "Sep"); + case 10: return i18n("October", "Oct"); + case 11: return i18n("November", "Nov"); + case 12: return i18n("December", "Dec"); + } + else + switch (i) + { + case 1: return i18n("January"); + case 2: return i18n("February"); + case 3: return i18n("March"); + case 4: return i18n("April"); + case 5: return i18n("May long", "May"); + case 6: return i18n("June"); + case 7: return i18n("July"); + case 8: return i18n("August"); + case 9: return i18n("September"); + case 10: return i18n("October"); + case 11: return i18n("November"); + case 12: return i18n("December"); + } + + return QString::null; +} + +QString KLocale::country() const +{ + return QString::null; +} + +QString KLocale::dateFormat() const +{ + if ( QApplication::desktop()->width() < 480 ) { + if ( mIntDateFormat == 0 ) + return "%a %d %b %Y"; + else if ( mIntDateFormat == 1 ) + return "%a %b %d %Y"; + else if ( mIntDateFormat == 2 ) + return "%a %Y %b %d"; + } else { + + if ( mIntDateFormat == 0 ) + return "%A %d %B %Y"; + else if ( mIntDateFormat == 1 ) + return "%A %B %d %Y"; + else if ( mIntDateFormat == 2 ) + return "%A %Y %B %d"; + } + return mDateFormat ; +} + +QString KLocale::dateFormatShort() const +{ + + if ( mIntDateFormat == 0 ) + return "%d.%m.%Y"; + else if ( mIntDateFormat == 1 ) + return "%m.%d.%Y"; + else if ( mIntDateFormat == 2 ) + return "%Y-%m-%d"; + return mDateFormatShort ; + +} + + +QString KLocale::timeFormat() const +{ + if ( mHourF24Format) + return "%H:%M:%S"; + return "%I:%M:%S%p"; +} + +void KLocale::insertCatalogue ( const QString & ) +{ +} + +KCalendarSystem *KLocale::calendar() +{ + if ( !mCalendarSystem ) { + mCalendarSystem = new KCalendarSystemGregorian; + } + + return mCalendarSystem; +} + +int KLocale::timezoneOffset( QString timeZone ) +{ + int ret = 1001; + int index = mTimeZoneList.findIndex( timeZone ); + if ( index < 24 ) + ret = ( index-11 ) * 60 ; + return ret; +} + +QStringList KLocale::timeZoneList() const +{ + return mTimeZoneList; +} +void KLocale::setTimezone( const QString &timeZone ) +{ + mTimeZoneOffset = timezoneOffset( timeZone ); +} + +void KLocale::setDaylightSaving( bool b, int start , int end ) +{ + daylightEnabled = b; + daylightStart = start; + daylightEnd = end; + mSouthDaylight = (end < start); + // qDebug("klocale daylight %d %d %d ", b, start , end ); +} + +int KLocale::localTimeOffset( const QDateTime &dt ) +{ + bool addDaylight = false; + if ( daylightEnabled ) { + int d_end, d_start; + int dayofyear = dt.date().dayOfYear(); + int year = dt.date().year(); + int add = 0; + if ( QDate::leapYear(year) ) + add = 1; + QDate date ( year,1,1 ); + if ( daylightEnd > 59 ) + d_end = daylightEnd +add; + else + d_end = daylightEnd; + if ( daylightStart > 59 ) + d_start = daylightStart +add; + else + d_start = daylightStart; + QDate s_date = date.addDays( d_start -1 ); + QDate e_date = date.addDays( d_end -1 ); + int dof = s_date.dayOfWeek(); + if ( dof < 7 ) + s_date = s_date.addDays( -dof ); + dof = e_date.dayOfWeek(); + if ( dof < 7 ) + e_date = e_date.addDays( -dof ); + QTime startTime ( 3,0,0 ); + QDateTime startDt( s_date, startTime ); + QDateTime endDt( e_date, startTime ); + //qDebug("dayligt saving start %s end %s ",startDt.toString().latin1(),endDt.toString().latin1( )); + if ( mSouthDaylight ) { + if ( ! ( endDt < dt && dt < startDt) ) + addDaylight = true; + } else { + if ( startDt < dt && dt < endDt ) + addDaylight = true; + + + } + } + int addMin = 0; + if ( addDaylight ) + addMin = 60; + return mTimeZoneOffset + addMin; +} +// ****************************************************************** +// added LR +QString KLocale::formatNumber(double num, int precision) const +{ + bool neg = num < 0; + if (precision == -1) precision = 2; + QString res = QString::number(neg?-num:num, 'f', precision); + int pos = res.find('.'); + if (pos == -1) pos = res.length(); + else res.replace(pos, 1, decimalSymbol()); + + while (0 < (pos -= 3)) + res.insert(pos, thousandsSeparator()); // thousand sep + + // How can we know where we should put the sign? + res.prepend(neg?negativeSign():positiveSign()); + + return res; +} +QString KLocale::formatNumber(const QString &numStr) const +{ + return formatNumber(numStr.toDouble()); +} +double KLocale::readNumber(const QString &_str, bool * ok) const +{ + QString str = _str.stripWhiteSpace(); + bool neg = str.find(negativeSign()) == 0; + if (neg) + str.remove( 0, negativeSign().length() ); + + /* will hold the scientific notation portion of the number. + Example, with 2.34E+23, exponentialPart == "E+23" + */ + QString exponentialPart; + int EPos; + + EPos = str.find('E', 0, false); + + if (EPos != -1) + { + exponentialPart = str.mid(EPos); + str = str.left(EPos); + } + + int pos = str.find(decimalSymbol()); + QString major; + QString minor; + if ( pos == -1 ) + major = str; + else + { + major = str.left(pos); + minor = str.mid(pos + decimalSymbol().length()); + } + + // Remove thousand separators + int thlen = thousandsSeparator().length(); + int lastpos = 0; + while ( ( pos = major.find( thousandsSeparator() ) ) > 0 ) + { + // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N + int fromEnd = major.length() - pos; + if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error + || pos - lastpos > 3 // More than 3 digits between two separators -> error + || pos == 0 // Can't start with a separator + || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators + { + if (ok) *ok = false; + return 0.0; + } + + lastpos = pos; + major.remove( pos, thlen ); + } + if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator + { + if (ok) *ok = false; + return 0.0; + } + + QString tot; + if (neg) tot = '-'; + + tot += major + '.' + minor + exponentialPart; + + return tot.toDouble(ok); +} +QString KLocale::decimalSymbol() const +{ + + return m_decimalSymbol; +} + +QString KLocale::thousandsSeparator() const +{ + + return m_thousandsSeparator; +} +QString KLocale::positiveSign() const +{ + return m_positiveSign; +} + +QString KLocale::negativeSign() const +{ + return m_negativeSign; +} diff --git a/microkde/kdecore/klocale.h b/microkde/kdecore/klocale.h new file mode 100644 index 0000000..7470cd2 --- a/dev/null +++ b/microkde/kdecore/klocale.h @@ -0,0 +1,110 @@ +#ifndef MINIKDE_KLOCALE_H +#define MINIKDE_KLOCALE_H + +#include <qstring.h> +#include <qstringlist.h> +#include <qdatetime.h> +#include <qdict.h> + +#ifndef I18N_NOOP +#define I18N_NOOP(x) (x) +#endif + +class KCalendarSystem; +void setLocaleDict( QDict<QString> * dict ); +QString i18n(const char *text); +QString i18n(const char *hint, const char *text); +QString i18n(const char *text1, const char *textn, int num); + +// Qt3's uic generates i18n( "msg", "comment" ) calls which conflict +// with our i18n method. we use uic -tr tr2i18n to redirect +// to the right i18n() function +inline QString tr2i18n(const char* message, const char* =0) { + return i18n( message); +} + +class KLocale +{ + public: + KLocale(); + + QString formatNumber(double num, int precision = -1) const; + QString formatNumber(const QString &numStr) const; + double readNumber(const QString &numStr, bool * ok = 0) const; + + QString decimalSymbol() const; + QString thousandsSeparator() const; + QString positiveSign() const; + QString negativeSign() const; + + + QString translate( const char *index ) const; + QString translate( const char *index, const char *fallback) const; + + QString formatDate(const QDate &pDate, bool shortFormat = false) const; + QString formatTime(const QTime &pTime, bool includeSecs = false) const; + QString formatDateTime(const QDateTime &pDateTime) const; + QString formatDateTime(const QDateTime &pDateTime, + bool shortFormat, + bool includeSecs = false) const; + + QDate readDate(const QString &str, bool* ok = 0) const; + QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const; + QTime readTime(const QString &str, bool* ok = 0) const; + + bool use12Clock() const; + bool weekStartsMonday() const; + int weekStartDay() const; + + QString weekDayName(int,bool=false) const; + QString monthName(int,bool=false) const; + + QString country() const; + + QString dateFormat() const; + QString dateFormatShort() const; + QString timeFormat() const; + + void insertCatalogue ( const QString & ); + + KCalendarSystem *calendar(); + void setHore24Format ( bool ); + void setWeekStartMonday( bool ); + void setIntDateFormat( int ); + int getIntDateFormat( ); + void setLanguage( int ); + void setDateFormat( QString ); + void setDateFormatShort( QString ); + + QString m_decimalSymbol; + QString m_thousandsSeparator; + QString m_currencySymbol; + QString m_monetaryDecimalSymbol; + QString m_monetaryThousandsSeparator; + QString m_positiveSign; + QString m_negativeSign; + + int timezoneOffset( QString ); + QStringList timeZoneList() const; + void setDaylightSaving( bool, int , int ); + int localTimeOffset(const QDateTime &); + void setTimezone( const QString &timeZone ); + private: + QTime readTime(const QString &str, bool seconds, bool *ok) const; + QDate readDate(const QString &str, bool shortFormat, bool *ok) const; + KCalendarSystem *mCalendarSystem; + bool mWeekStartsMonday; + bool mHourF24Format; + int mIntDateFormat; + int mLanguage; + QString mDateFormat; + QString mDateFormatShort; + QStringList mTimeZoneList; + bool daylightEnabled; + int mDaylightTZoffset; + int mNondaylightTZoffset; + bool mSouthDaylight; + int daylightStart, daylightEnd, mTimeZoneOffset; +}; + +#endif diff --git a/microkde/kdecore/klocale_new.cpp b/microkde/kdecore/klocale_new.cpp new file mode 100644 index 0000000..223b6c4 --- a/dev/null +++ b/microkde/kdecore/klocale_new.cpp @@ -0,0 +1,2441 @@ +// -*- c-basic-offset: 2 -*- +/* This file is part of the KDE libraries + Copyright (c) 1997,2001 Stephan Kulow <coolo@kde.org> + Copyright (c) 1999 Preston Brown <pbrown@kde.org> + Copyright (c) 1999-2002 Hans Petter Bieker <bieker@kde.org> + Copyright (c) 2002 Lukas Tinkl <lukas@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//US#include <config.h> + +#include <stdlib.h> // getenv +#include <assert.h> + +#include <qtextcodec.h> +#include <qfile.h> +#include <qdict.h> +#include <qprinter.h> +#include <qdatetime.h> +#include <qfileinfo.h> +#include <qregexp.h> + +#include "kcatalogue.h" +#include "kglobal.h" +#include "kstandarddirs.h" +#include "ksimpleconfig.h" +//US #include "kinstance.h" +#include "kconfig.h" +#include "kconfigbase.h" +#include "kdebug.h" +#include "kcalendarsystem.h" + +//US we use no factory. Simply use the gregorian calendar +//US #include "kcalendarsystemfactory.h" +#include "kcalendarsystemgregorian.h" + +#include "klocale.h" + +static const char * const SYSTEM_MESSAGES = "kdelibs"; + +static const char *maincatalogue = 0; + +QDict<char> *mLocaleDict = 0; + +void setLocaleDict( QDict<char> * dict ) +{ + mLocaleDict = dict; + +} + +class KLocalePrivate +{ +public: + int weekStartDay; + int plural_form; + bool nounDeclension; + bool dateMonthNamePossessive; + QStringList languageList; + QValueList<KCatalogue> catalogues; + QString encoding; + QTextCodec * codecForEncoding; + KConfig * config; + bool formatInited; + int /*QPrinter::PageSize*/ pageSize; + KLocale::MeasureSystem measureSystem; + QStringList langTwoAlpha; + KConfig *languages; + + QString calendarType; + KCalendarSystem * calendar; + QString first_language; + bool utf8FileEncoding; +}; + +static KLocale *this_klocale = 0; + +KLocale::KLocale( const QString & catalogue, KConfig * config ) +{ + d = new KLocalePrivate; + d->config = config; + d->languages = 0; + d->calendar = 0; + + initCatalogue(catalogue); + initEncoding(0); + initFileNameEncoding(0); + + KConfig *cfg = d->config; + this_klocale = this; +//US if (!cfg) cfg = KGlobal::instance()->config(); + if (!cfg) cfg = KGlobal::config(); + this_klocale = 0; +//US Q_ASSERT( cfg ); + ASSERT( cfg ); + + if (m_language.isEmpty()) + initLanguage(cfg, config == 0); + + +/*US +//US mDateFormat = "%a %Y %b %d"; +//US mDateFormatShort = "%Y-%m-%d"; + mTimeZoneList << i18n ("-11:00 US/Samoa") + << i18n ("-10:00 US/Hawaii") + << i18n ("-09:00 US/Alaska") + << i18n ("-08:00 US/Pacific") + << i18n ("-07:00 US/Mountain") + << i18n ("-06:00 US/Central") + << i18n ("-05:00 US/Eastern") + << i18n ("-04:00 Brazil/West") + << i18n ("-03:00 Brazil/East") + << i18n ("-02:00 Brazil/DeNoronha") + << i18n ("-01:00 Atlantic/Azores") + << i18n (" 00:00 Europe/London(UTC)") + << i18n ("+01:00 Europe/Oslo(CET)") + << i18n ("+02:00 Europe/Helsinki") + << i18n ("+03:00 Europe/Moscow") + << i18n ("+04:00 Indian/Mauritius") + << i18n ("+05:00 Indian/Maldives") + << i18n ("+06:00 Indian/Chagos") + << i18n ("+07:00 Asia/Bangkok") + << i18n ("+08:00 Asia/Hongkong") + << i18n ("+09:00 Asia/Tokyo") + << i18n ("+10:00 Asia/Vladivostok") + << i18n ("+11:00 Asia/Magadan") + << i18n ("+12:00 Asia/Kamchatka") + // << i18n (" xx:xx User defined offset") + << i18n (" Local Time"); +*/ + mTimeZoneList << "-11:00 US/Samoa" + << "-10:00 US/Hawaii" + << "-09:00 US/Alaska" + << "-08:00 US/Pacific" + << "-07:00 US/Mountain" + << "-06:00 US/Central" + << "-05:00 US/Eastern" + << "-04:00 Brazil/West" + << "-03:00 Brazil/East" + << "-02:00 Brazil/DeNoronha" + << "-01:00 Atlantic/Azores" + << " 00:00 Europe/London(UTC)" + << "+01:00 Europe/Oslo(CET)" + << "+02:00 Europe/Helsinki" + << "+03:00 Europe/Moscow" + << "+04:00 Indian/Mauritius" + << "+05:00 Indian/Maldives" + << "+06:00 Indian/Chagos" + << "+07:00 Asia/Bangkok" + << "+08:00 Asia/Hongkong" + << "+09:00 Asia/Tokyo" + << "+10:00 Asia/Vladivostok" + << "+11:00 Asia/Magadan" + << "+12:00 Asia/Kamchatka" + // << " xx:xx User defined offset" + << " Local Time"; + + mSouthDaylight = false; + mTimeZoneOffset = 0; + daylightEnabled = false; + + mWeekStartsMonday = true; + mHourF24Format = true; + mIntDateFormat = 0; + mLanguage = 0; + +} + + +QString KLocale::_initLanguage(KConfigBase *config) +{ + if (this_klocale) + { + // ### HPB Why this cast?? + this_klocale->initLanguage((KConfig *) config, true); + return this_klocale->language(); + } + return QString::null; +} + +void KLocale::initCatalogue(const QString & catalogue) +{ + // Use the first non-null string. + QString mainCatalogue = catalogue; + if (maincatalogue) + mainCatalogue = QString::fromLatin1(maincatalogue); + + if (mainCatalogue.isEmpty()) { + kdDebug(173) << "KLocale instance created called without valid " + << "catalogue! Give an argument or call setMainCatalogue " + << "before init" << endl; + } + else + d->catalogues.append( KCatalogue(mainCatalogue ) ); + + // always include kdelibs.mo + d->catalogues.append( KCatalogue( SYSTEM_MESSAGES ) ); +} + +void KLocale::initLanguage(KConfig * config, bool useEnv) +{ + KConfigGroupSaver saver(config, "Locale"); + + m_country = config->readEntry( "Country" ); + if ( m_country.isEmpty() ) + m_country = defaultCountry(); + + // Reset the list and add the new languages + QStringList languageList; + if ( useEnv ) + languageList += QStringList::split + (':', QFile::decodeName( ::getenv("KDE_LANG") )); + +//US languageList += config->readListEntry("Language", ':'); + languageList += config->readListEntry("Language"); + + // same order as setlocale use + if ( useEnv ) + { + // HPB: Only run splitLocale on the environment variables.. + QStringList langs; + + langs << QFile::decodeName( ::getenv("LC_ALL") ); + langs << QFile::decodeName( ::getenv("LC_MESSAGES") ); + langs << QFile::decodeName( ::getenv("LANG") ); + langs << QFile::decodeName( ::getenv("LC_CTYPE") ); + + for ( QStringList::Iterator it = langs.begin(); + it != langs.end(); + ++it ) + { + QString ln, ct, chrset; + splitLocale(*it, ln, ct, chrset); + + if (!ct.isEmpty()) { + langs.insert(it, ln + '_' + ct); + if (!chrset.isEmpty()) + langs.insert(it, ln + '_' + ct + '.' + chrset); + } + + langs.insert(it, ln); + } + + languageList += langs; + } + + // now we have a language list -- let's use the first OK language + setLanguage( languageList ); +} + +void KLocale::doBindInit() +{ + return; // LR + for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin(); + it != d->catalogues.end(); + ++it ) + initCatalogue( *it ); + + if ( useDefaultLanguage() ) + d->plural_form = -1; + else + { + QString pf = translate_priv + ( I18N_NOOP("_: Dear translator, please do not translate this string " + "in any form, but pick the _right_ value out of " + "NoPlural/TwoForms/French... If not sure what to do mail " + "thd@kde.org and coolo@kde.org, they will tell you. " + "Better leave that out if unsure, the programs will " + "crash!!\nDefinition of PluralForm - to be set by the " + "translator of kdelibs.po"), 0); + if ( pf.isEmpty() ) { + kdWarning(173) << "found no definition of PluralForm for " << m_language << endl; + d->plural_form = -1; + } else if ( pf == "NoPlural" ) + d->plural_form = 0; + else if ( pf == "TwoForms" ) + d->plural_form = 1; + else if ( pf == "French" ) + d->plural_form = 2; + else if ( pf == "OneTwoRest" || pf == "Gaeilge" ) // Gaelige is the old name + d->plural_form = 3; + else if ( pf == "Russian" ) + d->plural_form = 4; + else if ( pf == "Polish" ) + d->plural_form = 5; + else if ( pf == "Slovenian" ) + d->plural_form = 6; + else if ( pf == "Lithuanian" ) + d->plural_form = 7; + else if ( pf == "Czech" ) + d->plural_form = 8; + else if ( pf == "Slovak" ) + d->plural_form = 9; + else if ( pf == "Maltese" ) + d->plural_form = 10; + else if ( pf == "Arabic" ) + d->plural_form = 11; + else if ( pf == "Balcan" ) + d->plural_form = 12; + else { + kdWarning(173) << "Definition of PluralForm is none of " + << "NoPlural/" + << "TwoForms/" + << "French/" + << "OneTwoRest/" + << "Russian/" + << "Polish/" + << "Slovenian/" + << "Lithuanian/" + << "Czech/" + << "Slovak/" + << "Arabic/" + << "Balcan/" + << "Maltese: " << pf << endl; + exit(1); + } + } + + d->formatInited = false; +} + +void KLocale::doFormatInit() const +{ + if ( d->formatInited ) return; + + KLocale * that = const_cast<KLocale *>(this); + that->initFormat(); + + d->formatInited = true; +} + +void KLocale::initFormat() +{ + KConfig *config = d->config; +//US if (!config) config = KGlobal::instance()->config(); + if (!config) config = KGlobal::config(); + ASSERT( config ); + + kdDebug(173) << "KLocale::initFormat" << endl; + + // make sure the config files are read using the correct locale + // ### Why not add a KConfigBase::setLocale( const KLocale * )? + // ### Then we could remove this hack +//US +//US KLocale *lsave = KGlobal::_locale; +//US KGlobal::_locale = this; + KLocale *lsave = KGlobal::locale(); + KGlobal::setLocale(this); + + KConfigGroupSaver saver(config, "Locale"); + + + +//US in kabc/adress.cpp we have a similar setup. Check there in case of problems + KSimpleConfig entry(locateLocal("locale", + QString::fromLatin1("l10n/%1/entry.desktop") + .arg(m_country)) ); + + entry.setGroup("KCM Locale"); + + // Numeric +#define readConfigEntry(key, default, save) \ + save = entry.readEntry(key, QString::fromLatin1(default)); \ + save = config->readEntry(key, save); + +#define readConfigNumEntry(key, default, save, type) \ + save = (type)entry.readNumEntry(key, default); \ + save = (type)config->readNumEntry(key, save); + +#define readConfigBoolEntry(key, default, save) \ + save = entry.readBoolEntry(key, default); \ + save = config->readBoolEntry(key, save); + + readConfigEntry("DecimalSymbol", ".", m_decimalSymbol); + readConfigEntry("ThousandsSeparator", ",", m_thousandsSeparator); + m_thousandsSeparator.replace( QString::fromLatin1("$0"), QString::null ); + //kdDebug(173) << "m_thousandsSeparator=" << m_thousandsSeparator << endl; + + readConfigEntry("PositiveSign", "", m_positiveSign); + readConfigEntry("NegativeSign", "-", m_negativeSign); + + // Monetary + readConfigEntry("CurrencySymbol", "$", m_currencySymbol); + readConfigEntry("MonetaryDecimalSymbol", ".", m_monetaryDecimalSymbol); + readConfigEntry("MonetaryThousandsSeparator", ",", + m_monetaryThousandsSeparator); + m_monetaryThousandsSeparator.replace(QString::fromLatin1("$0"), QString::null); + + readConfigNumEntry("FracDigits", 2, m_fracDigits, int); + readConfigBoolEntry("PositivePrefixCurrencySymbol", true, + m_positivePrefixCurrencySymbol); + readConfigBoolEntry("NegativePrefixCurrencySymbol", true, + m_negativePrefixCurrencySymbol); + readConfigNumEntry("PositiveMonetarySignPosition", (int)BeforeQuantityMoney, + m_positiveMonetarySignPosition, SignPosition); + readConfigNumEntry("NegativeMonetarySignPosition", (int)ParensAround, + m_negativeMonetarySignPosition, SignPosition); + + //Grammatical + readConfigBoolEntry("NounDeclension", false, d->nounDeclension); + + // Date and time + readConfigEntry("TimeFormat", "%H:%M:%S", m_timeFormat); + readConfigEntry("DateFormat", "%A %d %B %Y", m_dateFormat); + readConfigEntry("DateFormatShort", "%Y-%m-%d", m_dateFormatShort); + readConfigBoolEntry("DateMonthNamePossessive", false, + d->dateMonthNamePossessive); + readConfigNumEntry("WeekStartDay", 1, d->weekStartDay, int); + + // other +//US readConfigNumEntry("PageSize", (int)QPrinter::A4, d->pageSize, int); + readConfigNumEntry("MeasureSystem", (int)Metric, d->measureSystem, + MeasureSystem); + readConfigEntry("CalendarSystem", "gregorian", d->calendarType); + delete d->calendar; + d->calendar = 0; // ### HPB Is this the correct place? + + // end of hack +//US KGlobal::_locale = lsave; + KGlobal::setLocale(lsave); +} + +bool KLocale::setCountry(const QString & country) +{ + // Check if the file exists too?? + if ( country.isEmpty() ) + return false; + + m_country = country; + + d->formatInited = false; + + return true; +} + +QString KLocale::catalogueFileName(const QString & language, + const KCatalogue & catalogue) +{ + QString path = QString::fromLatin1("%1/LC_MESSAGES/%2.mo") + .arg( language ) + .arg( catalogue.name() ); + + return locate( "locale", path ); +} + +bool KLocale::isLanguageInstalled(const QString & language) const +{ + // Do not allow empty languages + if ( language.isEmpty() ) return false; + + bool bRes = true; + if ( language != defaultLanguage() ) + for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin(); + it != d->catalogues.end() && bRes; + ++it ) + { + bRes = !catalogueFileName( language, *it ).isNull(); + if ( !bRes ) + kdDebug(173) << "message catalogue not found: " + << (*it).name() << endl; + } + + return bRes; +} + +bool KLocale::setLanguage(const QString & language) +{ + bool bRes = true; + + if (d->first_language.isNull() || language != d->first_language) + bRes = isLanguageInstalled( language ); + + if ( bRes ) + { + m_language = language; + + // remember our first time - it will be our true love + if (d->first_language.isNull()) + d->first_language = language; + + doBindInit(); + } + + return bRes; +} + +bool KLocale::setLanguage(const QStringList & languages) +{ + QStringList languageList(languages); + + // Remove duplicate entries in reverse so that we + // can keep user's language preference order intact. (DA) + for( QStringList::Iterator it = languageList.fromLast(); + it != languageList.begin(); + --it ) + if ( languageList.contains(*it) > 1 || (*it).isEmpty() ) + it = languageList.remove( it ); + + bool bRes = false; + for ( QStringList::ConstIterator it = languageList.begin(); + it != languageList.end(); + ++it ) + if ( bRes = setLanguage( *it ) ) + break; + + if ( !bRes ) + setLanguage(defaultLanguage()); + + d->languageList = languageList; + d->langTwoAlpha.clear(); // Flush cache + + return bRes; +} + +void KLocale::splitLocale(const QString & aStr, + QString & language, + QString & country, + QString & chrset) +{ + QString str = aStr; + + // just in case, there is another language appended + int f = str.find(':'); + if (f >= 0) + str.truncate(f); + + country = QString::null; + chrset = QString::null; + language = QString::null; + + f = str.find('.'); + if (f >= 0) + { + chrset = str.mid(f + 1); + str.truncate(f); + } + + f = str.find('_'); + if (f >= 0) + { + country = str.mid(f + 1); + str.truncate(f); + } + + language = str; +} + +QString KLocale::language() const +{ + return m_language; +} + +QString KLocale::country() const +{ + return m_country; +} + +QString KLocale::monthName(int i, bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return translate("January", "Jan"); + case 2: return translate("February", "Feb"); + case 3: return translate("March", "Mar"); + case 4: return translate("April", "Apr"); + case 5: return translate("May short", "May"); + case 6: return translate("June", "Jun"); + case 7: return translate("July", "Jul"); + case 8: return translate("August", "Aug"); + case 9: return translate("September", "Sep"); + case 10: return translate("October", "Oct"); + case 11: return translate("November", "Nov"); + case 12: return translate("December", "Dec"); + } + else + switch (i) + { + case 1: return translate("January"); + case 2: return translate("February"); + case 3: return translate("March"); + case 4: return translate("April"); + case 5: return translate("May long", "May"); + case 6: return translate("June"); + case 7: return translate("July"); + case 8: return translate("August"); + case 9: return translate("September"); + case 10: return translate("October"); + case 11: return translate("November"); + case 12: return translate("December"); + } + + return QString::null; +} + +QString KLocale::monthNamePossessive(int i, bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return translate("of January", "of Jan"); + case 2: return translate("of February", "of Feb"); + case 3: return translate("of March", "of Mar"); + case 4: return translate("of April", "of Apr"); + case 5: return translate("of May short", "of May"); + case 6: return translate("of June", "of Jun"); + case 7: return translate("of July", "of Jul"); + case 8: return translate("of August", "of Aug"); + case 9: return translate("of September", "of Sep"); + case 10: return translate("of October", "of Oct"); + case 11: return translate("of November", "of Nov"); + case 12: return translate("of December", "of Dec"); + } + else + switch (i) + { + case 1: return translate("of January"); + case 2: return translate("of February"); + case 3: return translate("of March"); + case 4: return translate("of April"); + case 5: return translate("of May long", "of May"); + case 6: return translate("of June"); + case 7: return translate("of July"); + case 8: return translate("of August"); + case 9: return translate("of September"); + case 10: return translate("of October"); + case 11: return translate("of November"); + case 12: return translate("of December"); + } + + return QString::null; +} + +QString KLocale::weekDayName (int i, bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return translate("Monday", "Mon"); + case 2: return translate("Tuesday", "Tue"); + case 3: return translate("Wednesday", "Wed"); + case 4: return translate("Thursday", "Thu"); + case 5: return translate("Friday", "Fri"); + case 6: return translate("Saturday", "Sat"); + case 7: return translate("Sunday", "Sun"); + } + else + switch ( i ) + { + case 1: return translate("Monday"); + case 2: return translate("Tuesday"); + case 3: return translate("Wednesday"); + case 4: return translate("Thursday"); + case 5: return translate("Friday"); + case 6: return translate("Saturday"); + case 7: return translate("Sunday"); + } + + return QString::null; +} + +void KLocale::insertCatalogue( const QString & catalogue ) +{ + KCatalogue cat( catalogue ); + + initCatalogue( cat ); + + d->catalogues.append( cat ); +} + +void KLocale::removeCatalogue(const QString &catalogue) +{ + for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin(); + it != d->catalogues.end(); ) + if ((*it).name() == catalogue) { + it = d->catalogues.remove(it); + return; + } else + ++it; +} + +void KLocale::setActiveCatalogue(const QString &catalogue) +{ + for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin(); + it != d->catalogues.end(); ++it) + if ((*it).name() == catalogue) { + KCatalogue save = *it; + d->catalogues.remove(it); + d->catalogues.prepend(save); + return; + } +} + +KLocale::~KLocale() +{ + delete d->languages; + delete d; +} + +QString KLocale::translate_priv(const char *msgid, + const char *fallback, + const char **translated) const +{ + if (!msgid || !msgid[0]) + { + kdWarning() << "KLocale: trying to look up \"\" in catalogue. " + << "Fix the program" << endl; + return QString::null; + } + + if ( useDefaultLanguage() ) + return QString::fromUtf8( fallback ); + + for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin(); + it != d->catalogues.end(); + ++it ) + { + // kdDebug(173) << "translate " << msgid << " " << (*it).name() << " " << (!KGlobal::activeInstance() ? QCString("no instance") : KGlobal::activeInstance()->instanceName()) << endl; + const char * text = (*it).translate( msgid ); + + if ( text ) + { + // we found it + if (translated) + *translated = text; + return QString::fromUtf8( text ); + } + } + + // Always use UTF-8 if the string was not found + return QString::fromUtf8( fallback ); +} + +QString KLocale::translate(const char* msgid) const +{ + return translate_priv(msgid, msgid); +} + +QString KLocale::translate( const char *index, const char *fallback) const +{ + if (!index || !index[0] || !fallback || !fallback[0]) + { + kdDebug(173) << "KLocale: trying to look up \"\" in catalogue. " + << "Fix the program" << endl; + return QString::null; + } + + if ( useDefaultLanguage() ) + return QString::fromUtf8( fallback ); + + char *newstring = new char[strlen(index) + strlen(fallback) + 5]; + sprintf(newstring, "_: %s\n%s", index, fallback); + // as copying QString is very fast, it looks slower as it is ;/ + QString r = translate_priv(newstring, fallback); + delete [] newstring; + + return r; +} + +static QString put_n_in(const QString &orig, unsigned long n) +{ + QString ret = orig; + int index = ret.find("%n"); + if (index == -1) + return ret; + ret.replace(index, 2, QString::number(n)); + return ret; +} + +#define EXPECT_LENGTH(x) \ + if (forms.count() != x) { \ + kdError() << "translation of \"" << singular << "\" doesn't contain " << x << " different plural forms as expected\n"; \ + return QString( "BROKEN TRANSLATION %1" ).arg( singular ); } + +QString KLocale::translate( const char *singular, const char *plural, + unsigned long n ) const +{ + if (!singular || !singular[0] || !plural || !plural[0]) + { + kdWarning() << "KLocale: trying to look up \"\" in catalogue. " + << "Fix the program" << endl; + return QString::null; + } + + char *newstring = new char[strlen(singular) + strlen(plural) + 6]; + sprintf(newstring, "_n: %s\n%s", singular, plural); + // as copying QString is very fast, it looks slower as it is ;/ + QString r = translate_priv(newstring, 0); + delete [] newstring; + + if ( r.isEmpty() || useDefaultLanguage() || d->plural_form == -1) { + if ( n == 1 ) { + return put_n_in( QString::fromUtf8( singular ), n ); + } else { + QString tmp = QString::fromUtf8( plural ); +#ifndef NDEBUG + if (tmp.find("%n") == -1) { + kdWarning() << "the message for i18n should contain a '%n'! " << plural << endl; + } +#endif + return put_n_in( tmp, n ); + } + } + + QStringList forms = QStringList::split( "\n", r, false ); + switch ( d->plural_form ) { + case 0: // NoPlural + EXPECT_LENGTH( 1 ); + return put_n_in( forms[0], n); + case 1: // TwoForms + EXPECT_LENGTH( 2 ); + if ( n == 1 ) + return put_n_in( forms[0], n); + else + return put_n_in( forms[1], n); + case 2: // French + EXPECT_LENGTH( 2 ); + if ( n == 1 || n == 0 ) + return put_n_in( forms[0], n); + else + return put_n_in( forms[1], n); + case 3: // Gaeilge + EXPECT_LENGTH( 3 ); + if ( n == 1 ) + return put_n_in( forms[0], n); + else if ( n == 2 ) + return put_n_in( forms[1], n); + else + return put_n_in( forms[2], n); + case 4: // Russian, corrected by mok + EXPECT_LENGTH( 3 ); + if ( n%10 == 1 && n%100 != 11) + return put_n_in( forms[0], n); // odin fail + else if (( n%10 >= 2 && n%10 <=4 ) && (n%100<10 || n%100>20)) + return put_n_in( forms[1], n); // dva faila + else + return put_n_in( forms[2], n); // desyat' failov + case 5: // Polish + EXPECT_LENGTH( 3 ); + if ( n == 1 ) + return put_n_in( forms[0], n); + else if ( n%10 >= 2 && n%10 <=4 && (n%100<10 || n%100>=20) ) + return put_n_in( forms[1], n); + else + return put_n_in( forms[2], n); + case 6: // Slovenian + EXPECT_LENGTH( 4 ); + if ( n%100 == 1 ) + return put_n_in( forms[1], n); // ena datoteka + else if ( n%100 == 2 ) + return put_n_in( forms[2], n); // dve datoteki + else if ( n%100 == 3 || n%100 == 4 ) + return put_n_in( forms[3], n); // tri datoteke + else + return put_n_in( forms[0], n); // sto datotek + case 7: // Lithuanian + EXPECT_LENGTH( 3 ); + if ( n%10 == 0 || (n%100>=11 && n%100<=19) ) + return put_n_in( forms[2], n); + else if ( n%10 == 1 ) + return put_n_in( forms[0], n); + else + return put_n_in( forms[1], n); + case 8: // Czech + EXPECT_LENGTH( 3 ); + if ( n%100 == 1 ) + return put_n_in( forms[0], n); + else if (( n%100 >= 2 ) && ( n%100 <= 4 )) + return put_n_in( forms[1], n); + else + return put_n_in( forms[2], n); + case 9: // Slovak + EXPECT_LENGTH( 3 ); + if ( n == 1 ) + return put_n_in( forms[0], n); + else if (( n >= 2 ) && ( n <= 4 )) + return put_n_in( forms[1], n); + else + return put_n_in( forms[2], n); + case 10: // Maltese + EXPECT_LENGTH( 4 ); + if ( n == 1 ) + return put_n_in( forms[0], n ); + else if ( ( n == 0 ) || ( n%100 > 0 && n%100 <= 10 ) ) + return put_n_in( forms[1], n ); + else if ( n%100 > 10 && n%100 < 20 ) + return put_n_in( forms[2], n ); + else + return put_n_in( forms[3], n ); + case 11: // Arabic + EXPECT_LENGTH( 4 ); + if (n == 1) + return put_n_in(forms[0], n); + else if (n == 2) + return put_n_in(forms[1], n); + else if ( n < 11) + return put_n_in(forms[2], n); + else + return put_n_in(forms[3], n); + case 12: // Balcan + EXPECT_LENGTH( 3 ); + if (n != 11 && n % 10 == 1) + return put_n_in(forms[0], n); + else if (n / 10 != 1 && n % 10 >= 2 && n % 10 <= 4) + return put_n_in(forms[1], n); + else + return put_n_in(forms[2], n); + } + kdError() << "The function should have been returned in another way\n"; + + return QString::null; +} + +QString KLocale::translateQt( const char *context, const char *source, + const char *message) const +{ + if (!source || !source[0]) { + kdWarning() << "KLocale: trying to look up \"\" in catalogue. " + << "Fix the program" << endl; + return QString::null; + } + + if ( useDefaultLanguage() ) { + return QString::null; + } + + char *newstring = 0; + const char *translation = 0; + QString r; + + if ( message && message[0]) { + char *newstring = new char[strlen(source) + strlen(message) + 5]; + sprintf(newstring, "_: %s\n%s", source, message); + const char *translation = 0; + // as copying QString is very fast, it looks slower as it is ;/ + r = translate_priv(newstring, source, &translation); + delete [] newstring; + if (translation) + return r; + } + + if ( context && context[0] && message && message[0]) { + newstring = new char[strlen(context) + strlen(message) + 5]; + sprintf(newstring, "_: %s\n%s", context, message); + // as copying QString is very fast, it looks slower as it is ;/ + r = translate_priv(newstring, source, &translation); + delete [] newstring; + if (translation) + return r; + } + + r = translate_priv(source, source, &translation); + if (translation) + return r; + return QString::null; +} + +bool KLocale::nounDeclension() const +{ + doFormatInit(); + return d->nounDeclension; +} + +bool KLocale::dateMonthNamePossessive() const +{ + doFormatInit(); + return d->dateMonthNamePossessive; +} + +int KLocale::weekStartDay() const +{ + doFormatInit(); + return d->weekStartDay; +} + +bool KLocale::weekStartsMonday() const //deprecated +{ + doFormatInit(); + return (d->weekStartDay==1); +} + +QString KLocale::decimalSymbol() const +{ + doFormatInit(); + return m_decimalSymbol; +} + +QString KLocale::thousandsSeparator() const +{ + doFormatInit(); + return m_thousandsSeparator; +} + +QString KLocale::currencySymbol() const +{ + doFormatInit(); + return m_currencySymbol; +} + +QString KLocale::monetaryDecimalSymbol() const +{ + doFormatInit(); + return m_monetaryDecimalSymbol; +} + +QString KLocale::monetaryThousandsSeparator() const +{ + doFormatInit(); + return m_monetaryThousandsSeparator; +} + +QString KLocale::positiveSign() const +{ + doFormatInit(); + return m_positiveSign; +} + +QString KLocale::negativeSign() const +{ + doFormatInit(); + return m_negativeSign; +} + +int KLocale::fracDigits() const +{ + doFormatInit(); + return m_fracDigits; +} + +bool KLocale::positivePrefixCurrencySymbol() const +{ + doFormatInit(); + return m_positivePrefixCurrencySymbol; +} + +bool KLocale::negativePrefixCurrencySymbol() const +{ + doFormatInit(); + return m_negativePrefixCurrencySymbol; +} + +KLocale::SignPosition KLocale::positiveMonetarySignPosition() const +{ + doFormatInit(); + return m_positiveMonetarySignPosition; +} + +KLocale::SignPosition KLocale::negativeMonetarySignPosition() const +{ + doFormatInit(); + return m_negativeMonetarySignPosition; +} + +static inline void put_it_in( QChar *buffer, uint& index, const QString &s ) +{ + for ( uint l = 0; l < s.length(); l++ ) + buffer[index++] = s.at( l ); +} + +static inline void put_it_in( QChar *buffer, uint& index, int number ) +{ + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; +} + +QString KLocale::formatMoney(double num, + const QString & symbol, + int precision) const +{ + // some defaults + QString currency = symbol.isNull() + ? currencySymbol() + : symbol; + if (precision < 0) precision = fracDigits(); + + // the number itself + bool neg = num < 0; + QString res = QString::number(neg?-num:num, 'f', precision); + int pos = res.find('.'); + if (pos == -1) pos = res.length(); + else res.replace(pos, 1, monetaryDecimalSymbol()); + + while (0 < (pos -= 3)) + res.insert(pos, monetaryThousandsSeparator()); // thousend sep + + // set some variables we need later + int signpos = neg + ? negativeMonetarySignPosition() + : positiveMonetarySignPosition(); + QString sign = neg + ? negativeSign() + : positiveSign(); + + switch (signpos) + { + case ParensAround: + res.prepend('('); + res.append (')'); + break; + case BeforeQuantityMoney: + res.prepend(sign); + break; + case AfterQuantityMoney: + res.append(sign); + break; + case BeforeMoney: + currency.prepend(sign); + break; + case AfterMoney: + currency.append(sign); + break; + } + + if (neg?negativePrefixCurrencySymbol(): + positivePrefixCurrencySymbol()) + { + res.prepend(' '); + res.prepend(currency); + } else { + res.append (' '); + res.append (currency); + } + + return res; +} + +QString KLocale::formatMoney(const QString &numStr) const +{ + return formatMoney(numStr.toDouble()); +} + +QString KLocale::formatNumber(double num, int precision) const +{ + bool neg = num < 0; + if (precision == -1) precision = 2; + QString res = QString::number(neg?-num:num, 'f', precision); + int pos = res.find('.'); + if (pos == -1) pos = res.length(); + else res.replace(pos, 1, decimalSymbol()); + + while (0 < (pos -= 3)) + res.insert(pos, thousandsSeparator()); // thousand sep + + // How can we know where we should put the sign? + res.prepend(neg?negativeSign():positiveSign()); + + return res; +} + +QString KLocale::formatLong(long num) const +{ + return formatNumber((double)num, 0); +} + +QString KLocale::formatNumber(const QString &numStr) const +{ + return formatNumber(numStr.toDouble()); +} + +QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const +{ + const QString rst = shortFormat?dateFormatShort():dateFormat(); + + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 50]; + + unsigned int index = 0; + bool escape = false; + int number = 0; + + int year = calendar()->year(pDate); + int month = calendar()->month(pDate); + int day = calendar()->day(pDate); + + for ( uint format_index = 0; format_index < rst.length(); ++format_index ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'Y': + put_it_in( buffer, index, year / 100 ); + case 'y': + put_it_in( buffer, index, year % 100 ); + break; + case 'n': + number = month; + case 'e': + // to share the code + if ( rst.at( format_index ).unicode() == 'e' ) + number = day; + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'm': + put_it_in( buffer, index, month ); + break; + case 'b': + if (d->nounDeclension && d->dateMonthNamePossessive) +//US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, true) ); + put_it_in( buffer, index, calendar()->monthNamePossessive(month, true) ); + else +//US put_it_in( buffer, index, calendar()->monthName(month, year, true) ); + put_it_in( buffer, index, calendar()->monthName(month, true) ); + break; + case 'B': + if (d->nounDeclension && d->dateMonthNamePossessive) +//US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, false) ); + put_it_in( buffer, index, calendar()->monthNamePossessive(month, false) ); + else +//US put_it_in( buffer, index, calendar()->monthName(month, year, false) ); + put_it_in( buffer, index, calendar()->monthName(month, false) ); + break; + case 'd': + put_it_in( buffer, index, day ); + break; + case 'a': + put_it_in( buffer, index, calendar()->weekDayName(pDate, true) ); + break; + case 'A': + put_it_in( buffer, index, calendar()->weekDayName(pDate, false) ); + break; + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +void KLocale::setMainCatalogue(const char *catalogue) +{ + maincatalogue = catalogue; +} + +double KLocale::readNumber(const QString &_str, bool * ok) const +{ + QString str = _str.stripWhiteSpace(); + bool neg = str.find(negativeSign()) == 0; + if (neg) + str.remove( 0, negativeSign().length() ); + + /* will hold the scientific notation portion of the number. + Example, with 2.34E+23, exponentialPart == "E+23" + */ + QString exponentialPart; + int EPos; + + EPos = str.find('E', 0, false); + + if (EPos != -1) + { + exponentialPart = str.mid(EPos); + str = str.left(EPos); + } + + int pos = str.find(decimalSymbol()); + QString major; + QString minor; + if ( pos == -1 ) + major = str; + else + { + major = str.left(pos); + minor = str.mid(pos + decimalSymbol().length()); + } + + // Remove thousand separators + int thlen = thousandsSeparator().length(); + int lastpos = 0; + while ( ( pos = major.find( thousandsSeparator() ) ) > 0 ) + { + // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N + int fromEnd = major.length() - pos; + if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error + || pos - lastpos > 3 // More than 3 digits between two separators -> error + || pos == 0 // Can't start with a separator + || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators + { + if (ok) *ok = false; + return 0.0; + } + + lastpos = pos; + major.remove( pos, thlen ); + } + if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator + { + if (ok) *ok = false; + return 0.0; + } + + QString tot; + if (neg) tot = '-'; + + tot += major + '.' + minor + exponentialPart; + + return tot.toDouble(ok); +} + +double KLocale::readMoney(const QString &_str, bool * ok) const +{ + QString str = _str.stripWhiteSpace(); + bool neg = false; + bool currencyFound = false; + // First try removing currency symbol from either end + int pos = str.find(currencySymbol()); + if ( pos == 0 || pos == (int) str.length()-1 ) + { + str.remove(pos,currencySymbol().length()); + str = str.stripWhiteSpace(); + currencyFound = true; + } + if (str.isEmpty()) + { + if (ok) *ok = false; + return 0; + } + // Then try removing negative sign from either end + // (with a special case for parenthesis) + if (negativeMonetarySignPosition() == ParensAround) + { + if (str.at(0) == '(' && str.at(str.length()-1) == ')') + { + neg = true; + str.remove(str.length()-1,1); + str.remove(0,1); + } + } + else + { + int i1 = str.find(negativeSign()); + if ( i1 == 0 || i1 == (int) str.length()-1 ) + { + neg = true; + str.remove(i1,negativeSign().length()); + } + } + if (neg) str = str.stripWhiteSpace(); + + // Finally try again for the currency symbol, if we didn't find + // it already (because of the negative sign being in the way). + if ( !currencyFound ) + { + pos = str.find(currencySymbol()); + if ( pos == 0 || pos == (int) str.length()-1 ) + { + str.remove(pos,currencySymbol().length()); + str = str.stripWhiteSpace(); + } + } + + // And parse the rest as a number + pos = str.find(monetaryDecimalSymbol()); + QString major; + QString minior; + if (pos == -1) + major = str; + else + { + major = str.left(pos); + minior = str.mid(pos + monetaryDecimalSymbol().length()); + } + + // Remove thousand separators + int thlen = monetaryThousandsSeparator().length(); + int lastpos = 0; + while ( ( pos = major.find( monetaryThousandsSeparator() ) ) > 0 ) + { + // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N + int fromEnd = major.length() - pos; + if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error + || pos - lastpos > 3 // More than 3 digits between two separators -> error + || pos == 0 // Can't start with a separator + || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators + { + if (ok) *ok = false; + return 0.0; + } + lastpos = pos; + major.remove( pos, thlen ); + } + if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator + { + if (ok) *ok = false; + return 0.0; + } + + QString tot; + if (neg) tot = '-'; + tot += major + '.' + minior; + return tot.toDouble(ok); +} + +/** + * helper function to read integers + * @param str + * @param pos the position to start at. It will be updated when we parse it. + * @return the integer read in the string, or -1 if no string + */ +static int readInt(const QString &str, uint &pos) +{ + if (!str.at(pos).isDigit()) return -1; + int result = 0; + for (; str.length() > pos && str.at(pos).isDigit(); pos++) + { + result *= 10; + result += str.at(pos).digitValue(); + } + + return result; +} + +QDate KLocale::readDate(const QString &intstr, bool* ok) const +{ + QDate date; + date = readDate(intstr, ShortFormat, ok); + if (date.isValid()) return date; + return readDate(intstr, NormalFormat, ok); +} + +QDate KLocale::readDate(const QString &intstr, ReadDateFlags flags, bool* ok) const +{ + QString fmt = ((flags & ShortFormat) ? dateFormatShort() : dateFormat()).simplifyWhiteSpace(); + return readDate( intstr, fmt, ok ); +} + +QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const +{ + //kdDebug() << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl; + QString str = intstr.simplifyWhiteSpace().lower(); + int day = -1, month = -1; + // allow the year to be omitted if not in the format + int year = calendar()->year(QDate::currentDate()); + uint strpos = 0; + uint fmtpos = 0; + + bool error = false; + + while (fmt.length() > fmtpos && str.length() > strpos && !error) + { + + QChar c = fmt.at(fmtpos++); + + if (c != '%') { + if (c.isSpace() && str.at(strpos).isSpace()) + strpos++; + else if (c != str.at(strpos++)) + error = true; + } + else + { + int j; + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = fmt.at(fmtpos++); + switch (c) + { + case 'a': + case 'A': + + error = true; + j = 1; + while (error && (j < 8)) { + QString s = weekDayName(j, c == 'a').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + { + strpos += len; + error = false; + } + j++; + } + break; + case 'b': + case 'B': + + error = true; + if (d->nounDeclension && d->dateMonthNamePossessive) { + j = 1; + while (error && (j < 13)) { +//US QString s = calendar()->monthNamePossessive(j, year, c == 'b').lower(); + QString s = calendar()->monthNamePossessive(j, c == 'b').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) { + month = j; + strpos += len; + error = false; + } + j++; + } + } + j = 1; + while (error && (j < 13)) { +//US QString s = calendar()->monthName(j, year, c == 'b').lower(); + QString s = calendar()->monthName(j, c == 'b').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) { + month = j; + strpos += len; + error = false; + } + j++; + } + break; + case 'd': + case 'e': + day = readInt(str, strpos); + error = (day < 1 || day > 31); + break; + + case 'n': + case 'm': + month = readInt(str, strpos); + error = (month < 1 || month > 12); + break; + + case 'Y': + case 'y': + year = readInt(str, strpos); + error = (year < 0); + // Qt treats a year in the range 0-100 as 1900-1999. + // It is nicer for the user if we treat 0-68 as 2000-2068 + if (c == 'y' && year < 69) + // eg. gregorian += 2000 + year += (calendar()->year(QDate::currentDate()) / 100) * 100; + else if (c == 'y' && year < 100) + // eg. gregorian += 1900 + year += (calendar()->year(QDate::currentDate()) / 100) * 100 - 100; + break; + } + } + } + + /* for a match, we should reach the end of both strings, not just one of + them */ + if ( fmt.length() > fmtpos || str.length() > strpos ) + { + error = true; + } + + //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl; + if ( year != -1 && month != -1 && day != -1 && !error) + { + if (ok) *ok = true; + + QDate result; + calendar()->setYMD(result, year, month, day); + + return result; + } + else + { + if (ok) *ok = false; + return QDate(); // invalid date + } +} + +QTime KLocale::readTime(const QString &intstr, bool *ok) const +{ + QTime _time; + _time = readTime(intstr, WithSeconds, ok); + if (_time.isValid()) return _time; + return readTime(intstr, WithoutSeconds, ok); +} + +QTime KLocale::readTime(const QString &intstr, ReadTimeFlags flags, bool *ok) const +{ + QString str = intstr.simplifyWhiteSpace().lower(); + QString Format = timeFormat().simplifyWhiteSpace(); + if (flags & WithoutSeconds) + { +//US remove not available in my QT version +//US Format.remove(QRegExp(".%S")); + Format.replace(QRegExp(".%S"), ""); + } + + int hour = -1, minute = -1; + int second = ( (flags & WithoutSeconds) == 0 ) ? -1 : 0; // don't require seconds + bool g_12h = false; + bool pm = false; + uint strpos = 0; + uint Formatpos = 0; + + while (Format.length() > Formatpos || str.length() > strpos) + { + if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error; + + QChar c = Format.at(Formatpos++); + + if (c != '%') + { + if (c.isSpace()) + strpos++; + else if (c != str.at(strpos++)) + goto error; + continue; + } + + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = Format.at(Formatpos++); + switch (c) + { + case 'p': + { + QString s; + s = translate("pm").lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + { + pm = true; + strpos += len; + } + else + { + s = translate("am").lower(); + len = s.length(); + if (str.mid(strpos, len) == s) { + pm = false; + strpos += len; + } + else + goto error; + } + } + break; + + case 'k': + case 'H': + g_12h = false; + hour = readInt(str, strpos); + if (hour < 0 || hour > 23) + goto error; + + break; + + case 'l': + case 'I': + g_12h = true; + hour = readInt(str, strpos); + if (hour < 1 || hour > 12) + goto error; + + break; + + case 'M': + minute = readInt(str, strpos); + if (minute < 0 || minute > 59) + goto error; + + break; + + case 'S': + second = readInt(str, strpos); + if (second < 0 || second > 59) + goto error; + + break; + } + } + if (g_12h) { + hour %= 12; + if (pm) hour += 12; + } + + if (ok) *ok = true; + return QTime(hour, minute, second); + + error: + if (ok) *ok = false; + return QTime(-1, -1, -1); // return invalid date if it didn't work +} + +QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const +{ + const QString rst = timeFormat(); + + // only "pm/am" here can grow, the rest shrinks, but + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 30]; + + uint index = 0; + bool escape = false; + int number = 0; + + for ( uint format_index = 0; format_index < rst.length(); format_index++ ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'H': + put_it_in( buffer, index, pTime.hour() ); + break; + case 'I': + put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 ); + break; + case 'M': + put_it_in( buffer, index, pTime.minute() ); + break; + case 'S': + if (includeSecs) + put_it_in( buffer, index, pTime.second() ); + else if ( index > 0 ) + { + // we remove the seperator sign before the seconds and + // assume that works everywhere + --index; + break; + } + break; + case 'k': + number = pTime.hour(); + case 'l': + // to share the code + if ( rst.at( format_index ).unicode() == 'l' ) + number = (pTime.hour() + 11) % 12 + 1; + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'p': + { + QString s; + if ( pTime.hour() >= 12 ) + put_it_in( buffer, index, translate("pm") ); + else + put_it_in( buffer, index, translate("am") ); + break; + } + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +bool KLocale::use12Clock() const +{ + if ((timeFormat().contains(QString::fromLatin1("%I")) > 0) || + (timeFormat().contains(QString::fromLatin1("%l")) > 0)) + return true; + else + return false; +} + +QString KLocale::languages() const +{ + return d->languageList.join( QString::fromLatin1(":") ); +} + +QStringList KLocale::languageList() const +{ + return d->languageList; +} + +QString KLocale::formatDateTime(const QDateTime &pDateTime, + bool shortFormat, + bool includeSeconds) const +{ + return translate("concatenation of dates and time", "%1 %2") + .arg( formatDate( pDateTime.date(), shortFormat ) ) + .arg( formatTime( pDateTime.time(), includeSeconds ) ); +} + +QString i18n(const char* text) +{ + /* + register KLocale *instance = KGlobal::locale(); + if (instance) + return instance->translate(text); + */ + return QString::fromUtf8(text); +} + +QString i18n(const char* index, const char *text) +{ + /* + register KLocale *instance = KGlobal::locale(); + if (instance) + return instance->translate(index, text); + */ + return QString::fromUtf8(text); +} + +QString i18n(const char* singular, const char* plural, unsigned long n) +{ + return (QString::fromUtf8(plural)); // hack! remove this line! + register KLocale *instance = KGlobal::locale(); + if (instance) + return instance->translate(singular, plural, n); + if (n == 1) + return put_n_in(QString::fromUtf8(singular), n); + else + return put_n_in(QString::fromUtf8(plural), n); +} + +void KLocale::initInstance() +{ + if (KGlobal::locale()) + return; + +/*US lets change the whole way how to create a KLocale + KInstance *app = KGlobal::instance(); + if (app) { + KGlobal::_locale = new KLocale(QString::fromLatin1(app->instanceName())); + + // only do this for the global instance + QTextCodec::setCodecForLocale(KGlobal::_locale->codecForEncoding()); + } + else + kdDebug(173) << "no app name available using KLocale - nothing to do\n"; +*/ +//US new implementation + QString appname = KGlobal::getAppName(); + if (appname) { + KLocale *l = new KLocale(appname); + KGlobal::setLocale(l); + + // only do this for the global instance +//US +//US QTextCodec::setCodecForLocale(KGlobal::locale())->codecForEncoding()); +//US qt_set_locale_codec( KGlobal::locale()->codecForEncoding() ); + qDebug("KLocale::initInstance we have to do here something !!!"); + } + else + kdDebug(173) << "no app name available using KLocale - nothing to do\n"; + +} + +QString KLocale::langLookup(const QString &fname, const char *rtype) +{ + QStringList search; + + // assemble the local search paths +//US we have only one resourcedir. So use it !! +/*US original + const QStringList localDoc = KGlobal::dirs()->resourceDirs(rtype); + // look up the different languages + for (int id=localDoc.count()-1; id >= 0; --id) + { + QStringList langs = KGlobal::locale()->languageList(); + langs.append( "en" ); + langs.remove( defaultLanguage() ); + QStringList::ConstIterator lang; + for (lang = langs.begin(); lang != langs.end(); ++lang) + search.append(QString("%1%2/%3").arg(localDoc[id]).arg(*lang).arg(fname)); + } +*/ +//US new code +//US What is here correct??? const QString localDoc = KGlobal::dirs()->findResourceDir(rtype); + const QString localDoc = rtype; + // look up the different languages + QStringList langs = KGlobal::locale()->languageList(); + langs.append( "en" ); + langs.remove( defaultLanguage() ); + QStringList::ConstIterator lang; + for (lang = langs.begin(); lang != langs.end(); ++lang) + search.append(QString("%1%2/%3").arg(localDoc).arg(*lang).arg(fname)); + + // try to locate the file + QStringList::Iterator it; + for (it = search.begin(); it != search.end(); ++it) + { + kdDebug(173) << "Looking for help in: " << *it << endl; + + QFileInfo info(*it); + if (info.exists() && info.isFile() && info.isReadable()) + return *it; + } + + return QString::null; +} + +bool KLocale::useDefaultLanguage() const +{ + return language() == defaultLanguage(); +} + +void KLocale::initEncoding(KConfig *) +{ + const int mibDefault = 4; // ISO 8859-1 + + // This all made more sense when we still had the EncodingEnum config key. + setEncoding( QTextCodec::codecForLocale()->mibEnum() ); + + if ( !d->codecForEncoding ) + { + kdWarning(173) << " Defaulting to ISO 8859-1 encoding." << endl; + setEncoding(mibDefault); + } + + ASSERT( d->codecForEncoding ); +} + +void KLocale::initFileNameEncoding(KConfig *) +{ + // If the following environment variable is set, assume all filenames + // are in UTF-8 regardless of the current C locale. + d->utf8FileEncoding = getenv("KDE_UTF8_FILENAMES") != 0; + if (d->utf8FileEncoding) + { + QFile::setEncodingFunction(KLocale::encodeFileNameUTF8); + QFile::setDecodingFunction(KLocale::decodeFileNameUTF8); + } + // Otherwise, stay with QFile's default filename encoding functions + // which, on Unix platforms, use the locale's codec. +} + +QCString KLocale::encodeFileNameUTF8( const QString & fileName ) +{ + return fileName.utf8(); +} + +QString KLocale::decodeFileNameUTF8( const QCString & localFileName ) +{ + return QString::fromUtf8(localFileName); +} + +void KLocale::initCatalogue( KCatalogue & catalogue ) +{ + catalogue.setFileName( catalogueFileName( language(), catalogue ) ); +} + +void KLocale::setDateFormat(const QString & format) +{ + doFormatInit(); + m_dateFormat = format.stripWhiteSpace(); +} + +void KLocale::setDateFormatShort(const QString & format) +{ + doFormatInit(); + m_dateFormatShort = format.stripWhiteSpace(); +} + +void KLocale::setDateMonthNamePossessive(bool possessive) +{ + doFormatInit(); + d->dateMonthNamePossessive = possessive; +} + +void KLocale::setTimeFormat(const QString & format) +{ + doFormatInit(); + m_timeFormat = format.stripWhiteSpace(); +} + +void KLocale::setWeekStartsMonday(bool start) //deprecated +{ + doFormatInit(); + if (start) + d->weekStartDay = 1; + else + d->weekStartDay = 7; +} + +void KLocale::setWeekStartDay(int day) +{ + doFormatInit(); + if (day>7 || day<1) + d->weekStartDay = 1; //Monday is default + else + d->weekStartDay = day; +} + +QString KLocale::dateFormat() const +{ + doFormatInit(); + return m_dateFormat; +} + +QString KLocale::dateFormatShort() const +{ + doFormatInit(); + return m_dateFormatShort; +} + +QString KLocale::timeFormat() const +{ + doFormatInit(); + return m_timeFormat; +} + +void KLocale::setDecimalSymbol(const QString & symbol) +{ + doFormatInit(); + m_decimalSymbol = symbol.stripWhiteSpace(); +} + +void KLocale::setThousandsSeparator(const QString & separator) +{ + doFormatInit(); + // allow spaces here + m_thousandsSeparator = separator; +} + +void KLocale::setPositiveSign(const QString & sign) +{ + doFormatInit(); + m_positiveSign = sign.stripWhiteSpace(); +} + +void KLocale::setNegativeSign(const QString & sign) +{ + doFormatInit(); + m_negativeSign = sign.stripWhiteSpace(); +} + +void KLocale::setPositiveMonetarySignPosition(SignPosition signpos) +{ + doFormatInit(); + m_positiveMonetarySignPosition = signpos; +} + +void KLocale::setNegativeMonetarySignPosition(SignPosition signpos) +{ + doFormatInit(); + m_negativeMonetarySignPosition = signpos; +} + +void KLocale::setPositivePrefixCurrencySymbol(bool prefix) +{ + doFormatInit(); + m_positivePrefixCurrencySymbol = prefix; +} + +void KLocale::setNegativePrefixCurrencySymbol(bool prefix) +{ + doFormatInit(); + m_negativePrefixCurrencySymbol = prefix; +} + +void KLocale::setFracDigits(int digits) +{ + doFormatInit(); + m_fracDigits = digits; +} + +void KLocale::setMonetaryThousandsSeparator(const QString & separator) +{ + doFormatInit(); + // allow spaces here + m_monetaryThousandsSeparator = separator; +} + +void KLocale::setMonetaryDecimalSymbol(const QString & symbol) +{ + doFormatInit(); + m_monetaryDecimalSymbol = symbol.stripWhiteSpace(); +} + +void KLocale::setCurrencySymbol(const QString & symbol) +{ + doFormatInit(); + m_currencySymbol = symbol.stripWhiteSpace(); +} + +int KLocale::pageSize() const +{ + doFormatInit(); + return d->pageSize; +} + +void KLocale::setPageSize(int pageSize) +{ + // #### check if it's in range?? + doFormatInit(); + d->pageSize = pageSize; +} + +KLocale::MeasureSystem KLocale::measureSystem() const +{ + doFormatInit(); + return d->measureSystem; +} + +void KLocale::setMeasureSystem(MeasureSystem value) +{ + doFormatInit(); + d->measureSystem = value; +} + +QString KLocale::defaultLanguage() +{ + return QString::fromLatin1("en_US"); +} + +QString KLocale::defaultCountry() +{ + return QString::fromLatin1("C"); +} + +const char * KLocale::encoding() const +{ + return codecForEncoding()->name(); +} + +int KLocale::encodingMib() const +{ + return codecForEncoding()->mibEnum(); +} + +int KLocale::fileEncodingMib() const +{ + if (d->utf8FileEncoding) + return 106; + return codecForEncoding()->mibEnum(); +} + +QTextCodec * KLocale::codecForEncoding() const +{ + return d->codecForEncoding; +} + +bool KLocale::setEncoding(int mibEnum) +{ + QTextCodec * codec = QTextCodec::codecForMib(mibEnum); + if (codec) + d->codecForEncoding = codec; + + return codec != 0; +} + +QStringList KLocale::languagesTwoAlpha() const +{ + if (d->langTwoAlpha.count()) + return d->langTwoAlpha; + + const QStringList &origList = languageList(); + + QStringList result; + +//US KConfig config(QString::fromLatin1("language.codes"), true, false); + KConfig config(locateLocal("config", QString::fromLatin1("language.codes"))); + config.setGroup("TwoLetterCodes"); + + for ( QStringList::ConstIterator it = origList.begin(); + it != origList.end(); + ++it ) + { + QString lang = *it; + QStringList langLst; + +/*US I changed the following code, because hasKey is not available. +!!! check if my version is correct + if (config.hasKey( lang )) + langLst = config.readListEntry( lang ); + else + { + int i = lang.find('_'); + if (i >= 0) + lang.truncate(i); + langLst << lang; + } +*/ + langLst = config.readListEntry( lang ); + if (langLst.isEmpty()) + { + int i = lang.find('_'); + if (i >= 0) + lang.truncate(i); + langLst << lang; + } + + + for ( QStringList::ConstIterator langIt = langLst.begin(); + langIt != langLst.end(); + ++langIt ) + { + if ( !(*langIt).isEmpty() && !result.contains( *langIt ) ) + result += *langIt; + } + } + d->langTwoAlpha = result; + return result; +} + +QStringList KLocale::allLanguagesTwoAlpha() const +{ + if (!d->languages) +//US d->languages = new KConfig("all_languages", true, false, "locale"); + d->languages = new KConfig(locateLocal( "locale", "all_languages")); + +//US return d->languages->groupList(); + qDebug("KLocale::allLanguagesTwoAlpha has to be fixed."); + return *(new QStringList()); + +} + +QString KLocale::twoAlphaToLanguageName(const QString &code) const +{ + if (!d->languages) +//US d->languages = new KConfig("all_languages", true, false, "locale"); + d->languages = new KConfig(locateLocal( "locale", "all_languages")); + + d->languages->setGroup(code.lower()); + return d->languages->readEntry("Name"); +} + +QStringList KLocale::allCountriesTwoAlpha() const +{ + QStringList countries; + + qDebug("KLocale::allCountriesTwoAlpha has to be fixed."); +//US QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop"); + QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop", true, true); + + for(QStringList::ConstIterator it = paths.begin(); + it != paths.end(); ++it) + { + QString code = (*it).mid((*it).length()-16, 2); + if (code != "/C") + countries.append(code); + } + return countries; +} + +QString KLocale::twoAlphaToCountryName(const QString &code) const +{ +//US KConfig cfg("l10n/"+code.lower()+"/entry.desktop", true, false, "locale"); + KConfig cfg(locateLocal("locale", "l10n/"+code.lower()+"/entry.desktop")); + cfg.setGroup("KCM Locale"); + return cfg.readEntry("Name"); +} + +void KLocale::setCalendar(const QString & calType) +{ + doFormatInit(); + + d->calendarType = calType; + + delete d->calendar; + d->calendar = 0; +} + +QString KLocale::calendarType() const +{ + doFormatInit(); + + return d->calendarType; +} + +const KCalendarSystem * KLocale::calendar() const +{ + doFormatInit(); + + // Check if it's the correct calendar?!? +//US we are always using the gregorian calendar +//US if ( !d->calendar ) +//US d->calendar = KCalendarSystemFactory::create( d->calendarType, this ); + if ( !d->calendar ) + d->calendar = new KCalendarSystemGregorian; + + return d->calendar; +} + +KLocale::KLocale(const KLocale & rhs) +{ + d = new KLocalePrivate; + + *this = rhs; +} + +KLocale & KLocale::operator=(const KLocale & rhs) +{ + // Numbers and money + m_decimalSymbol = rhs.m_decimalSymbol; + m_thousandsSeparator = rhs.m_thousandsSeparator; + m_currencySymbol = rhs.m_currencySymbol; + m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol; + m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator; + m_positiveSign = rhs.m_positiveSign; + m_negativeSign = rhs.m_negativeSign; + m_fracDigits = rhs.m_fracDigits; + m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol; + m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol; + m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition; + m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition; + + // Date and time + m_timeFormat = rhs.m_timeFormat; + m_dateFormat = rhs.m_dateFormat; + m_dateFormatShort = rhs.m_dateFormatShort; + + m_language = rhs.m_language; + m_country = rhs.m_country; + + // the assignment operator works here + *d = *rhs.d; + d->languages = 0; // Don't copy languages + d->calendar = 0; // Don't copy the calendar + + return *this; +} + +bool KLocale::setCharset(const QString & ) { return true; } +QString KLocale::charset() const { return QString::fromLatin1("UTF-8"); } + + +int KLocale::timezoneOffset( QString timeZone ) +{ + int ret = 1001; + int index = mTimeZoneList.findIndex( timeZone ); + if ( index < 24 ) + ret = ( index-11 ) * 60 ; + return ret; +} + +QStringList KLocale::timeZoneList() const +{ + return mTimeZoneList; +} +void KLocale::setTimezone( const QString &timeZone ) +{ + mTimeZoneOffset = timezoneOffset( timeZone ); +} + +void KLocale::setDaylightSaving( bool b, int start , int end ) +{ + daylightEnabled = b; + daylightStart = start; + daylightEnd = end; + mSouthDaylight = (end < start); + // qDebug("klocale daylight %d %d %d ", b, start , end ); +} + +int KLocale::localTimeOffset( const QDateTime &dt ) +{ + bool addDaylight = false; + if ( daylightEnabled ) { + int d_end, d_start; + int dayofyear = dt.date().dayOfYear(); + int year = dt.date().year(); + int add = 0; + if ( QDate::leapYear(year) ) + add = 1; + QDate date ( year,1,1 ); + if ( daylightEnd > 59 ) + d_end = daylightEnd +add; + else + d_end = daylightEnd; + if ( daylightStart > 59 ) + d_start = daylightStart +add; + else + d_start = daylightStart; + QDate s_date = date.addDays( d_start -1 ); + QDate e_date = date.addDays( d_end -1 ); + int dof = s_date.dayOfWeek(); + if ( dof < 7 ) + s_date = s_date.addDays( -dof ); + dof = e_date.dayOfWeek(); + if ( dof < 7 ) + e_date = e_date.addDays( -dof ); + QTime startTime ( 3,0,0 ); + QDateTime startDt( s_date, startTime ); + QDateTime endDt( e_date, startTime ); + //qDebug("dayligt saving start %s end %s ",startDt.toString().latin1(),endDt.toString().latin1( )); + if ( mSouthDaylight ) { + if ( ! ( endDt < dt && dt < startDt) ) + addDaylight = true; + } else { + if ( startDt < dt && dt < endDt ) + addDaylight = true; + + + } + } + int addMin = 0; + if ( addDaylight ) + addMin = 60; + return mTimeZoneOffset + addMin; +} + +void KLocale::setHore24Format ( bool b ) +{ + mHourF24Format = b; +} +void KLocale::setWeekStartMonday( bool b ) +{ + mWeekStartsMonday = b; +} +void KLocale::setIntDateFormat( int i ) +{ + mIntDateFormat = i; +} +void KLocale::setLanguage( int i ) +{ + mLanguage = i; +} + + + diff --git a/microkde/kdecore/klocale_new.h b/microkde/kdecore/klocale_new.h new file mode 100644 index 0000000..777c0bd --- a/dev/null +++ b/microkde/kdecore/klocale_new.h @@ -0,0 +1,1224 @@ +#ifndef MINIKDE_KLOCALE_H +#define MINIKDE_KLOCALE_H + +#include <qstring.h> +#include <qstringlist.h> +#include <qdict.h> + +class QStringList; +class QTextCodec; +class QDate; +class QTime; +class QDateTime; + +class KGlobal; +class KConfig; +class KConfigBase; +class KLocalePrivate; +class KCatalogue; +class KCalendarSystem; + +#ifndef I18N_NOOP +#define I18N_NOOP(x) (x) +#endif + +void setLocaleDict( QDict<char> * dict ); + +/** + * i18n is the function that does everything you need to translate + * a string. You just wrap around every user visible string a i18n + * call to get a QString with the string in the user's preferred + * language. + * + * The argument must be an UTF-8 encoded string (If you only use + * characters that are in US-ASCII, you're on the safe side. But + * for e.g. german umlauts or french accents should be recoded to + * UTF-8) + **/ +QString i18n(const char *text); + +/** + * If the string is too ambiguous to be translated well to a non-english + * language, use this form of i18n to separate lookup string and english + * text. + * @see translate + **/ +QString i18n(const char *index, const char *text); + +/** + * If you want to handle plural forms, use this form of i18n. + * The plural has to contain a %n where n fits into. + * @see translate + **/ +QString i18n(const char *singular, const char *plural, unsigned long n); + +/** + * Qt3's uic generates i18n( "msg", "comment" ) calls which conflict + * with our i18n method. We use uic -tr tr2i18n to redirect + * to the right i18n() function +**/ +inline QString tr2i18n(const char* message, const char* =0) { + return i18n(message); +} + +/** + * + * KLocale provides support for country specific stuff like + * the national language. + * + * KLocale supports translating, as well as specifying the format + * for numbers, currency, time, and date. + * + * @author Stephan Kulow <coolo@kde.org>, Preston Brown <pbrown@kde.org>, + * Hans Petter Bieker <bieker@kde.org>, Lukas Tinkl <lukas.tinkl@suse.cz> + * @short class for supporting locale settings and national language + */ +class KLocale +{ + friend class KGlobal; // for initInstance() +public: + /** + * Constructs a KLocale with the given catalogue name. + * The constructor looks for an entry Locale/Language in the + * configuration file. + * If no config file is specified, it will also look for languages + * using the environment variables (KDE_LANG, LC_MESSAGES, LC_ALL, LANG), + * as well as the global configuration fie. If we were not able to use + * non of the specified languages, the default language (en_US) will be + * used. + * + * If you specify a configuration file, it has to be valid until + * the KLocale object is destroyed. + * + * @param catalogue The name of the main language file + * @param config The configuration file to use. + */ + KLocale( const QString& catalogue, KConfig *config = 0 ); + + /** + * Copy constructor. + */ + KLocale( const KLocale & rhs ); + + /** + * Assignment operator. + */ + KLocale& operator= ( const KLocale & rhs ); + + /** + * Destructor. + */ + ~KLocale(); + + /** + * Translates the string into the corresponding string in + * the national language, if available. If not, returns + * the string itself. + * There is a KDE wide message file that contains the most + * often used phrases, so we can avoid duplicating the + * translation of these phrases. If a phrase is not found + * in the catalogue given to the constructor, it will search + * in the system catalog. This makes it possible to override + * some phrases for your needs. + * + * The argument must be an UTF-8 encoded string (If you only use + * characters that are in US-ASCII you're on the safe side. But + * for e.g. german umlauts or french accents should be recoded to + * UTF-8) + * + * @param index The lookup text and default text, if not found. + */ + QString translate( const char *index ) const; + + /** + * Translates the string into the corresponding string in the + * national language, if available. + * + * The real contents of the string is in the argument fallback, + * but the meaning of it is coded into the argument index. + * In some cases you'll need this function, when english is + * too ambiguous to express it. + * + * Most of the times the translators will tell you if it can't + * be translated as it, but think of cases as "New", where the + * translations differs depending on what is New. + * Or simple cases as "Open", that can be used to express something + * is open or it can be used to express that you want something to + * open... There are tons of such examples. + * + * If translate("Open") is not enough to translate it well, use + * translate("To Open", "Open") or translate("Is Open", "Open"). + * The english user will see "Open" in both cases, but the translated + * version may vary. Of course you can also use i18n() + * + * @param index The lookup text + * @param fallback the default text, if not found + * @return translation + */ + QString translate( const char *index, const char *fallback) const; + + /** + * Used to get the correct, translated singular or plural of a + * word. + * @param singular the singular form of the word, for example "file". + * @param plural the plural form of the word. Must contain a "%n" that will + * be replaced by the number @n, for example "%n files" + * @param n the number + * @return the correct singular or plural for the selected language, + * depending on n + */ + QString translate( const char *singular, const char *plural, + unsigned long n) const; + + /** + * Changes the current encoding. + * + * @param mibEnum The mib of the preferred codec + * + * @return True on success. + */ + bool setEncoding(int mibEnum); + + /** + * Changes the current language. The current language will be left + * unchanged if failed. It will force a reload of the country specific + * configuration as well. + * + * @param language The language code. + * + * @return True on success. + */ + bool setLanguage(const QString & language); + + /** + * Changes the list of prefed languages for the locale. The first valid + * language in the list will be used, or the default (en_US) language + * will be used if non of the specified languages were available. + * + * @param languages The list of language codes. + * + * @return True if one of the specified languages were used. + */ + bool setLanguage(const QStringList & languages); + + /** + * Changes the current country. The current country will be left + * unchanged if failed. It will force a reload of the country specific + * configuration. + * + * @param country The ISO 3166 country code. + * + * @return True on success. + */ + bool setCountry(const QString & country); + + /** + * Various positions for where to place the positive or negative + * sign when they are related to a monetary value. + */ + enum SignPosition { ParensAround = 0, BeforeQuantityMoney = 1, + AfterQuantityMoney = 2, + BeforeMoney = 3, AfterMoney = 4 }; + + /** + * Returns what a decimal point should look like ("." or "," etc.) + * according to the current locale or user settings. + * + * @return The decimal symbol used by locale. + */ + QString decimalSymbol() const; + + /** + * Returns what the thousands separator should look + * like ("," or "." etc.) + * according to the current locale or user settings. + * + * @return The thousands separator used by locale. + */ + QString thousandsSeparator() const; + + /** + * Returns what the symbol denoting currency in the current locale + * as as defined by user settings should look like. + * + * @return The default currency symbol used by locale. + */ + QString currencySymbol() const; + + /** + * Returns what a decimal point should look like ("." or "," etc.) + * for monetary values, according to the current locale or user + * settings. + * + * @return The monetary decimal symbol used by locale. + */ + QString monetaryDecimalSymbol() const; + + /** + * Returns what a thousands separator for monetary values should + * look like ("," or " " etc.) according to the current locale or + * user settings. + * + * @return The monetary thousands separator used by locale. + */ + QString monetaryThousandsSeparator() const; + + /** + * Returns what a positive sign should look like ("+", " ", etc.) + * according to the current locale or user settings. + * + * @return The positive sign used by locale. + */ + QString positiveSign() const; + + /** + * Returns what a negative sign should look like ("-", etc.) + * according to the current locale or user settings. + * + * @return The negative sign used by locale. + */ + QString negativeSign() const; + + /** + * The number of fractional digits to include in numeric/monetary + * values (usually 2). + * + * @return Default number of fractional digits used by locale. + */ + int fracDigits() const; + + /** + * If and only if the currency symbol precedes a positive value, + * this will be true. + * + * @return Where to print the currency symbol for positive numbers. + */ + bool positivePrefixCurrencySymbol() const; + + /** + * If and only if the currency symbol precedes a negative value, + * this will be true. + * + * @return True if the currency symbol precedes negative numbers. + */ + bool negativePrefixCurrencySymbol() const; + + /** + * Returns the position of a positive sign in relation to a + * monetary value. + * + * @return Where/how to print the positive sign. + * @see SignPosition + */ + SignPosition positiveMonetarySignPosition() const; + + /** + * Denotes where to place a negative sign in relation to a + * monetary value. + * + * @return Where/how to print the negative sign. + * @see SignPosition + */ + SignPosition negativeMonetarySignPosition() const; + + /** + * Given a double, converts that to a numeric string containing + * the localized monetary equivalent. + * + * e.g. given 123456, return "$ 123,456.00". + * + * @param num The number we want to format + * @param currency The currency symbol you want. + * @param digits Number of fractional digits, or -1 for the default + * value + * + * @return The number of money as a localized string + * @see fracDigits() + */ + QString formatMoney(double num, + const QString & currency = QString::null, + int digits = -1) const; + + /** + * Given a double, converts that to a numeric string containing + * the localized numeric equivalent. + * + * e.g. given 123456.78F, return "123,456.78" (for some European country). + * If precision isn't specified, 2 is used. + * + * @param num The number to convert + * @param precision Number of fractional digits used. + * + * @return The number as a localized string + */ + QString formatNumber(double num, int precision = -1) const; + + /** + * Given an integer, converts that to a numeric string containing + * the localized numeric equivalent. + * + * e.g. given 123456L, return "123,456" (for some European country). + * + * @param num The number to convert + * + * @return The number as a localized string + * @since 3.2 + */ + QString formatLong(long num) const; + + /** + * Use this to determine whether nouns are declined in + * locale's language. This property should remain + * read-only (no setter function) + * + * @return If nouns are declined + * @since 3.1 + */ + bool nounDeclension() const; + + /** + * Returns a string formatted to the current locale's conventions + * regarding dates. + * + * @param pDate The date to be formated. + * @param shortFormat True for non text dates. + * + * @return The date as a string + */ + QString formatDate(const QDate &pDate, bool shortFormat = false) const; + + /** + * Use this to determine whether in dates a possessive form of month + * name is preferred ("of January" rather than "January") + * + * @return If possessive form should be used + * @since 3.1 + */ + bool dateMonthNamePossessive() const; + + /** + * Returns a string formatted to the current locale's conventions + * regarding times. + * + * @param pTime The time to be formated. + * @param includeSecs if true, seconds are included in the output, + * otherwise only hours and minutes are formatted. + * + * @return The time as a string + */ + QString formatTime(const QTime &pTime, bool includeSecs = false) const; + + /** + * Use this to determine if the user wants a 12 hour clock. + * + * @return If the user wants 12h clock + */ + bool use12Clock() const; + + /** + * @deprecated + * + * Please use the @ref weekStartDay method instead. + * + * Use this to determine if the user wants the week to start on Monday. + * + * @return true if the week starts on Monday + */ + bool weekStartsMonday() const; //### remove for KDE 4.0 + + /** + * Use this to determine which day is the first day of the week. + * + * @return an integer (Monday=1..Sunday=7) + * @since 3.1 + */ + int weekStartDay() const; + + /** + * @deprecated + * + * Returns a string containing the name of the month name used in the Gregorian calendar. + * + * @param i the month number of the year starting at 1/January. + * @param shortName we will return the short version of the string. + * + * @return The name of the month + */ + QString monthName(int i, bool shortName = false) const; + + /** + * @deprecated + * + * Returns a string containing the possessive form of the month name used in the Gregorian calendar. + * ("of January", "of February", etc.) + * It's needed in long format dates in some languages. + * + * @param i the month number of the year starting at 1/January. + * @param shortName we will return the short version of the string. + * + * @return The possessive form of the name of the month + * @since 3.1 + */ + QString monthNamePossessive(int i, bool shortName = false) const; + + /** + * @deprecated + * + * Returns a string containing the name of the week day used in the Gregorian calendar. + * + * @param i the day number of the week starting at 1/Monday. + * @param shortName we will return the short version of the string. + * + * @return The name of the day + */ + QString weekDayName(int i, bool shortName = false) const; + + /** + * Returns a pointer to the calendar system object. + * + * @return the current calendar system instance + * @since 3.2 + */ + const KCalendarSystem * calendar() const; + + /** + * Returns the name of the calendar system that is currently being + * used by the system. + * + * @return the name of the calendar system + * @since 3.2 + */ + QString calendarType() const; + + /** + * Changes the current calendar system to the calendar specified. + * Currently is "gregorian" and "hijri" supported. If the calendar + * system specified is not found, gregorian will be used. + * + * @param calendarType the name of the calendar type + * @since 3.2 + */ + void setCalendar(const QString & calendarType); + + /** + * Returns a string formated to the current locale's conventions + * regarding both date and time. + * + * @param pDateTime The date and time to be formated. + * @param shortFormat using the short date format. + * @param includeSecs using the short date format. + * + * @return The date and time as a string + */ + QString formatDateTime(const QDateTime &pDateTime, + bool shortFormat = true, + bool includeSecs = false) const; + + /** + * Converts a localized monetary string to a double. + * + * @param numStr the string we want to convert. + * @param ok the boolean that is set to false if it's not a number. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a double + */ + double readMoney(const QString &numStr, bool * ok = 0) const; + + /** + * Converts a localized numeric string to a double. + * + * @param numStr the string we want to convert. + * @param ok the boolean that is set to false if it's not a number. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a double + */ + double readNumber(const QString &numStr, bool * ok = 0) const; + + /** + * Converts a localized date string to a QDate. + * The bool pointed by ok will be invalid if the date entered was not valid. + * + * @param str the string we want to convert. + * @param ok the boolean that is set to false if it's not a valid date. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a QDate + */ + QDate readDate(const QString &str, bool* ok = 0) const; + + /** + * Converts a localized date string to a QDate, using the specified format. + * You will usually not want to use this method. + */ + QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const; + + enum ReadDateFlags { + NormalFormat = 1, + ShortFormat = 2 + }; + + /** + * Converts a localized date string to a QDate. + * This method is stricter than readDate(str,&ok): it will either accept + * a date in full format or a date in short format, depending on @p flags. + * + * @param str the string we want to convert. + * @param flags whether the date string is to be in full format or in short format. + * @param ok the boolean that is set to false if it's not a valid date. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a QDate + * @since 3.2 + */ + QDate readDate(const QString &str, ReadDateFlags flags, bool *ok = 0) const; + + /** + * Converts a localized time string to a QTime. + * This method will try to parse it with seconds, then without seconds. + * The bool pointed by ok will be false if the time entered was not valid. + * + * @param str the string we want to convert. + * @param ok the boolean that is set to false if it's not a valid time. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a QTime + */ + QTime readTime(const QString &str, bool* ok = 0) const; + + enum ReadTimeFlags { + WithSeconds = 0, // default (no flag set) + WithoutSeconds = 1 + }; // (maybe use this enum as a bitfield, if adding independent features?) + /** + * Converts a localized time string to a QTime. + * This method is stricter than readTime(str,&ok): it will either accept + * a time with seconds or a time without seconds. + * Use this method when the format is known by the application. + * + * @param str the string we want to convert. + * @param flags whether the time string is expected to contain seconds or not. + * @param ok the boolean that is set to false if it's not a valid time. + * If @p ok is 0, it will be ignored + * + * @return The string converted to a QTime + * @since 3.2 + */ + QTime readTime(const QString &str, ReadTimeFlags flags, bool *ok = 0) const; + + /** + * Returns the language used by this object. The domain AND the + * library translation must be available in this language. + * @ref defaultLanguage() is returned by default, if no other available. + * + * @return The currently used language. + */ + QString language() const; + + /** + * Returns the country code of the country where the user lives. + * @ref defaultCountry() is returned by default, if no other available. + * + * @return The country code for the user. + */ + QString country() const; + + /** + * Returns the preferred languages as ISO 639-1 codes. This means + * that information about country is removed. If the internal language + * code might be represented by more than one 639-1 code, they will all be + * listed (but only once). + * + * If the selected languages are "nn, nb, pt_BR", you will get: + * "nn, no, nb, pt". + * + * @return List of language codes + * + * @see languageList + */ + QStringList languagesTwoAlpha() const; + + /** + * Returns the languages selected by user. The codes returned here is the + * internal language codes. + * + * @return List of language codes + * + * @see languagesTwoAlpha + */ + QStringList languageList() const; + + /** + * Returns the user's preferred encoding. + * + * @return The name of the preferred encoding + * + * @see codecForEncoding + * @see encodingMib + */ + const char * encoding() const; + + /** + * Returns the user's preferred encoding. + * + * @return The Mib of the preferred encoding + * + * @see encoding + * @see codecForEncoding + */ + int encodingMib() const; + /** + * Returns the user's preferred encoding. Should never be NULL. + * + * @return The codec for the preferred encoding + * + * @see encoding + * @see encodingMib + */ + QTextCodec * codecForEncoding() const; + + /** + * Returns the file encoding. + * + * @return The Mib of the file encoding + * + * @see QFile::encodeName + * @see QFile::decodeName + */ + int fileEncodingMib() const; + + /** + * Changes the current date format. + * + * The format of the date is a string which contains variables that will + * be replaced: + * @li %Y with the century (e.g. "19" for "1984") + * @li %y with the lower 2 digits of the year (e.g. "84" for "1984") + * @li %n with the month (January="1", December="12") + * @li %m with the month with two digits (January="01", December="12") + * @li %e with the day of the month (e.g. "1" on the first of march) + * @li %d with the day of the month with two digits(e.g. "01" on the first of march) + * @li %b with the short form of the month (e.g. "Jan" for January) + * @li %a with the short form of the weekday (e.g. "Wed" for Wednesday) + * @li %A with the long form of the weekday (e.g. "Wednesday" for Wednesday) + * Everything else in the format string will be taken as is. + * For example, March 20th 1989 with the format "%y:%m:%d" results + * in "89:03:20". + * + * @param format The new date format + */ + void setDateFormat(const QString & format); + /** + * Changes the current short date format. + * + * The format of the date is a string which contains variables that will + * be replaced: + * @li %Y with the century (e.g. "19" for "1984") + * @li %y with the lower 2 digits of the year (e.g. "84" for "1984") + * @li %n with the month (January="1", December="12") + * @li %m with the month with two digits (January="01", December="12") + * @li %e with the day of the month (e.g. "1" on the first of march) + * @li %d with the day of the month with two digits(e.g. "01" on the first of march) + * @li %b with the short form of the month (e.g. "Jan" for January) + * @li %a with the short form of the weekday (e.g. "Wed" for Wednesday) + * @li %A with the long form of the weekday (e.g. "Wednesday" for Wednesday) + * Everything else in the format string will be taken as is. + * For example, March 20th 1989 with the format "%y:%m:%d" results + * in "89:03:20". + * + * @param format The new short date format + */ + void setDateFormatShort(const QString & format); + /** + * Changes the form of month name used in dates. + * + * @param possessive True if possessive forms should be used + * @since 3.1 + */ + void setDateMonthNamePossessive(bool possessive); + /** + * Changes the current time format. + * + * The format of the time is string a which contains variables that will + * be replaced: + * @li %H with the hour in 24h format and 2 digits (e.g. 5pm is "17", 5am is "05") + * @li %k with the hour in 24h format and one digits (e.g. 5pm is "17", 5am is "5") + * @li %I with the hour in 12h format and 2 digits (e.g. 5pm is "05", 5am is "05") + * @li %l with the hour in 12h format and one digits (e.g. 5pm is "5", 5am is "5") + * @li %M with the minute with 2 digits (e.g. the minute of 07:02:09 is "02") + * @li %S with the seconds with 2 digits (e.g. the minute of 07:02:09 is "09") + * @li %p with pm or am (e.g. 17.00 is "pm", 05.00 is "am") + * Everything else in the format string will be taken as is. + * For example, 5.23pm with the format "%H:%M" results + * in "17:23". + * + * @param format The new time format + */ + void setTimeFormat(const QString & format); + + /** + * @deprecated + * + * Please use @ref setWeekStartDay instead. + * + * Changes how KLocale defines the first day in week. + * + * @param start True if Monday is the first day in the week + */ + void setWeekStartsMonday(bool start); //### remove for KDE 4.0 + + /** + * Changes how KLocale defines the first day in week. + * + * @param day first day of the week (Monday=1..Sunday=7) as integer + * @since 3.1 + */ + void setWeekStartDay(int day); + /** + * Returns the currently selected date format. + * + * @return Current date format. + * @see setDateFormat() + */ + QString dateFormat() const; + /** + * Returns the currently selected short date format. + * + * @return Current short date format. + * @see setDateFormatShort() + */ + QString dateFormatShort() const; + /** + * Returns the currently selected time format. + * + * @return Current time format. + * @see setTimeFormat() + */ + QString timeFormat() const; + + /** + * Changes the symbol used to identify the decimal pointer. + * + * @param symbol The new decimal symbol. + */ + void setDecimalSymbol(const QString & symbol); + /** + * Changes the separator used to group digits when formating numbers. + * + * @param separator The new thousands separator. + */ + void setThousandsSeparator(const QString & separator); + /** + * Changes the sign used to identify a positive number. Normally this is + * left blank. + * + * @param sign Sign used for positive numbers. + */ + void setPositiveSign(const QString & sign); + /** + * Changes the sign used to identify a negative number. + * + * @param sign Sign used for negative numbers. + */ + void setNegativeSign(const QString & sign); + /** + * Changes the sign position used for positive monetary values. + * + * @param signpos The new sign position + */ + void setPositiveMonetarySignPosition(SignPosition signpos); + /** + * Changes the sign position used for negative monetary values. + * + * @param signpos The new sign position + */ + void setNegativeMonetarySignPosition(SignPosition signpos); + /** + * Changes the position where the currency symbol should be printed for + * positive monetary values. + * + * @param prefix True if the currency symbol should be prefixed instead of + * postfixed + */ + void setPositivePrefixCurrencySymbol(bool prefix); + /** + * Changes the position where the currency symbol should be printed for + * negative monetary values. + * + * @param prefix True if the currency symbol should be prefixed instead of + * postfixed + */ + void setNegativePrefixCurrencySymbol(bool prefix); + /** + * Changes the number of digits used when formating numbers. + * + * @param digits The default number of digits to use. + */ + void setFracDigits(int digits); + /** + * Changes the separator used to group digits when formating monetary values. + * + * @param separator The new thousands separator. + */ + void setMonetaryThousandsSeparator(const QString & separator); + /** + * Changes the symbol used to identify the decimal pointer for monetary + * values. + * + * @param symbol The new decimal symbol. + */ + void setMonetaryDecimalSymbol(const QString & symbol); + /** + * Changes the current currency symbol. + * + * @param symbol The new currency symbol + */ + void setCurrencySymbol(const QString & symbol); + + /** + * Returns the preferred page size for printing. + * + * @return The preferred page size, cast it to QPrinter::PageSize + */ + int pageSize() const; + + /** + * Changes the preferred page size when printing. + * + * @param paperFormat the new preferred page size in the format QPrinter::PageSize + */ + void setPageSize(int paperFormat); + + /** + * The Metric system will give you information in mm, while the + * Imperial system will give you information in inches. + */ + enum MeasureSystem { Metric, Imperial }; + + /** + * Returns which measuring system we use. + * + * @return The preferred measuring system + */ + MeasureSystem measureSystem() const; + + /** + * Changes the preferred measuring system. + * + * @return value The preferred measuring system + */ + void setMeasureSystem(MeasureSystem value); + + /** + * Adds another catalogue to search for translation lookup. + * This function is useful for extern libraries and/or code, + * that provides its own messages. + * + * If the catalogue does not exist for the chosen language, + * it will be ignored and en_US will be used. + * + * @param catalogue The catalogue to add. + */ + void insertCatalogue(const QString& catalogue); + + /** + * Removes a catalog for translation lookup. + * @param catalogue The catalogue to remove. + * @see insertCatalogue() + */ + void removeCatalogue(const QString &catalogue); + + /** + * Sets the active catalog for translation lookup. + * @param catalogue The catalogue to activate. + */ + void setActiveCatalogue(const QString &catalogue); + + /** + * Translates a message as a QTranslator is supposed to. + * The parameters are similar to i18n(), but the result + * value has other semantics (it can be QString::null) + * @since 3.1 + **/ + QString translateQt(const char *context, + const char *sourceText, + const char *message) const; + + /** + * Returns list of all known ISO 639-1 codes. + * @return a list of all language codes + * @since 3.1 + */ + QStringList allLanguagesTwoAlpha() const; + + /** + * Convert a ISO 639-1 code to a human readable form. + * @param code the language ISO 639-1 code + * @return the human readable form + * @since 3.1 + */ + QString twoAlphaToLanguageName(const QString &code) const; + + /** + * Returns list of all known country codes. + * @return a list of all country codes + * @since 3.1 + */ + QStringList allCountriesTwoAlpha() const; + + /** + * Convert a country code to a human readable form. + * @param code the country code + * @return the human readable form of the country name + * @since 3.1 + */ + QString twoAlphaToCountryName(const QString &code) const; + + + + int timezoneOffset( QString ); + QStringList timeZoneList() const; + void setDaylightSaving( bool, int , int ); + int localTimeOffset(const QDateTime &); + void setTimezone( const QString &timeZone ); + + void setHore24Format ( bool ); + void setWeekStartMonday( bool ); + void setIntDateFormat( int ); + void setLanguage( int ); + + + + /** + * Returns the parts of the parameter str understood as language setting + * the format is language_COUNTRY.charset + * + * @param str The string to split. + * @param language This will be set to the language part of the string. + * @param country This will be set to the country part of the string. + * @param charset This will be set to the charset part of the string. + */ + static void splitLocale(const QString & str, + QString & language, + QString & country, + QString & charset); + + /** + * Use this to as main catalogue for *all* KLocales, if not the appname + * will be used. This function is best to be the very first instruction + * in your program's main function as it only has an effect before the + * first KLocale object is created (and this is in common KDE applications + * quite early). + * + * @param catalogue Catalogue to override all other main catalogues. + */ + static void setMainCatalogue(const char *catalogue); + + /** + * Finds localized resource in resourceDir( rtype ) + \<lang> + fname. + * + * @param fname relative path to find + * @param rtype resource type to use + */ + static QString langLookup(const QString &fname, const char *rtype = "html"); + + /** + * Returns the name of the internal language. + * + * @return Name of the default language + */ + static QString defaultLanguage(); + + /** + * Returns the name of the default country. + * + * @return Name of the default country + */ + static QString defaultCountry(); + + + /** + * @internal Called from KConfigBackend to initialize language. + */ + static QString _initLanguage(KConfigBase *config); + +#ifdef KDE_NO_COMPAT +private: +#endif + /** + * @deprecated + * use formatMoney(double) + */ + QString formatMoney(const QString &numStr) const; + + /** + * @deprecated + * use formatNumber(double) + */ + QString formatNumber(const QString &numStr) const; + + /** + * @deprecated + * Use languageList() + * + * @return String containing language codes separated by colons + */ + QString languages() const; + + /** + * @deprecated + * @return True + */ + bool setCharset(const QString & charset); + + /** + * @deprecated + * @see encoding + */ + QString charset() const; + +protected: + /** + * @internal Creates a KLocale object for KGlobal and inits the locale + * pointer. + */ + static void initInstance(); + +private: + /** + * @internal Inits the localization part of the instance with the config + * object. + * + * @param config The configuration object used for init. + */ + void initFormat(KConfig *config); + + /** + * @internal Inits the language part of the instance with the given config + * object. It should be valid and contain the global entries. + * + * @param config The configuration object used for init + * @param useEnv True if we should use environment variables + */ + void initLanguage(KConfig * config, bool useEnv); + + /** + * @internal Figures out which encoding the user prefers. + * + * @param config The configuration object used for init + */ + void initEncoding(KConfig * config); + + /** + * @internal Figures out which catalogues to use. + * + * @param catalogue The name of the main catalogue + */ + void initCatalogue(const QString & catalogue); + + /** + * @internal Figures out which encoding the user prefers for filenames + * and sets up the appropriate QFile encoding and decoding functions. + */ + void initFileNameEncoding(KConfig *config); + + /** + * @internal A QFile filename encoding function (QFile::encodeFn). + */ + static QCString encodeFileNameUTF8( const QString & fileName ); + + /** + * @internal QFile filename decoding function (QFile::decodeFn). + */ + static QString decodeFileNameUTF8( const QCString & localFileName ); + + /** + * @internal Changes the file name of the catalogue to the correct + * one. + */ + void initCatalogue( KCatalogue & catalogue ); + + /** + * @internal Reads the language and format configuration form disk. + */ + void doBindInit(); + + /** + * @internal Ensures that the format configuration is read. + */ + void doFormatInit() const; + + /** + * @internal Reads the format configuration from disk. + */ + void initFormat(); + + /** + * @internal function used by the two translate versions + */ + QString translate_priv(const char *index, + const char *text, + const char ** original = 0) const; + + /** + * @internal function used to determine if we are using the en_US translation + */ + bool useDefaultLanguage() const; + + /** + * @internal Checks if the specified language is installed + */ + bool isLanguageInstalled(const QString & language) const; + + /** + * @internal Retrieves the file name of the catalogue, or QString::null + * if not found. + */ + static QString catalogueFileName(const QString & language, + const KCatalogue & catalogue); + + +private: + // Numbers and money + QString m_decimalSymbol; + QString m_thousandsSeparator; + QString m_currencySymbol; + QString m_monetaryDecimalSymbol; + QString m_monetaryThousandsSeparator; + QString m_positiveSign; + QString m_negativeSign; + int m_fracDigits; + SignPosition m_positiveMonetarySignPosition; + SignPosition m_negativeMonetarySignPosition; + + // Date and time + QString m_timeFormat; + QString m_dateFormat; + QString m_dateFormatShort; + + QString m_language; + QString m_country; + + QStringList mTimeZoneList; + bool daylightEnabled; + int mDaylightTZoffset; + int mNondaylightTZoffset; + bool mSouthDaylight; + int daylightStart, daylightEnd, mTimeZoneOffset; + bool mWeekStartsMonday; + bool mHourF24Format; + int mIntDateFormat; + int mLanguage; + + + + + bool m_weekStartsMonday; //### remove for KDE 4.0 + bool m_positivePrefixCurrencySymbol; + bool m_negativePrefixCurrencySymbol; + + KLocalePrivate *d; +}; + +#endif diff --git a/microkde/kdecore/kmdcodec.cpp b/microkde/kdecore/kmdcodec.cpp new file mode 100644 index 0000000..bc03569 --- a/dev/null +++ b/microkde/kdecore/kmdcodec.cpp @@ -0,0 +1,1127 @@ +/* + Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org> + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) + version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992. + RSA Data Security, Inc. Created 1991. All rights reserved. + + The KMD5 class is based on a C++ implementation of + "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by + Mordechai T. Abzug, Copyright (c) 1995. This implementation + passes the test-suite as defined in RFC 1321. + + The encoding and decoding utilities in KCodecs with the exception of + quoted-printable are based on the java implementation in HTTPClient + package by Ronald Tschal� Copyright (C) 1996-1999. + + The quoted-printable codec as described in RFC 2045, section 6.7. is by + Rik Hemsley (C) 2001. +*/ + +//US #include <config.h> + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <kdebug.h> +#include "kmdcodec.h" + +#define KMD5_S11 7 +#define KMD5_S12 12 +#define KMD5_S13 17 +#define KMD5_S14 22 +#define KMD5_S21 5 +#define KMD5_S22 9 +#define KMD5_S23 14 +#define KMD5_S24 20 +#define KMD5_S31 4 +#define KMD5_S32 11 +#define KMD5_S33 16 +#define KMD5_S34 23 +#define KMD5_S41 6 +#define KMD5_S42 10 +#define KMD5_S43 15 +#define KMD5_S44 21 + +const char KCodecs::Base64EncMap[64] = +{ + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, + 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, + 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F +}; + +const char KCodecs::Base64DecMap[128] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const char KCodecs::UUEncMap[64] = +{ + 0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F +}; + +const char KCodecs::UUDecMap[128] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const char KCodecs::hexChars[16] = +{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +const unsigned int KCodecs::maxQPLineLength = 70; + + +/******************************** KCodecs ********************************/ +// strchr(3) for broken systems. +static int rikFindChar(register const char * _s, const char c) +{ + register const char * s = _s; + + while (true) + { + if ((0 == *s) || (c == *s)) break; ++s; + if ((0 == *s) || (c == *s)) break; ++s; + if ((0 == *s) || (c == *s)) break; ++s; + if ((0 == *s) || (c == *s)) break; ++s; + } + + return s - _s; +} + +QCString KCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF) +{ + QByteArray out; + quotedPrintableEncode (in, out, useCRLF); + return QCString (out.data(), out.size()+1); +} + +QCString KCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF) +{ + if (str.isEmpty()) + return ""; + + QByteArray in (str.length()); + memcpy (in.data(), str.data(), str.length()); + return quotedPrintableEncode(in, useCRLF); +} + +void KCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& out, bool useCRLF) +{ + out.resize (0); + if (in.isEmpty()) + return; + + char *cursor; + const char *data; + unsigned int lineLength; + unsigned int pos; + + const unsigned int length = in.size(); + const unsigned int end = length - 1; + + + // Reasonable guess for output size when we're encoding + // mostly-ASCII data. It doesn't really matter, because + // the underlying allocation routines are quite efficient, + // but it's nice to have 0 allocations in many cases. + out.resize ((length*12)/10); + cursor = out.data(); + data = in.data(); + lineLength = 0; + pos = 0; + + for (unsigned int i = 0; i < length; i++) + { + unsigned char c (data[i]); + + // check if we have to enlarge the output buffer, use + // a safety margin of 16 byte + pos = cursor-out.data(); + if (out.size()-pos < 16) { + out.resize(out.size()+4096); + cursor = out.data()+pos; + } + + // Plain ASCII chars just go straight out. + + if ((c >= 33) && (c <= 126) && ('=' != c)) + { + *cursor++ = c; + ++lineLength; + } + + // Spaces need some thought. We have to encode them at eol (or eof). + + else if (' ' == c) + { + if + ( + (i >= length) + || + ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2])) + || + (!useCRLF && ('\n' == data[i + 1])))) + ) + { + *cursor++ = '='; + *cursor++ = '2'; + *cursor++ = '0'; + + lineLength += 3; + } + else + { + *cursor++ = ' '; + ++lineLength; + } + } + // If we find a line break, just let it through. + else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) || + (!useCRLF && ('\n' == c))) + { + lineLength = 0; + + if (useCRLF) { + *cursor++ = '\r'; + *cursor++ = '\n'; + ++i; + } else { + *cursor++ = '\n'; + } + } + + // Anything else is converted to =XX. + + else + { + *cursor++ = '='; + *cursor++ = hexChars[c / 16]; + *cursor++ = hexChars[c % 16]; + + lineLength += 3; + } + + // If we're approaching the maximum line length, do a soft line break. + + if ((lineLength > maxQPLineLength) && (i < end)) + { + if (useCRLF) { + *cursor++ = '='; + *cursor++ = '\r'; + *cursor++ = '\n'; + } else { + *cursor++ = '='; + *cursor++ = '\n'; + } + + lineLength = 0; + } + } + + out.truncate(cursor - out.data()); +} + +QCString KCodecs::quotedPrintableDecode(const QByteArray & in) +{ + QByteArray out; + quotedPrintableDecode (in, out); + return QCString (out.data(), out.size()+1); +} + +QCString KCodecs::quotedPrintableDecode(const QCString & str) +{ + if (str.isEmpty()) + return ""; + + QByteArray in (str.length()); + memcpy (in.data(), str.data(), str.length()); + return quotedPrintableDecode (in); +} + +void KCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& out) +{ + // clear out the output buffer + out.resize (0); + if (in.isEmpty()) + return; + + char *cursor; + const char *data; + const unsigned int length = in.size(); + + data = in.data(); + out.resize (length); + cursor = out.data(); + + for (unsigned int i = 0; i < length; i++) + { + char c(in.at(i)); + + if ('=' == c) + { + if (i < length - 2) + { + char c1 = in.at(i + 1); + char c2 = in.at(i + 2); + + if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) + { + // Soft line break. No output. + if ('\r' == c1) + i += 2; // CRLF line breaks + else + i += 1; + } + else + { + // =XX encoded byte. + + int hexChar0 = rikFindChar(hexChars, c1); + int hexChar1 = rikFindChar(hexChars, c2); + + if (hexChar0 < 16 && hexChar1 < 16) + { + *cursor++ = char((hexChar0 * 16) | hexChar1); + i += 2; + } + } + } + } + else + { + *cursor++ = c; + } + } + + out.truncate(cursor - out.data()); +} + +QCString KCodecs::base64Encode( const QCString& str, bool insertLFs ) +{ + if ( str.isEmpty() ) + return ""; + + QByteArray in (str.length()); + memcpy( in.data(), str.data(), str.length() ); + return base64Encode( in, insertLFs ); +} + +QCString KCodecs::base64Encode( const QByteArray& in, bool insertLFs ) +{ + QByteArray out; + base64Encode( in, out, insertLFs ); + return QCString( out.data(), out.size()+1 ); +} + +void KCodecs::base64Encode( const QByteArray& in, QByteArray& out, + bool insertLFs ) +{ + // clear out the output buffer + out.resize (0); + if ( in.isEmpty() ) + return; + + unsigned int sidx = 0; + unsigned int didx = 0; + const char* data = in.data(); + const unsigned int len = in.size(); + + unsigned int out_len = ((len+2)/3)*4; + + // Deal with the 76 characters or less per + // line limit specified in RFC 2045 on a + // pre request basis. + insertLFs = (insertLFs && out_len > 76); + if ( insertLFs ) + out_len += ((out_len-1)/76); + + int count = 0; + out.resize( out_len ); + + // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion + if ( len > 1 ) + { + while (sidx < len-2) + { + if ( insertLFs ) + { + if ( count && (count%76) == 0 ) + out.at(didx++) = '\n'; + count += 4; + } + out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = Base64EncMap[(data[sidx+2] >> 6) & 003 | + (data[sidx+1] << 2) & 077]; + out.at(didx++) = Base64EncMap[data[sidx+2] & 077]; + sidx += 3; + } + } + + if (sidx < len) + { + if ( insertLFs && (count > 0) && (count%76) == 0 ) + out.at(didx++) = '\n'; + + out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077]; + if (sidx < len-1) + { + out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = Base64EncMap[(data[sidx+1] << 2) & 077]; + } + else + { + out.at(didx++) = Base64EncMap[(data[sidx] << 4) & 077]; + } + } + + // Add padding + while (didx < out.size()) + { + out.at(didx) = '='; + didx++; + } +} + +QCString KCodecs::base64Decode( const QCString& str ) +{ + if ( str.isEmpty() ) + return ""; + + QByteArray in( str.length() ); + memcpy( in.data(), str.data(), str.length() ); + return base64Decode( in ); +} + +QCString KCodecs::base64Decode( const QByteArray& in ) +{ + QByteArray out; + base64Decode( in, out ); + return QCString( out.data(), out.size()+1 ); +} + +void KCodecs::base64Decode( const QByteArray& in, QByteArray& out ) +{ + out.resize(0); + if ( in.isEmpty() ) + return; + + unsigned int count = 0; + unsigned int len = in.size(), tail = len; + const char* data = in.data(); + + // Deal with possible *nix "BEGIN" marker!! + while ( count < len && (data[count] == '\n' || data[count] == '\r' || + data[count] == '\t' || data[count] == ' ') ) + count++; + + if ( QString(data+count).left(5).lower() == "begin" ) + { + count += 5; + while ( count < len && data[count] != '\n' && data[count] != '\r' ) + count++; + + while ( count < len && (data[count] == '\n' || data[count] == '\r') ) + count ++; + + data += count; + tail = (len -= count); + } + + // Find the tail end of the actual encoded data even if + // there is/are trailing CR and/or LF. + while ( data[tail-1] == '=' || data[tail-1] == '\n' || + data[tail-1] == '\r' ) + if ( data[--tail] != '=' ) len = tail; + + unsigned int outIdx = 0; + out.resize( (count=len) ); + for (unsigned int idx = 0; idx < count; idx++) + { + // Adhere to RFC 2045 and ignore characters + // that are not part of the encoding table. + unsigned char ch = data[idx]; + if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) || + (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=') + { + out.at(outIdx++) = Base64DecMap[ch]; + } + else + { + len--; + tail--; + } + } + + // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl; + + // 4-byte to 3-byte conversion + len = (tail>(len/4)) ? tail-(len/4) : 0; + unsigned int sidx = 0, didx = 0; + if ( len > 1 ) + { + while (didx < len-2) + { + out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003)); + out.at(didx+1) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017)); + out.at(didx+2) = (((out.at(sidx+2) << 6) & 255) | (out.at(sidx+3) & 077)); + sidx += 4; + didx += 3; + } + } + + if (didx < len) + out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003)); + + if (++didx < len ) + out.at(didx) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017)); + + // Resize the output buffer + if ( len == 0 || len < out.size() ) + out.resize(len); +} + +QCString KCodecs::uuencode( const QCString& str ) +{ + if ( str.isEmpty() ) + return ""; + + QByteArray in; + in.resize( str.length() ); + memcpy( in.data(), str.data(), str.length() ); + return uuencode( in ); +} + +QCString KCodecs::uuencode( const QByteArray& in ) +{ + QByteArray out; + uuencode( in, out ); + return QCString( out.data(), out.size()+1 ); +} + +void KCodecs::uuencode( const QByteArray& in, QByteArray& out ) +{ + out.resize( 0 ); + if( in.isEmpty() ) + return; + + unsigned int sidx = 0; + unsigned int didx = 0; + unsigned int line_len = 45; + + const char nl[] = "\n"; + const char* data = in.data(); + const unsigned int nl_len = strlen(nl); + const unsigned int len = in.size(); + + out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) ); + // split into lines, adding line-length and line terminator + while (sidx+line_len < len) + { + // line length + out.at(didx++) = UUEncMap[line_len]; + + // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion + for (unsigned int end = sidx+line_len; sidx < end; sidx += 3) + { + out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 | + (data[sidx+1] << 2) & 077]; + out.at(didx++) = UUEncMap[data[sidx+2] & 077]; + } + + // line terminator + //for (unsigned int idx=0; idx < nl_len; idx++) + //out.at(didx++) = nl[idx]; + memcpy(out.data()+didx, nl, nl_len); + didx += nl_len; + } + + // line length + out.at(didx++) = UUEncMap[len-sidx]; + // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion + while (sidx+2 < len) + { + out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 | + (data[sidx+1] << 2) & 077]; + out.at(didx++) = UUEncMap[data[sidx+2] & 077]; + sidx += 3; + } + + if (sidx < len-1) + { + out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 | + (data[sidx] << 4) & 077]; + out.at(didx++) = UUEncMap[(data[sidx+1] << 2) & 077]; + out.at(didx++) = UUEncMap[0]; + } + else if (sidx < len) + { + out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077]; + out.at(didx++) = UUEncMap[(data[sidx] << 4) & 077]; + out.at(didx++) = UUEncMap[0]; + out.at(didx++) = UUEncMap[0]; + } + + // line terminator + memcpy(out.data()+didx, nl, nl_len); + didx += nl_len; + + // sanity check + if ( didx != out.size() ) + out.resize( 0 ); +} + +QCString KCodecs::uudecode( const QCString& str ) +{ + if ( str.isEmpty() ) + return ""; + + QByteArray in; + in.resize( str.length() ); + memcpy( in.data(), str.data(), str.length() ); + return uudecode( in ); +} + +QCString KCodecs::uudecode( const QByteArray& in ) +{ + QByteArray out; + uudecode( in, out ); + return QCString( out.data(), out.size()+1 ); +} + +void KCodecs::uudecode( const QByteArray& in, QByteArray& out ) +{ + out.resize( 0 ); + if( in.isEmpty() ) + return; + + unsigned int sidx = 0; + unsigned int didx = 0; + unsigned int len = in.size(); + unsigned int line_len, end; + const char* data = in.data(); + + // Deal with *nix "BEGIN"/"END" separators!! + unsigned int count = 0; + while ( count < len && (data[count] == '\n' || data[count] == '\r' || + data[count] == '\t' || data[count] == ' ') ) + count ++; + + bool hasLF = false; + if ( QString( data+count).left(5).lower() == "begin" ) + { + count += 5; + while ( count < len && data[count] != '\n' && data[count] != '\r' ) + count ++; + + while ( count < len && (data[count] == '\n' || data[count] == '\r') ) + count ++; + + data += count; + len -= count; + hasLF = true; + } + + out.resize( len/4*3 ); + while ( sidx < len ) + { + // get line length (in number of encoded octets) + line_len = UUDecMap[ (unsigned char) data[sidx++]]; + // ascii printable to 0-63 and 4-byte to 3-byte conversion + end = didx+line_len; + char A, B, C, D; + if (end > 2) { + while (didx < end-2) + { + A = UUDecMap[(unsigned char) data[sidx]]; + B = UUDecMap[(unsigned char) data[sidx+1]]; + C = UUDecMap[(unsigned char) data[sidx+2]]; + D = UUDecMap[(unsigned char) data[sidx+3]]; + out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) ); + out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) ); + out.at(didx++) = ( ((C << 6) & 255) | (D & 077) ); + sidx += 4; + } + } + + if (didx < end) + { + A = UUDecMap[(unsigned char) data[sidx]]; + B = UUDecMap[(unsigned char) data[sidx+1]]; + out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) ); + } + + if (didx < end) + { + B = UUDecMap[(unsigned char) data[sidx+1]]; + C = UUDecMap[(unsigned char) data[sidx+2]]; + out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) ); + } + + // skip padding + while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r') + sidx++; + + // skip end of line + while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r')) + sidx++; + + // skip the "END" separator when present. + if ( hasLF && QString( data+sidx).left(3).lower() == "end" ) + break; + } + + if ( didx < out.size() ) + out.resize( didx ); +} + +/******************************** KMD5 ********************************/ +KMD5::KMD5() +{ + init(); +} + +KMD5::KMD5(const char *in, int len) +{ + init(); + update(in, len); +} + +KMD5::KMD5(const QByteArray& in) +{ + init(); + update( in ); +} + +KMD5::KMD5(const QCString& in) +{ + init(); + update( in ); +} + +void KMD5::update(const QByteArray& in) +{ + update(in.data(), int(in.size())); +} + +void KMD5::update(const QCString& in) +{ + update(in.data(), int(in.length())); +} + +void KMD5::update(const unsigned char* in, int len) +{ + if (len < 0) + len = qstrlen(reinterpret_cast<const char*>(in)); + + if (!len) + return; + + if (m_finalized) { + kdWarning() << "KMD5::update called after state was finalized!" << endl; + return; + } + + Q_UINT32 in_index; + Q_UINT32 buffer_index; + Q_UINT32 buffer_space; + Q_UINT32 in_length = static_cast<Q_UINT32>( len ); + + buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F); + + if ( (m_count[0] += (in_length << 3))<(in_length << 3) ) + m_count[1]++; + + m_count[1] += (in_length >> 29); + buffer_space = 64 - buffer_index; + + if (in_length >= buffer_space) + { + memcpy (m_buffer + buffer_index, in, buffer_space); + transform (m_buffer); + + for (in_index = buffer_space; in_index + 63 < in_length; + in_index += 64) + transform (reinterpret_cast<const unsigned char*>(in+in_index)); + + buffer_index = 0; + } + else + in_index=0; + + memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index); +} + +bool KMD5::update(QIODevice& file) +{ + char buffer[1024]; + int len; + + while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0) + update(buffer, len); + + return file.atEnd(); +} + +void KMD5::finalize () +{ + if (m_finalized) return; + + Q_UINT8 bits[8]; + Q_UINT32 index, padLen; + static unsigned char PADDING[64]= + { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + encode (bits, m_count, 8); + //memcpy( bits, m_count, 8 ); + + // Pad out to 56 mod 64. + index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + update (reinterpret_cast<const char*>(PADDING), padLen); + + // Append length (before padding) + update (reinterpret_cast<const char*>(bits), 8); + + // Store state in digest + encode (m_digest, m_state, 16); + //memcpy( m_digest, m_state, 16 ); + + // Fill sensitive information with zero's + memset ( (void *)m_buffer, 0, sizeof(*m_buffer)); + + m_finalized = true; +} + + +bool KMD5::verify( const KMD5::Digest& digest) +{ + finalize(); + return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest))); +} + +bool KMD5::verify( const QCString& hexdigest) +{ + finalize(); + return (0 == strcmp(hexDigest().data(), hexdigest)); +} + +const KMD5::Digest& KMD5::rawDigest() +{ + finalize(); + return m_digest; +} + +void KMD5::rawDigest( KMD5::Digest& bin ) +{ + finalize(); + memcpy( bin, m_digest, 16 ); +} + + +QCString KMD5::hexDigest() +{ + QCString s(33); + + finalize(); + sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], + m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], + m_digest[12], m_digest[13], m_digest[14], m_digest[15]); + + return s; +} + +void KMD5::hexDigest(QCString& s) +{ + finalize(); + s.resize(33); + sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], + m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], + m_digest[12], m_digest[13], m_digest[14], m_digest[15]); +} + +QCString KMD5::base64Digest() +{ + QByteArray ba(16); + + finalize(); + memcpy(ba.data(), m_digest, 16); + return KCodecs::base64Encode(ba); +} + + +void KMD5::init() +{ + d = 0; + reset(); +} + +void KMD5::reset() +{ + m_finalized = false; + + m_count[0] = 0; + m_count[1] = 0; + + m_state[0] = 0x67452301; + m_state[1] = 0xefcdab89; + m_state[2] = 0x98badcfe; + m_state[3] = 0x10325476; + + memset ( m_buffer, 0, sizeof(*m_buffer)); + memset ( m_digest, 0, sizeof(*m_digest)); +} + +void KMD5::transform( const unsigned char block[64] ) +{ + + Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16]; + + decode (x, block, 64); + //memcpy( x, block, 64 ); + +//US Q_ASSERT(!m_finalized); // not just a user error, since the method is private + ASSERT(!m_finalized); // not just a user error, since the method is private + + /* Round 1 */ + FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */ + + m_state[0] += a; + m_state[1] += b; + m_state[2] += c; + m_state[3] += d; + + memset ( static_cast<void *>(x), 0, sizeof(x) ); +} + +inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n) +{ + return (x << n) | (x >> (32-n)) ; +} + +inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) +{ + return (x & y) | (~x & z); +} + +inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) +{ + return (x & z) | (y & ~z); +} + +inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) +{ + return x ^ y ^ z; +} + +inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) +{ + return y ^ (x | ~z); +} + +void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, + Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) +{ + a += F(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +void KMD5::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, + Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac) +{ + a += G(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +void KMD5::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, + Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) +{ + a += H(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +void KMD5::II ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, + Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac ) +{ + a += I(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + + +void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len ) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(output, in, len); + +#else + Q_UINT32 i, j; + for (i = 0, j = 0; j < len; i++, j += 4) + { + output[j] = static_cast<Q_UINT8>((in[i] & 0xff)); + output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff)); + output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff)); + output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff)); + } +#endif +} + +// Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a +// multiple of 4. +void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(output, in, len); + +#else + Q_UINT32 i, j; + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = static_cast<Q_UINT32>(in[j]) | + (static_cast<Q_UINT32>(in[j+1]) << 8) | + (static_cast<Q_UINT32>(in[j+2]) << 16) | + (static_cast<Q_UINT32>(in[j+3]) << 24); +#endif +} diff --git a/microkde/kdecore/kmdcodec.h b/microkde/kdecore/kmdcodec.h new file mode 100644 index 0000000..2c4d611 --- a/dev/null +++ b/microkde/kdecore/kmdcodec.h @@ -0,0 +1,572 @@ +/* + Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org> + Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) + version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992. + RSA Data Security, Inc. Created 1991. All rights reserved. + + The KMD5 class is based on a C++ implementation of + "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by + Mordechai T. Abzug, Copyright (c) 1995. This implementation + passes the test-suite as defined in RFC 1321. + + The encoding and decoding utilities in KCodecs with the exception of + quoted-printable are based on the java implementation in HTTPClient + package by Ronald Tschalär Copyright (C) 1996-1999. + + The quoted-printable codec as described in RFC 2045, section 6.7. is by + Rik Hemsley (C) 2001. +*/ + +#ifndef _KMDBASE_H +#define _KMDBASE_H + +#define KBase64 KCodecs + +#include <qglobal.h> +#include <qstring.h> +#include <qiodevice.h> + +/** + * A wrapper class for the most commonly used encoding and + * decoding algorithms. Currently there is support for encoding + * and decoding input using base64, uu and the quoted-printable + * specifications. + * + * @sect Usage: + * + * <PRE> + * QCString input = "Aladdin:open sesame"; + * QCString result = KCodecs::base64Encode(input); + * cout << "Result: " << result.data() << endl; + * + * Output should be + * Result: QWxhZGRpbjpvcGVuIHNlc2FtZQ== + * </PRE> + * + * The above example makes use of the convenience functions + * (ones that accept/return null-terminated strings) to encode/decode + * a string. If what you need is to encode or decode binary data, then + * it is highly recommended that you use the functions that take an input + * and output QByteArray as arguments. These functions are specifically + * tailored for encoding and decoding binary data. + * + * @short A collection of commonly used encoding and decoding algorithms. + * @author Dawit Alemayehu <adawit@kde.org> + * @author Rik Hemsley <rik@kde.org> + */ +class KCodecs +{ +public: + + /** + * Encodes the given data using the quoted-printable algorithm. + * + * @param in data to be encoded. + * @param useCRLF if true the input data is expected to have + * CRLF line breaks and the output will have CRLF line + * breaks, too. + * @return quoted-printable encoded data. + */ + static QCString quotedPrintableEncode(const QByteArray & in, + bool useCRLF = true); + + /** + * @overload + * + * Same as above except it accepts a null terminated + * string instead an array. + * + * @param str data to be encoded. + * @param useCRLF if true the input data is expected to have + * CRLF line breaks and the output will have CRLF line + * breaks, too. + * @return quoted-printable encoded data. + */ + static QCString quotedPrintableEncode(const QCString & str, + bool useCRLF = true); + + /** + * Encodes the given data using the quoted-printable algorithm. + * + * Use this function if you want the result of the encoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is also the preferred method for encoding binary data. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in data to be encoded. + * @param out decoded data. + * @param useCRLF if true the input data is expected to have + * CRLF line breaks and the output will have CRLF line + * breaks, too. + * @return quoted-printable encoded data. + */ + static void quotedPrintableEncode(const QByteArray & in, QByteArray& out, + bool useCRLF); + + /** + * Decodes a quoted-printable encoded string. + * + * Accepts data with CRLF or standard unix line breaks. + * + * @param in the data to be decoded. + * @return decoded data. + */ + static QCString quotedPrintableDecode(const QByteArray & in); + + /** + * @overload + * + * Same as above except it accepts a null terminated + * string instead an array. + * + * @param str the data to be decoded. + * @return decoded data. + */ + static QCString quotedPrintableDecode(const QCString & str); + + /** + * Decodes a quoted-printable encoded data. + * + * Accepts data with CRLF or standard unix line breaks. + * Use this function if you want the result of the decoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is also the preferred method for decoding an encoded + * binary data. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in data to be encoded. + * @param out decoded data. + * + * @return quoted-printable encoded data. + */ + static void quotedPrintableDecode(const QByteArray & in, QByteArray& out); + + + /** + * Encodes the given data using the uuencode algorithm. + * + * The output is split into lines starting with the number of + * encoded octets in the line and ending with a newline. No + * line is longer than 45 octets (60 characters), excluding the + * line terminator. + * + * @param in the data to be uuencoded + * @return a uuencoded data. + */ + static QCString uuencode( const QByteArray& in ); + + /** + * @overload + * + * Same as the above functions except it accepts + * a null terminated string instead an array. + * + * @param str the string to be uuencoded. + * @return the encoded string. + */ + static QCString uuencode( const QCString& str ); + + /** + * Encodes the given data using the uuencode algorithm. + * + * Use this function if you want the result of the encoding + * to be placed in another array and cut down the number of + * copy operation that have to be performed in the process. + * This is the preffered method for encoding binary data. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in the data to be uuencoded. + * @param out the container for the uudecoded data. + */ + static void uuencode( const QByteArray& in, QByteArray& out ); + + /** + * Decodes the given data using the uuencode algorithm. + * + * Any 'begin' and 'end' lines like those generated by + * the utilities in unix and unix-like OS will be + * automatically ignored. + * + * @param in the data uuencoded data to be decoded. + * @return a decoded string. + */ + static QCString uudecode( const QByteArray& in ); + + /** + * @overload + * + * Same as the above functions except it accepts + * a null terminated string instead an array. + * + * @param str the string to be decoded. + * @return a uudecoded string. + */ + static QCString uudecode( const QCString& str ); + + /** + * Decodes the given data using the uudecode algorithm. + * + * Use this function if you want the result of the decoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is the preferred method for decoding binary data. + * + * Any 'begin' and 'end' lines like those generated by + * the utilities in unix and unix-like OS will be + * automatically ignored. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in the uuencoded-data to be decoded. + * @param out the container for the uudecoded data. + */ + static void uudecode( const QByteArray& in, QByteArray& out ); + + + /** + * Encodes the given data using the base64 algorithm. + * + * The boolean argument determines if the encoded data is + * going to be restricted to 76 characters or less per line + * as specified by RFC 2045. If @p insertLFs is true, then + * there will be 76 characters or less per line. + * + * @param in the data to be encoded. + * @param insertLFs limit the number of characters per line. + * + * @return a base64 encoded string. + */ + static QCString base64Encode( const QByteArray& in, bool insertLFs = false); + + /** + * @overload + * + * Same as the above functions except it accepts + * a null terminated string instead an array. + * + * @param str the string to be encoded. + * @param insertLFs limit the number of characters per line. + * @return the decoded string. + */ + static QCString base64Encode( const QCString& str, bool insertLFs = false ); + + /** + * Encodes the given data using the base64 algorithm. + * + * Use this function if you want the result of the encoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is also the preferred method for encoding binary data. + * + * The boolean argument determines if the encoded data is going + * to be restricted to 76 characters or less per line as specified + * by RFC 2045. If @p insertLFs is true, then there will be 76 + * characters or less per line. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in the data to be encoded using base64. + * @param out the container for the encoded data. + * @param insertLFs limit the number of characters per line. + */ + static void base64Encode( const QByteArray& in, QByteArray& out, + bool insertLFs = false ); + + /** + * Decodes the given data that was encoded using the + * base64 algorithm. + * + * @param in the base64-encoded data to be decoded. + * @return the decoded data. + */ + static QCString base64Decode( const QByteArray& in ); + + /** + * @overload + * + * Same as the above functions except it accepts + * a null terminated string instead an array. + * + * @param str the base64-encoded string. + * @return the decoded string. + */ + static QCString base64Decode( const QCString& str ); + + /** + * Decodes the given data that was encoded with the base64 + * algorithm. + * + * Use this function if you want the result of the decoding + * to be placed in another array which cuts down the number + * of copy operation that have to be performed in the process. + * This is also the preferred method for decoding an encoded + * binary data. + * + * NOTE: the output array is first reset and then resized + * appropriately before use, hence, all data stored in the + * output array will be lost. + * + * @param in the encoded data to be decoded. + * @param out the container for the decoded data. + */ + static void base64Decode( const QByteArray& in, QByteArray& out ); + + +private: + KCodecs(); + +private: + static const char UUEncMap[64]; + static const char UUDecMap[128]; + static const char Base64EncMap[64]; + static const char Base64DecMap[128]; + static const char hexChars[16]; + static const unsigned int maxQPLineLength; +}; + +class KMD5Private; +/** + * Provides an easy to use C++ implementation of RSA's + * MD5 algorithm. + * + * The default constructor is designed to provide much the same + * functionality as the most commonly used C-implementation, while + * the other three constructors are meant to further simplify the + * process of obtaining a digest by calculating the result in a + * single step. + * + * KMD5 is state-based, that means you can add new contents with + * update() as long as you didn't request the digest value yet. + * After the digest value was requested, the object is "finalized" + * and you have to call reset() to be able to do another calculation + * with it. The reason for this behaviour is that upon requesting + * the message digest KMD5 has to pad the received contents up to a + * 64 byte boundary to calculate its value. After this operation it + * is not possible to resume consuming data. + * + * @sect Usage: + * + * A common usage of this class: + * + * <PRE> + * const char* test1; + * KMD5::Digest rawResult; + * + * test1 = "This is a simple test."; + * KMD5 context (test1); + * cout << "Hex Digest output: " << context.hexDigest().data() << endl; + * </PRE> + * + * To cut down on the unnecessary overhead of creating multiple KMD5 + * objects, you can simply invoke @ref reset() to reuse the same object + * in making another calculation: + * + * <PRE> + * context.reset (); + * context.update ("TWO"); + * context.update ("THREE"); + * cout << "Hex Digest output: " << context.hexDigest().data() << endl; + * </PRE> + * + * @short An adapted C++ implementation of RSA Data Securities MD5 algorithm. + * @author Dirk Mueller <mueller@kde.org>, Dawit Alemayehu <adawit@kde.org> + */ + +class KMD5 +{ +public: + + typedef unsigned char Digest[16]; + + KMD5(); + + /** + * Constructor that updates the digest for the given string. + * + * @param in C string or binary data + * @param len if negative, calculates the length by using + * strlen on the first parameter, otherwise + * it trusts the given length (does not stop on NUL byte). + */ + KMD5(const char* in, int len = -1); + + /** + * @overload + * + * Same as above except it accepts a QByteArray as its argument. + */ + KMD5(const QByteArray& a ); + + /** + * @overload + * + * Same as above except it accepts a QByteArray as its argument. + */ + KMD5(const QCString& a ); + + /** + * Updates the message to be digested. Be sure to add all data + * before you read the digest. After reading the digest, you + * can <b>not</b> add more data! + * + * @param in message to be added to digest + * @param len the length of the given message. + */ + void update(const char* in, int len = -1) { update(reinterpret_cast<const unsigned char*>(in), len); } + + /** + * @overload + */ + void update(const unsigned char* in, int len = -1); + + /** + * @overload + * + * @param in message to be added to the digest (QByteArray). + */ + void update(const QByteArray& in ); + + /** + * @overload + * + * @param in message to be added to the digest (QByteArray). + */ + void update(const QCString& in ); + + /** + * @overload + * + * reads the data from an I/O device, i.e. from a file (QFile). + * + * NOTE that the file must be open for reading. + * + * @param file a pointer to FILE as returned by calls like f{d,re}open + * + * @returns false if an error occured during reading. + */ + bool update(QIODevice& file); + + /** + * Calling this function will reset the calculated message digest. + * Use this method to perform another message digest calculation + * without recreating the KMD5 object. + */ + void reset(); + + /** + * @return the raw representation of the digest + */ + const Digest& rawDigest (); + + /** + * Fills the given array with the binary representation of the + * message digest. + * + * Use this method if you do not want to worry about making + * copy of the digest once you obtain it. + * + * @param bin an array of 16 characters ( char[16] ) + */ + void rawDigest( KMD5::Digest& bin ); + + /** + * Returns the value of the calculated message digest in + * a hexadecimal representation. + */ + QCString hexDigest (); + + /** + * @overload + */ + void hexDigest(QCString&); + + /** + * Returns the value of the calculated message digest in + * a base64-encoded representation. + */ + QCString base64Digest (); + + /** + * returns true if the calculated digest for the given + * message matches the given one. + */ + bool verify( const KMD5::Digest& digest); + + /** + * @overload + */ + bool verify(const QCString&); + +protected: + /** + * Performs the real update work. Note + * that length is implied to be 64. + */ + void transform( const unsigned char buffer[64] ); + + /** + * finalizes the digest + */ + void finalize(); + +private: + KMD5(const KMD5& u); + KMD5& operator=(const KMD5& md); + + void init(); + void encode( unsigned char* output, Q_UINT32 *in, Q_UINT32 len ); + void decode( Q_UINT32 *output, const unsigned char* in, Q_UINT32 len ); + + Q_UINT32 rotate_left( Q_UINT32 x, Q_UINT32 n ); + Q_UINT32 F( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); + Q_UINT32 G( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); + Q_UINT32 H( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); + Q_UINT32 I( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z ); + void FF( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, + Q_UINT32 s, Q_UINT32 ac ); + void GG( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, + Q_UINT32 s, Q_UINT32 ac ); + void HH( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, + Q_UINT32 s, Q_UINT32 ac ); + void II( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x, + Q_UINT32 s, Q_UINT32 ac ); + +private: + Q_UINT32 m_state[4]; + Q_UINT32 m_count[2]; + Q_UINT8 m_buffer[64]; + Digest m_digest; + bool m_finalized; + + KMD5Private* d; +}; +#endif diff --git a/microkde/kdecore/ksharedptr.h b/microkde/kdecore/ksharedptr.h new file mode 100644 index 0000000..545058a --- a/dev/null +++ b/microkde/kdecore/ksharedptr.h @@ -0,0 +1,171 @@ +/* This file is part of the KDE libraries + Copyright (c) 1999 Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KSharedPTR_H +#define KSharedPTR_H + +/** + * Reference counting for shared objects. If you derive your object + * from this class, then you may use it in conjunction with + * @ref KSharedPtr to control the lifetime of your object. + * + * Specifically, all classes that derive from KShared have an internal + * counter keeping track of how many other objects have a reference to + * their object. If used with @ref KSharedPtr, then your object will + * not be deleted until all references to the object have been + * released. + * + * You should probably not ever use any of the methods in this class + * directly -- let the @ref KSharedPtr take care of that. Just derive + * your class from KShared and forget about it. + * + * @author Waldo Bastian <bastian@kde.org> + * @version $Id$ + */ +class KShared { +public: + /** + * Standard constructor. This will initialize the reference count + * on this object to 0. + */ + KShared() : count(0) { } + + /** + * Copy constructor. This will @em not actually copy the objects + * but it will initialize the reference count on this object to 0. + */ + KShared( const KShared & ) : count(0) { } + + /** + * Overloaded assignment operator. + */ + KShared &operator=(const KShared & ) { return *this; } + + /** + * Increases the reference count by one. + */ + void _KShared_ref() const { count++; } + + /** + * Releases a reference (decreases the reference count by one). If + * the count goes to 0, this object will delete itself. + */ + void _KShared_unref() const { if (!--count) delete this; } + + /** + * Return the current number of references held. + * + * @return Number of references + */ + int _KShared_count() const { return count; } + +protected: + virtual ~KShared() { } +private: + mutable int count; +}; + +/** + * Can be used to control the lifetime of an object that has derived + * @ref KShared. As long a someone holds a KSharedPtr on some @ref KShared + * object it won't become deleted but is deleted once its reference + * count is 0. This struct emulates C++ pointers perfectly. So just + * use it like a simple C++ pointer. + * + * KShared and KSharedPtr are preferred over QShared / QSharedPtr + * since they are more safe. + * + * @author Waldo Bastian <bastian@kde.org> + * @version $Id$ + */ +template< class T > +struct KSharedPtr +{ +public: +/** + * Creates a null pointer. + */ + KSharedPtr() + : ptr(0) { } + /** + * Creates a new pointer. + * @param the pointer + */ + KSharedPtr( T* t ) + : ptr(t) { if ( ptr ) ptr->_KShared_ref(); } + + /** + * Copies a pointer. + * @param the pointer to copy + */ + KSharedPtr( const KSharedPtr& p ) + : ptr(p.ptr) { if ( ptr ) ptr->_KShared_ref(); } + + /** + * Unreferences the object that this pointer points to. If it was + * the last reference, the object will be deleted. + */ + ~KSharedPtr() { if ( ptr ) ptr->_KShared_unref(); } + + KSharedPtr<T>& operator= ( const KSharedPtr<T>& p ) { + if ( ptr == p.ptr ) return *this; + if ( ptr ) ptr->_KShared_unref(); + ptr = p.ptr; + if ( ptr ) ptr->_KShared_ref(); + return *this; + } + KSharedPtr<T>& operator= ( T* p ) { + if ( ptr == p ) return *this; + if ( ptr ) ptr->_KShared_unref(); + ptr = p; + if ( ptr ) ptr->_KShared_ref(); + return *this; + } + bool operator== ( const KSharedPtr<T>& p ) const { return ( ptr == p.ptr ); } + bool operator!= ( const KSharedPtr<T>& p ) const { return ( ptr != p.ptr ); } + bool operator== ( const T* p ) const { return ( ptr == p ); } + bool operator!= ( const T* p ) const { return ( ptr != p ); } + bool operator!() const { return ( ptr == 0 ); } + operator T*() const { return ptr; } + + /** + * Returns the pointer. + * @return the pointer + */ + T* data() { return ptr; } + + /** + * Returns the pointer. + * @return the pointer + */ + const T* data() const { return ptr; } + + const T& operator*() const { return *ptr; } + T& operator*() { return *ptr; } + const T* operator->() const { return ptr; } + T* operator->() { return ptr; } + + /** + * Returns the number of references. + * @return the number of references + */ + int count() const { return ptr->_KShared_count(); } // for debugging purposes +private: + T* ptr; +}; + +#endif diff --git a/microkde/kdecore/kshell.cpp b/microkde/kdecore/kshell.cpp new file mode 100644 index 0000000..efc007a --- a/dev/null +++ b/microkde/kdecore/kshell.cpp @@ -0,0 +1,386 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2003 Oswald Buddenhagen <ossi@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kshell.h> + +#include <qfile.h> +#include <qdir.h> + +#include <stdlib.h> +#ifndef _WIN32_ +#include <pwd.h> +#endif +//US #include <sys/types.h> + +/*US +static int fromHex( QChar c ) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return -1; +} + +inline static bool isQuoteMeta( uint c ) +{ +#if 0 // it's not worth it, especially after seeing gcc's asm output ... + static const uchar iqm[] = { + 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 + }; // \'"$ + + return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); +#else + return c == '\\' || c == '\'' || c == '"' || c == '$'; +#endif +} + +inline static bool isMeta( uint c ) +{ + static const uchar iqm[] = { + 0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00, 0xd8, + 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38 + }; // \'"$`<>|;&(){}*?# + + return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); +} + +QStringList KShell::splitArgs( const QString &args, int flags, int *err ) +{ + QStringList ret; + bool firstword = flags & AbortOnMeta; + + for (uint pos = 0; ; ) { + QChar c; + do { + if (pos >= args.length()) + goto okret; + c = args.unicode()[pos++]; + } while (c.isSpace()); + QString cret; + if ((flags & TildeExpand) && c == '~') { + uint opos = pos; + for (; ; pos++) { + if (pos >= args.length()) + break; + c = args.unicode()[pos]; + if (c == '/' || c.isSpace()) + break; + if (isQuoteMeta( c )) { + pos = opos; + c = '~'; + goto notilde; + } + if ((flags & AbortOnMeta) && isMeta( c )) + goto metaerr; + } + QString ccret = homeDir( QConstString( args.unicode() + opos, pos - opos ).string() ); + if (ccret.isEmpty()) { + pos = opos; + c = '~'; + goto notilde; + } + if (pos >= args.length()) { + ret += ccret; + goto okret; + } + pos++; + if (c.isSpace()) { + ret += ccret; + firstword = false; + continue; + } + cret = ccret; + } + // before the notilde label, as a tilde does not match anyway + if (firstword) { + if (c == '_' || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { + uint pos2 = pos; + QChar cc; + do + cc = args[pos2++]; + while (cc == '_' || (cc >= 'A' && cc <= 'Z') || + (cc >= 'a' && cc <= 'z') || (cc >= '0' && cc <= '9')); + if (cc == '=') + goto metaerr; + } + } + notilde: + do { + if (c == '\'') { + uint spos = pos; + do { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + } while (c != '\''); + cret += QConstString( args.unicode() + spos, pos - spos - 1 ).string(); + } else if (c == '"') { + for (;;) { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + if (c == '"') + break; + if (c == '\\') { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + if (c != '"' && c != '\\' && + !((flags & AbortOnMeta) && (c == '$' || c == '`'))) + cret += '\\'; + } else if ((flags & AbortOnMeta) && (c == '$' || c == '`')) + goto metaerr; + cret += c; + } + } else if (c == '$' && args[pos] == '\'') { + pos++; + for (;;) { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + if (c == '\'') + break; + if (c == '\\') { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + switch (c) { + case 'a': cret += '\a'; break; + case 'b': cret += '\b'; break; + case 'e': cret += '\033'; break; + case 'f': cret += '\f'; break; + case 'n': cret += '\n'; break; + case 'r': cret += '\r'; break; + case 't': cret += '\t'; break; + case '\\': cret += '\\'; break; + case '\'': cret += '\''; break; + case 'c': cret += args[pos++] & 31; break; + case 'x': + { + int hv = fromHex( args[pos] ); + if (hv < 0) { + cret += "\\x"; + } else { + int hhv = fromHex( args[++pos] ); + if (hhv > 0) { + hv = hv * 16 + hhv; + pos++; + } + cret += QChar( hv ); + } + break; + } + default: + if (c >= '0' && c <= '7') { + int hv = c - '0'; + for (int i = 0; i < 2; i++) { + c = args[pos]; + if (c < '0' || c > '7') + break; + hv = hv * 8 + (c - '0'); + pos++; + } + cret += QChar( hv ); + } else { + cret += '\\'; + cret += c; + } + break; + } + } else + cret += c; + } + } else { + if (c == '\\') { + if (pos >= args.length()) + goto quoteerr; + c = args.unicode()[pos++]; + if (!c.isSpace() && + !((flags & AbortOnMeta) ? isMeta( c ) : isQuoteMeta( c ))) + cret += '\\'; + } else if ((flags & AbortOnMeta) && isMeta( c )) + goto metaerr; + cret += c; + } + if (pos >= args.length()) + break; + c = args.unicode()[pos++]; + } while (!c.isSpace()); + ret += cret; + firstword = false; + } + + okret: + if (err) + *err = NoError; + return ret; + + quoteerr: + if (err) + *err = BadQuoting; + return QStringList(); + + metaerr: + if (err) + *err = FoundMeta; + return QStringList(); +} + +inline static bool isSpecial( uint c ) +{ + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0xdd, 0x07, 0x00, 0xd8, + 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38 + }; // 0-32 \'"$`<>|;&(){}*?# + + return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))); +} + +QString KShell::joinArgs( const QStringList &args ) +{ + QChar q( '\'' ); + QString ret; + for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it) { + if (!ret.isEmpty()) + ret += ' '; + if (!(*it).length()) + ret.append( q ).append( q ); + else { + for (uint i = 0; i < (*it).length(); i++) + if (isSpecial((*it).unicode()[i])) { + QString tmp(*it); + tmp.replace( q, "'\\''" ); + ret += q; + tmp += q; + ret += tmp; + goto ex; + } + ret += *it; + ex: ; + } + } + return ret; +} + +QString KShell::joinArgs( const char * const *args, int nargs ) +{ + if (!args) + return QString::null; // well, QString::empty, in fact. qt sucks ;) + QChar q( '\'' ); + QString ret; + for (const char * const *argp = args; nargs && *argp; argp++, nargs--) { + if (!ret.isEmpty()) + ret += ' '; + if (!**argp) + ret.append( q ).append( q ); + else { + QString tmp( QFile::decodeName( *argp ) ); + for (uint i = 0; i < tmp.length(); i++) + if (isSpecial(tmp.unicode()[i])) { + tmp.replace( q, "'\\''" ); + ret += q; + tmp += q; + ret += tmp; + goto ex; + } + ret += tmp; + ex: ; + } + } + return ret; +} + +QString KShell::joinArgsDQ( const QStringList &args ) +{ + QChar q( '\'' ), sp( ' ' ), bs( '\\' ); + QString ret; + for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it) { + if (!ret.isEmpty()) + ret += sp; + if (!(*it).length()) + ret.append( q ).append( q ); + else { + for (uint i = 0; i < (*it).length(); i++) + if (isSpecial((*it).unicode()[i])) { + ret.append( '$' ).append( q ); + for (uint pos = 0; pos < (*it).length(); pos++) { + int c = (*it).unicode()[pos]; + if (c < 32) { + ret += bs; + switch (c) { + case '\a': ret += 'a'; break; + case '\b': ret += 'b'; break; + case '\033': ret += 'e'; break; + case '\f': ret += 'f'; break; + case '\n': ret += 'n'; break; + case '\r': ret += 'r'; break; + case '\t': ret += 't'; break; + case '\034': ret += 'c'; ret += '|'; break; + default: ret += 'c'; ret += c + '@'; break; + } + } else { + if (c == '\'' || c == '\\') + ret += bs; + ret += c; + } + } + ret.append( q ); + goto ex; + } + ret += *it; + ex: ; + } + } + return ret; +} +*/ + +QString KShell::tildeExpand( const QString &fname ) +{ + if (fname[0] == '~') { + int pos = fname.find( '/' ); + if (pos < 0) + return homeDir( QConstString( (QChar*)(fname.unicode() + 1), fname.length() - 1 ).string() ); + QString ret = homeDir( QConstString( (QChar*)(fname.unicode() + 1), pos - 1 ).string() ); + if (!ret.isNull()) + ret += QConstString( (QChar*)(fname.unicode() + pos), fname.length() - pos ).string(); + return ret; + } + return fname; +} + +QString KShell::homeDir( const QString &user ) +{ +#ifdef _WIN32_ + return QDir::homeDirPath(); +#else + if (user.isEmpty()) + return QFile::decodeName( getenv( "HOME" ) ); + struct passwd *pw = getpwnam( QFile::encodeName( user ).data() ); + if (!pw) + return QString::null; + return QFile::decodeName( pw->pw_dir ); +#endif +} diff --git a/microkde/kdecore/kshell.h b/microkde/kdecore/kshell.h new file mode 100644 index 0000000..35d8217 --- a/dev/null +++ b/microkde/kdecore/kshell.h @@ -0,0 +1,143 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2003 Oswald Buddenhagen <ossi@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef _KSHELL_H +#define _KSHELL_H + +#include <qstring.h> +#include <qstringlist.h> + +/** + * Provides some basic POSIX shell and bash functionality. + * @see KStringHandler + */ +namespace KShell { + + /** + * Flags for @ref splitArgs(). + */ + enum Options { + NoOptions = 0, + + /** + * Perform tilde expansion. + */ + TildeExpand = 1, + + /** + * Bail out if a non-quoting and not quoted shell meta character is encoutered. + * Meta characters are the command separators @p semicolon and @p ampersand, + * the redirection symbols @p less-than, @p greater-than and the @p pipe @p symbol, + * the grouping symbols opening and closing @p parens and @p braces, the command + * substitution symbol @p backquote, the generic substitution symbol @p dollar + * (if not followed by an apostrophe), the wildcards @p asterisk and + * @p question @p mark, and the comment symbol @p hash @p mark. Additionally, + * a variable assignment in the first word is recognized. + */ + AbortOnMeta = 2 + }; + + /** + * Status codes from @ref splitArgs() + */ + enum Errors { + /** + * Success. + */ + NoError = 0, + + /** + * Indicates a parsing error, like an unterminated quoted string. + */ + BadQuoting, + + /** + * The AbortOnMeta flag was set and a shell meta character + * was encoutered. + */ + FoundMeta + }; + + /** + * Splits @p cmd according to POSIX shell word splitting and quoting rules. + * Can optionally perform tilde expansion and/or abort if it finds shell + * meta characters it cannot process. + * + * @param cmd the command to split + * @param flags operation flags, see @ref Options + * @param err if not NULL, a status code will be stored at the pointer + * target, see @ref Errors + * @return a list of unquoted words or an empty list if an error occured + */ + QStringList splitArgs( const QString &cmd, int flags = 0, int *err = 0 ); + + /** + * Quotes and joins @p args together according to POSIX shell rules. + * + * @param args a list of strings to quote and join + * @return a command suitable for shell execution + */ + QString joinArgs( const QStringList &args ); + + /** + * Same as above, but $'' is used instead of '' for the quoting. + * The output is suitable for @ref splitArgs(), bash, zsh and possibly + * other bourne-compatible shells, but not for plain sh. The advantage + * is, that control characters (ASCII less than 32) are escaped into + * human-readable strings. + * + * @param args a list of strings to quote and join + * @return a command suitable for shell execution + */ + QString joinArgsDQ( const QStringList &args ); + + /** + * Quotes and joins @p argv together according to POSIX shell rules. + * + * @param argv an array of c strings to quote and join. + * The strings are expected to be in local-8-bit encoding. + * @param argc maximal number of strings in @p argv. if not supplied, + * @p argv must be null-terminated. + * @return a command suitable for shell execution + */ + QString joinArgs( const char * const *argv, int argc = -1 ); + + /** + * Performs tilde expansion on @p path. Interprets "~/path" and + * "~user/path". + * + * @param path the path to tilde-expand + * @return the expanded path + */ + QString tildeExpand( const QString &path ); + + /** + * Obtain a @p user's home directory. + * + * @param user The name of the user whose home dir should be obtained. + * An empty string denotes the current user. + * @return The user's home directory. + */ + QString homeDir( const QString &user ); + +} + + +#endif /* _KSHELL_H */ diff --git a/microkde/kdecore/kshortcut.h b/microkde/kdecore/kshortcut.h new file mode 100644 index 0000000..4813734 --- a/dev/null +++ b/microkde/kdecore/kshortcut.h @@ -0,0 +1,846 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __KSHORTCUT_H +#define __KSHORTCUT_H +/*US +#include <qkeysequence.h> +#include <qstring.h> + +class QKeyEvent; +class KKeyNative; +*/ +/** +* A KKey object represents a single key with possible modifiers +* (Shift, Ctrl, Alt, Win). It can represent both keys which are +* understood by Qt as well as those which are additionally supported +* by the underlying system (e.g. X11). +* @see KKeyNative +* @see KKeySequence +* @see KShortcut +*/ +/*US +class KKey +{ + public: +*/ + /** + * The number of flags. + * @see ModFlag + */ +/*US + enum { MOD_FLAG_COUNT = 4 }; + enum { QtWIN = (Qt::ALT << 1) }; +*/ + /** + * Flags to represent the modifiers. You can combine modifiers + * by ORing them. + */ +/*US + enum ModFlag { + SHIFT = 0x01, + CTRL = 0x02, + ALT = 0x04, + WIN = 0x08 + }; +*/ + /** + * Creates a new null KKey. + * @see clear() + * @see isNull() + * @see null() + */ +//US KKey(); + + /** + * Creates a new key for the given Qt key code. + * @param keyQt the qt keycode + * @see Qt::Key + */ +//US KKey( int keyQt ); + + /** + * Creates a new key from the first key code of the given key sequence. + * @param keySeq the key sequence that contains the key + */ +//US KKey( const QKeySequence& keySeq ); + + /** + * Extracts the key from the given key event. + * @param keyEvent the key event to get the key from + */ +//US KKey( const QKeyEvent* keyEvent ); + + /** + * Copy constructor. + */ +//US KKey( const KKey& key ); + + /** + * Creates a new key from the given description. The form of the description + * is "[modifier+[modifier+]]+key", for example "e", "CTRL+q" or + * "CTRL+ALT+DEL". Allowed modifiers are "SHIFT", "CTRL", "ALT", "WIN" and + * "META". "WIN" and "META" are equivalent. Modifiers are not case-sensitive. + * @param key the description of the key + * @see KKeyServer::Sym::init() + */ +//US KKey( const QString& key ); + /** + * @internal + */ +//US KKey( uint key, uint mod ); +//US ~KKey(); + + // Initialization methods + /** + * Clears the key. The key is null after calling this function. + * @see isNull() + */ +//US void clear(); + + /** + * Initializes the key with the given Qt key code. + * @param keyQt the qt keycode + * @return true if successful, false otherwise + * @see Qt::Key + */ +//US bool init( int keyQt ); + + /** + * Initializes the key with the first key code of the given key sequence. + * @param keySeq the key sequence that contains the key + * @return true if successful, false otherwise + */ +//US bool init( const QKeySequence& keySeq ); + + /** + * Initializes the key by extracting the code from the given key event. + * @param keyEvent the key event to get the key from + * @return true if successful, false otherwise + */ +//US bool init( const QKeyEvent* keyEvent ); + + /** + * Copies the given key. + * @param key the key to copy + * @return true if successful, false otherwise + */ +//US bool init( const KKey& key ); + + /** + * Initializes the key with the given description. The form of the description + * is "[modifier+[modifier+]]+key", for example "e", "CTRL+q" or + * "CTRL+ALT+DEL". Allowed modifiers are "SHIFT", "CTRL", "ALT", "WIN" and + * "META". "WIN" and "META" are equivalent. Modifiers are not case-sensitive. + * @param key the description of the key + * @return true if successful, false otherwise + * @see KKeyServer::Sym::init() + */ +//US bool init( const QString& ); + + /** + * @internal + */ +//US bool init( uint key, uint mod ); + + /** + * Copies the key. + */ +//US KKey& operator =( const KKey& key ) +//US { init( key ); return *this; } + + // Query methods. + /** + * Returns true if the key is null (after @ref clear() or empty + * constructor). + * @return true if the key is null + * @see clear() + * @see null() + */ +//US bool isNull() const; + + /** + * @internal + */ +//US bool isValidQt() const; + + /** + * @internal + */ +//US bool isValidNative() const; + + /** + * @internal + */ +//US uint sym() const; + /** + * @internal + */ +//US uint modFlags() const; + + // Comparison Methods + /** + * Compares this key with the given KKey object. Returns a negative + * number if the given KKey is larger, 0 if they are equal and + * a positive number this KKey is larger. The returned value + * is the difference between the symbol or, if the symbols + * are equal, the difference between the encoded modifiers. + * @param key the key to compare with this key + * @return a negative number if the given KKey is larger, 0 if + * they are equal and a positive number this KKey is larger + */ +//US int compare( const KKey& key ) const; + + /** + * Compares the symbol and modifiers of both keys. + * @see compare() + */ +//US bool operator == ( const KKey& key ) const +//US { return compare( key ) == 0; } + /** + * Compares the symbol and modifiers of both keys. + * @see compare() + */ +//US bool operator != ( const KKey& key ) const +//US { return compare( key ) != 0; } + /** + * Compares the symbol and modifiers of both keys. + * @see compare() + */ +//US bool operator < ( const KKey& key ) const +//US { return compare( key ) < 0; } + + // Conversion methods. + /** + * Returns the qt key code. + * @return the qt key code or 0 if there is no key set. + * @see Qt::Key + */ +//US int keyCodeQt() const; + + /** + * Returns a human-readable representation of the key in the form + * "modifier+key". + * @return the string representation of the key + */ +//US QString toString() const; + + /** + * @internal + */ +//US QString toStringInternal() const; + + // Operation methods + /** + * @internal + */ +//US void simplify(); + + /** + * Returns a null key. + * @return the null key + * @see isNull() + * @see clear() + */ +//US static KKey& null(); + + /** + * Returns a user-readable representation of the given modifiers. + * @param f the modifiers to convert + * @return the string representation of the modifiers + */ +//US static QString modFlagLabel( ModFlag f ); + +//US private: + /* + * Under X11, m_key will hold an X11 key symbol. + * For Qt/Embedded, it will hold the Qt key code. + */ + /** + * Returns the native key symbol value key. Under X11, this is the X + * keycode. Under Qt/Embedded, this is the Qt keycode. + * @see /usr/include/X11/keysymdef.h + * @see qnamespace.h + */ +//US uint m_sym; + /** + * m_mod holds the + */ +//US uint m_mod; + +//US private: +//US friend class KKeyNative; +//US}; + +/** +* A KKeySequence object holds a sequence of up to 4 keys. +* Ex: Ctrl+X,I +* @see KKey +* @see KShortcut +*/ + +//USclass KKeySequence +//US{ +//US public: + /// Defines the maximum length of the key sequence +//US enum { MAX_KEYS = 4 }; + + /** + * Create a new null key sequence. + * @see isNull() + * @see null() + * @see clear() + */ +//US KKeySequence(); + + /** + * Copies the given qt key sequence. + * @param keySeq the qt key sequence to copy + */ +//US KKeySequence( const QKeySequence& keySeq ); + + /** + * Create a new key sequence that only contains the given key. + * @param key the key to add + */ +//US KKeySequence( const KKey& key ); + + /** + * Create a new key sequence that only contains the given key. + * @param key the key to add + */ +//US KKeySequence( const KKeyNative& key ); + + /** + * Copies the given key sequence. + * @param keySeq the key sequence to copy + */ +//US KKeySequence( const KKeySequence& keySeq ); + + /** + * Creates a new key sequence that contains the given key sequence. + * The description consists of comma-separated keys as + * required by @ref KKey::KKey(const QString&). + * @param keySeq the description of the key + * @see KKeyServer::Sym::init() + * @see KKey::KKey(const QString&) + */ +//US KKeySequence( const QString& keySeq ); + +//US ~KKeySequence(); + + /** + * Clears the key sequence. The key sequence is null after calling this + * function. + * @see isNull() + */ +//US void clear(); + + /** + * Copies the given qt key sequence over this key sequence. + * @param keySeq the qt key sequence to copy + * @return true if successful, false otherwise + */ +//US bool init( const QKeySequence& keySeq ); + + /** + * Initializes the key sequence to only contain the given key. + * @param key the key to set + * @return true if successful, false otherwise + */ +//US bool init( const KKey& key ); + + /** + * Initializes the key sequence to only contain the given key. + * @param key the key to set + * @return true if successful, false otherwise + */ +//US bool init( const KKeyNative& key ); + + /** + * Copies the given key sequence over this key sequence. + * @param keySeq the key sequence to copy + * @return true if successful, false otherwise + */ +//US bool init( const KKeySequence& keySeq ); + + /** + * Initializes this key sequence to contain the given key sequence. + * The description consists of comma-separated keys as + * required by @ref KKey::KKey(const QString&). + * @param key the description of the key + * @return true if successful, false otherwise + * @see KKeyServer::Sym::init() + * @see KKey::KKey(const QString&) + */ +//US bool init( const QString& key ); + + /** + * Copy the given key sequence into this sequence. + */ +//US KKeySequence& operator =( const KKeySequence& seq ) +//US { init( seq ); return *this; } + + /** + * Returns the number of key strokes of this sequence. + * @return the number of key strokes + * @see MAX_KEYS + */ +//US uint count() const; + + /** + * Return the @p i'th key of this sequence, or a null key if there + * are less then i keys. + * @param i the key to retrieve + * @return the @p i'th key, or @ref KKey::null() if there are less + * than i keys + * @see MAX_KEYS + */ +//US const KKey& key( uint i ) const; + + /** + * @internal + */ +//US bool isTriggerOnRelease() const; + + /** + * Sets the @p i'th key of the sequence. You can not introduce gaps + * in a sequence, so you must use an @p i <= @ref count(). Also note that + * the maximum length of a key sequence is @ref MAX_KEYS. + * @param i the position of the new key (<= @ref count(), <= @ref MAX_KEYS) + * @param key the key to set + * @return true if successful, false otherwise + */ +//US bool setKey( uint i, const KKey& key ); + + /** + * @internal + */ +//US void setTriggerOnRelease( bool ); + + /** + * Returns true if the key sequence is null (after @ref clear() or empty + * constructor). + * @return true if the key sequence is null + * @see clear() + * @see null() + */ +//US bool isNull() const; + + /** + * Returns true if this key sequence begins with the given sequence. + * @param keySeq the key sequence to search + * @return true if this key sequence begins with the given sequence + */ +//US bool startsWith( const KKeySequence& keySeq ) const; + + /** + * Compares this object with the given key sequence. Returns a negative + * number if the given KKeySequence is larger, 0 if they are equal and + * a positive number this KKeySequence is larger. Key sequences are + * compared by comparing the individual keys, starting from the beginning + * until an unequal key has been found. If a sequence contains more + * keys, it is considered larger. + * @param keySeq the key sequence to compare to + * @return a negative number if the given KKeySequence is larger, 0 if + * they are equal and a positive number this KKeySequence is larger + * @see KKey::sequence + */ +//US int compare( const KKeySequence& keySeq ) const; + + /** + * Compares the keys of both sequences. + * @see compare() + */ +//US bool operator == ( const KKeySequence& seq ) const +//US { return compare( seq ) == 0; } + + /** + * Compares the keys of both sequences. + * @see compare() + */ +//US bool operator != ( const KKeySequence& seq ) const +//US { return compare( seq ) != 0; } + + /** + * Compares the keys of both sequences. + * @see compare() + */ +//US bool operator < ( const KKeySequence& seq ) const +//US { return compare( seq ) < 0; } + // TODO: consider adding Qt::SequenceMatch matches(...) methods for QKeySequence equivalence + + /** + * Converts this key sequence to a QKeySequence. + * @return the QKeySequence + */ +//US QKeySequence qt() const; + + /** + * Returns the qt key code of the first key. + * @return the qt key code of the first key + * @see Qt::Key + * @see KKey::keyCodeQt() + */ +//US int keyCodeQt() const; + + /** + * Returns the key sequence as a number of key presses as + * returned by @ref KKey::toString(), seperated by commas. + * @return the string represenation of this key sequence + * @see KKey::toString() + */ +//US QString toString() const; + + /** + * @internal + */ +//US QString toStringInternal() const; + + /** + * Returns a null key sequence. + * @return the null key sequence + * @see isNull() + * @see clear() + */ +//US static KKeySequence& null(); + +//US protected: +//US uchar m_nKeys; +//US uchar m_bTriggerOnRelease; + // BCI: m_rgvar should be renamed to m_rgkey for KDE 4.0 +//US KKey m_rgvar[MAX_KEYS]; + +//US private: +//US class KKeySequencePrivate* d; +//US friend class KKeyNative; +//US}; + +/** +* The KShortcut class is used to represent a keyboard shortcut to an action. +* A shortcut is normally a single key with modifiers, such as Ctrl+V. +* A KShortcut object may also contain an alternate key which will also +* activate the action it's associated to, as long as no other actions have +* defined that key as their primary key. Ex: Ctrl+V;Shift+Insert. +*/ + +class KShortcut +{ + public: + /** + * The maximum number of key sequences that can be contained in + * a KShortcut. + */ + enum { MAX_SEQUENCES = 2 }; + + /** + * Creates a new null shortcut. + * @see null() + * @see isNull() + * @see clear() + */ + KShortcut() {} + + /** + * Creates a new shortcut with the given Qt key code + * as the only key sequence. + * @param keyQt the qt keycode + * @see Qt::Key + */ + KShortcut( int keyQt ) {} + + /** + * Creates a new shortcut that contains only the given qt key + * sequence. + * @param keySeq the qt key sequence to add + */ +//US KShortcut( const QKeySequence& keySeq ) {} + + /** + * Creates a new shortcut that contains only the given key + * in its only sequence. + * @param key the key to add + */ +//US KShortcut( const KKey& key ); + + /** + * Creates a new shortcut that contains only the given key + * sequence. + * @param keySeq the key sequence to add + */ +//US KShortcut( const KKeySequence& keySeq ); + + /** + * Copies the given shortcut. + * @param shortcut the shortcut to add + */ +//US KShortcut( const KShortcut& shortcut ); + + /** + * Creates a new key sequence that contains the given key sequence. + * The description consists of semicolon-separated keys as + * used in @ref KKeySequence::KKeySequence(const QString&). + * @param shortcut the description of the key + * @see KKeySequence::KKeySequence(const QString&) + */ + KShortcut( const char* shortcut ) {} + + /** + * Creates a new key sequence that contains the given key sequence. + * The description consists of semicolon-separated keys as + * used in @ref KKeySequence::KKeySequence(const QString&). + * @param shortcut the description of the key + * @see KKeySequence::KKeySequence(const QString&) + */ + KShortcut( const QString& shortcut ) {} + ~KShortcut() {} + + /** + * Clears the shortcut. The shortcut is null after calling this + * function. + * @see isNull() + */ +//US void clear(); + + /** + * Initializes the shortcut with the given Qt key code + * as the only key sequence. + * @param keyQt the qt keycode + * @see Qt::Key + */ +//US bool init( int keyQt ); + + /** + * Initializes the shortcut with the given qt key sequence. + * @param keySeq the qt key sequence to add + */ +//US bool init( const QKeySequence& keySeq ); + + /** + * Initializes the shortcut with the given key as its only sequence. + * @param key the key to add + */ +//US bool init( const KKey& key ); + + /** + * Initializes the shortcut with the given qt key sequence. + * @param keySeq the qt key sequence to add + */ +//US bool init( const KKeySequence& keySeq ); + + /** + * Copies the given shortcut. + * @param shortcut the shortcut to add + */ +//US bool init( const KShortcut& shortcut ); + + /** + * Initializes the key sequence with the given key sequence. + * The description consists of semicolon-separated keys as + * used in @ref KKeySequence::KKeySequence(const QString&). + * @param shortcut the description of the key + * @see KKeySequence::KKeySequence(const QString&) + */ +//US bool init( const QString& shortcut ); + + /** + * Copies the given shortcut over this shortcut. + */ +//US KShortcut& operator =( const KShortcut& cut ) +//US { init( cut ); return *this; } + + /** + * Returns the number of sequences that are in this + * shortcut. + * @return the number of sequences + * @ref MAX_SEQUENCES + */ +//US uint count() const; + + /** + * Returns the @p i'th key sequence of this shortcut. + * @param i the number of the key sequence to retrieve + * @return the @p i'th sequence or @ref KKeySequence::null() if + * there are less than @p i key sequences + * @ref MAX_SEQUENCES + */ +//US const KKeySequence& seq( uint i ) const; + + /** + * Returns the key code of the first key sequence, or + * null if there is no first key sequence. + * @return the key code of the first sequence's first key + * @see Qt::Key + * @see KKeySequence::keyCodeQt() + */ +//US int keyCodeQt() const; + + /** + * Returns true if the shortcut is null (after @ref clear() or empty + * constructor). + * @return true if the shortcut is null + * @see clear() + * @see null() + */ + bool isNull() const { return true; } + + /** + * Compares this object with the given shortcut. Returns a negative + * number if the given shortcut is larger, 0 if they are equal and + * a positive number this shortcut is larger. Shortcuts are + * compared by comparing the individual key sequences, starting from the + * beginning until an unequal key sequences has been found. If a shortcut + * contains more key sequences, it is considered larger. + * @param shortcut the shortcut to compare to + * @return a negative number if the given KShortcut is larger, 0 if + * they are equal and a positive number this KShortcut is larger + * @see KKey::compare() + * @see KKeyShortcut::compare() + */ +//US int compare( const KShortcut& shortcut ) const; + + /** + * Compares the sequences of both shortcuts. + * @see compare() + */ +//US bool operator == ( const KShortcut& cut ) const +//US { return compare( cut ) == 0; } + + /** + * Compares the sequences of both shortcuts. + * @see compare() + */ +//US bool operator != ( const KShortcut& cut ) const +//US { return compare( cut ) != 0; } + + /** + * Compares the sequences of both shortcuts. + * @see compare() + */ +//US bool operator < ( const KShortcut& cut ) const +//US { return compare( cut ) < 0; } + + /** + * Checks whether this shortcut contains a sequence that starts + * with the given key. + * @param key the key to check + * @return true if a key sequence starts with the key + */ +//US bool contains( const KKey& key ) const; + + /** + * Checks whether this shortcut contains a sequence that starts + * with the given key. + * @param key the key to check + * @return true if a key sequence starts with the key + */ +//US bool contains( const KKeyNative& key ) const; + + /** + * Checks whether this shortcut contains the given sequence. + * @param keySeq the key sequence to check + * @return true if the shortcut has the given key sequence + */ +//US bool contains( const KKeySequence& keySeq ) const; + + /** + * Sets the @p i'th key sequence of the shortcut. You can not introduce + * gaps in the list of sequences, so you must use an @i <= @ref count(). + * Also note that the maximum number of key sequences is @ref MAX_SEQUENCES. + * @param i the position of the new key sequence(<= @ref count(), + * <= @ref MAX_SEQUENCES) + * @param keySeq the key sequence to set + * @return true if successful, false otherwise + */ +//US bool setSeq( uint i, const KKeySequence& keySeq ); + + /** + * Appends the given key sequence. + * @param keySeq the key sequence to add + * @return true if successful, false otherwise + * @see setSeq() + * @see MAX_SEQUENCES + */ +//US bool append( const KKeySequence& keySeq ); + + /** + * Appends the given key + * @param spec the key to add + * @return true if successful, false otherwise + * @see setSeq() + * @see MAX_SEQUENCES + * @since 3.2 + */ +//US bool append( const KKey& spec ); + + /** + * Appends the sequences from the given shortcut. + * @param cut the shortcut to append + * @return true if successful, false otherwise + * @see MAX_SEQUENCES + * @since 3.2 + */ +//US bool append( const KShortcut& cut ); + + /** + * Converts this shortcut to a key sequence. The first key sequence + * will be taken. + */ +//US operator QKeySequence () const; + + /** + * Returns a description of the shortcut as semicolon-separated + * ket sequences, as returned by @ref KKeySequence::toString(). + * @return the string represenation of this shortcut + * @see KKey::toString() + * @see KKeySequence::toString() + */ +//US QString toString() const; + + /** + * @internal + */ + QString toStringInternal( const KShortcut* pcutDefault = 0 ) const + { + return "EMPTY IMPL."; + } + + /** + * Returns a null shortcut. + * @return the null shortcut + * @see isNull() + * @see clear() + */ +//US static KShortcut& null(); + +//US protected: +//US uint m_nSeqs; +//US KKeySequence m_rgseq[MAX_SEQUENCES]; + +//US private: +//US class KShortcutPrivate* d; +//US friend class KKeyNative; + +//US#ifndef KDE_NO_COMPAT +//US public: +//US operator int () const { return keyCodeQt(); } +//US#endif +}; + +#endif // __KSHORTCUT_H diff --git a/microkde/kdecore/kstandarddirs.cpp b/microkde/kdecore/kstandarddirs.cpp new file mode 100644 index 0000000..5abe05c --- a/dev/null +++ b/microkde/kdecore/kstandarddirs.cpp @@ -0,0 +1,1620 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org> + Copyright (C) 1999 Stephan Kulow <coolo@kde.org> + Copyright (C) 1999 Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * Author: Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org> + * Version: $Id$ + * Generated: Thu Mar 5 16:05:28 EST 1998 + */ + +//US #include "config.h" + +#include <stdlib.h> +#include <assert.h> +//US#include <errno.h> +//US #ifdef HAVE_SYS_STAT_H +//US #include <sys/stat.h> +//US #endif +//US#include <sys/types.h> +//US#include <dirent.h> +//US#include <pwd.h> + +#include <qregexp.h> +#include <qasciidict.h> +#include <qdict.h> +#include <qdir.h> +#include <qfileinfo.h> +#include <qstring.h> +#include <qstringlist.h> + +#include "kstandarddirs.h" +#include "kconfig.h" +#include "kdebug.h" +//US #include "kinstance.h" +#include "kshell.h" +//US#include <sys/param.h> +//US#include <unistd.h> + +//US +QString KStandardDirs::mAppDir = QString::null; + + +template class QDict<QStringList>; + +#if 0 +#include <qtextedit.h> +void ddd( QString op ) +{ + static QTextEdit * dot = 0; + if ( ! dot ) + dot = new QTextEdit(); + + dot->show(); + + dot->append( op ); + +} +#endif +class KStandardDirs::KStandardDirsPrivate +{ +public: + KStandardDirsPrivate() + : restrictionsActive(false), + dataRestrictionActive(false) + { } + + bool restrictionsActive; + bool dataRestrictionActive; + QAsciiDict<bool> restrictions; + QStringList xdgdata_prefixes; + QStringList xdgconf_prefixes; +}; + +static const char* const types[] = {"html", "icon", "apps", "sound", + "data", "locale", "services", "mime", + "servicetypes", "config", "exe", + "wallpaper", "lib", "pixmap", "templates", + "module", "qtplugins", + "xdgdata-apps", "xdgdata-dirs", "xdgconf-menu", 0 }; + +static int tokenize( QStringList& token, const QString& str, + const QString& delim ); + +KStandardDirs::KStandardDirs( ) : addedCustoms(false) +{ + d = new KStandardDirsPrivate; + dircache.setAutoDelete(true); + relatives.setAutoDelete(true); + absolutes.setAutoDelete(true); + savelocations.setAutoDelete(true); + addKDEDefaults(); +} + +KStandardDirs::~KStandardDirs() +{ + delete d; +} + +bool KStandardDirs::isRestrictedResource(const char *type, const QString& relPath) const +{ + if (!d || !d->restrictionsActive) + return false; + + if (d->restrictions[type]) + return true; + + if (strcmp(type, "data")==0) + { + applyDataRestrictions(relPath); + if (d->dataRestrictionActive) + { + d->dataRestrictionActive = false; + return true; + } + } + return false; +} + +void KStandardDirs::applyDataRestrictions(const QString &relPath) const +{ + QString key; + int i = relPath.find('/'); + if (i != -1) + key = "data_"+relPath.left(i); + else + key = "data_"+relPath; + + if (d && d->restrictions[key.latin1()]) + d->dataRestrictionActive = true; +} + + +QStringList KStandardDirs::allTypes() const +{ + QStringList list; + for (int i = 0; types[i] != 0; ++i) + list.append(QString::fromLatin1(types[i])); + return list; +} + +void KStandardDirs::addPrefix( const QString& _dir ) +{ + if (_dir.isNull()) + return; + + QString dir = _dir; + if (dir.at(dir.length() - 1) != '/') + dir += '/'; + + if (!prefixes.contains(dir)) { + prefixes.append(dir); + dircache.clear(); + } +} + +void KStandardDirs::addXdgConfigPrefix( const QString& _dir ) +{ + if (_dir.isNull()) + return; + + QString dir = _dir; + if (dir.at(dir.length() - 1) != '/') + dir += '/'; + + if (!d->xdgconf_prefixes.contains(dir)) { + d->xdgconf_prefixes.append(dir); + dircache.clear(); + } +} + +void KStandardDirs::addXdgDataPrefix( const QString& _dir ) +{ + if (_dir.isNull()) + return; + + QString dir = _dir; + if (dir.at(dir.length() - 1) != '/') + dir += '/'; + + if (!d->xdgdata_prefixes.contains(dir)) { + d->xdgdata_prefixes.append(dir); + dircache.clear(); + } +} + + +QString KStandardDirs::kfsstnd_prefixes() +{ + return prefixes.join(":"); +} + +bool KStandardDirs::addResourceType( const char *type, + const QString& relativename ) +{ + if (relativename.isNull()) + return false; + + QStringList *rels = relatives.find(type); + if (!rels) { + rels = new QStringList(); + relatives.insert(type, rels); + } + QString copy = relativename; + if (copy.at(copy.length() - 1) != '/') + copy += '/'; + if (!rels->contains(copy)) { + rels->prepend(copy); + dircache.remove(type); // clean the cache + return true; + } + return false; +} + +bool KStandardDirs::addResourceDir( const char *type, + const QString& absdir) +{ + QStringList *paths = absolutes.find(type); + if (!paths) { + paths = new QStringList(); + absolutes.insert(type, paths); + } + QString copy = absdir; + if (copy.at(copy.length() - 1) != '/') + copy += '/'; + + if (!paths->contains(copy)) { + paths->append(copy); + dircache.remove(type); // clean the cache + return true; + } + return false; +} + +QString KStandardDirs::findResource( const char *type, + const QString& filename ) const +{ + if (filename.at(0) == '/') + return filename; // absolute dirs are absolute dirs, right? :-/ + +#if 0 +kdDebug() << "Find resource: " << type << endl; +for (QStringList::ConstIterator pit = prefixes.begin(); + pit != prefixes.end(); + pit++) +{ + kdDebug() << "Prefix: " << *pit << endl; +} +#endif + + QString dir = findResourceDir(type, filename); + if (dir.isNull()) + return dir; + else return dir + filename; +} +/*US +static Q_UINT32 updateHash(const QString &file, Q_UINT32 hash) +{ + QCString cFile = QFile::encodeName(file); +//US struct stat buff; +//US if ((access(cFile, R_OK) == 0) && +//US (stat( cFile, &buff ) == 0) && +//US (S_ISREG( buff.st_mode ))) + QFileInfo pathfnInfo(cFile); + if (( pathfnInfo.isReadable() == true ) && + ( pathfnInfo.isFile()) ) + { +//US hash = hash + (Q_UINT32) buff.st_ctime; + hash = hash + (Q_UINT32) pathfnInfo.lastModified(); + } + return hash; +} +*/ +/*US +Q_UINT32 KStandardDirs::calcResourceHash( const char *type, + const QString& filename, bool deep) const +{ + Q_UINT32 hash = 0; + + if (filename.at(0) == '/') + { + // absolute dirs are absolute dirs, right? :-/ + return updateHash(filename, hash); + } + if (d && d->restrictionsActive && (strcmp(type, "data")==0)) + applyDataRestrictions(filename); + QStringList candidates = resourceDirs(type); + QString fullPath; + + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) + { + hash = updateHash(*it + filename, hash); + if (!deep && hash) + return hash; + } + return hash; +} +*/ + +QStringList KStandardDirs::findDirs( const char *type, + const QString& reldir ) const +{ + QStringList list; + + checkConfig(); + + if (d && d->restrictionsActive && (strcmp(type, "data")==0)) + applyDataRestrictions(reldir); + QStringList candidates = resourceDirs(type); + QDir testdir; + + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) { + testdir.setPath(*it + reldir); + if (testdir.exists()) + list.append(testdir.absPath() + '/'); + } + + return list; +} + +QString KStandardDirs::findResourceDir( const char *type, + const QString& filename) const +{ +#ifndef NDEBUG + if (filename.isEmpty()) { + kdWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!" << endl; + return QString::null; + } +#endif + + if (d && d->restrictionsActive && (strcmp(type, "data")==0)) + applyDataRestrictions(filename); + QStringList candidates = resourceDirs(type); + QString fullPath; + + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) + if (exists(*it + filename)) + return *it; + +#ifndef NDEBUG + if(false && type != "locale") + kdDebug() << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\"." << endl; +#endif + + return QString::null; +} + +bool KStandardDirs::exists(const QString &fullPath) +{ +//US struct stat buff; + QFileInfo fullPathInfo(QFile::encodeName(fullPath)); + +//US if (access(QFile::encodeName(fullPath), R_OK) == 0 && fullPathInfo.isReadable()) + if (fullPathInfo.isReadable()) + { + if (fullPath.at(fullPath.length() - 1) != '/') { +//US if (S_ISREG( buff.st_mode )) + if (fullPathInfo.isFile()) + return true; + } + else { +//US if (S_ISDIR( buff.st_mode )) + if (fullPathInfo.isDir()) + return true; + } + } + return false; +} + +static void lookupDirectory(const QString& path, const QString &relPart, + const QRegExp ®exp, + QStringList& list, + QStringList& relList, + bool recursive, bool uniq) +{ + QString pattern = regexp.pattern(); + if (recursive || pattern.contains('?') || pattern.contains('*')) + { + // We look for a set of files. +//US DIR *dp = opendir( QFile::encodeName(path)); + QDir dp(QFile::encodeName(path)); + if (!dp.exists()) + return; + static int iii = 0; + ++iii; + if ( iii == 5 ) + abort(); + assert(path.at(path.length() - 1) == '/'); + +//US struct dirent *ep; +//US struct stat buff; + + QString _dot("."); + QString _dotdot(".."); + +//US while( ( ep = readdir( dp ) ) != 0L ) + QStringList direntries = dp.entryList(); + QStringList::Iterator it = direntries.begin(); + + while ( it != list.end() ) // for each file... + { + +//US QString fn( QFile::decodeName(ep->d_name)); + QString fn = (*it); // dp.entryList already decodes + it++; + if ( fn.isNull() ) + break; + + if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1).latin1() == '~' ) + continue; + +/*US + if (!recursive && !regexp.exactMatch(fn)) + continue; // No match +*/ +//US this should do the same: + int pos = regexp.match(fn); + if (!recursive && !pos == 0) + continue; // No match + + QString pathfn = path + fn; +/*US + if ( stat( QFile::encodeName(pathfn), &buff ) != 0 ) { + kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl; + continue; // Couldn't stat (e.g. no read permissions) + } + + if ( recursive ) + { + if ( S_ISDIR( buff.st_mode )) { + lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, uniq); + } +*/ +//US replacement: + QFileInfo pathfnInfo(QFile::encodeName(pathfn)); + if ( pathfnInfo.isReadable() == false ) + { +//US kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl; + continue; // Couldn't stat (e.g. no read permissions) + } + + if ( recursive ) + { + if ( pathfnInfo.isDir()) { + lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, uniq); + } + + +/*US + if (!regexp.exactMatch(fn)) + continue; // No match +*/ +//US this should do the same: + pos = regexp.match(fn); + if (!pos == 0) + continue; // No match + } + +//US if ( S_ISREG( buff.st_mode)) + if ( pathfnInfo.isFile()) + { + if (!uniq || !relList.contains(relPart + fn)) + { + list.append( pathfn ); + relList.append( relPart + fn ); + } + } + } +//US closedir( dp ); + } + else + { + // We look for a single file. + QString fn = pattern; + QString pathfn = path + fn; +//US struct stat buff; + QFileInfo pathfnInfo(QFile::encodeName(pathfn)); + + +//US if ( stat( QFile::encodeName(pathfn), &buff ) != 0 ) + if ( pathfnInfo.isReadable() == false ) + return; // File not found + +//US if ( S_ISREG( buff.st_mode)) + if ( pathfnInfo.isFile()) + { + if (!uniq || !relList.contains(relPart + fn)) + { + list.append( pathfn ); + relList.append( relPart + fn ); + } + } + } +} + +static void lookupPrefix(const QString& prefix, const QString& relpath, + const QString& relPart, + const QRegExp ®exp, + QStringList& list, + QStringList& relList, + bool recursive, bool uniq) +{ + if (relpath.isNull()) { + lookupDirectory(prefix, relPart, regexp, list, + relList, recursive, uniq); + return; + } + QString path; + QString rest; + + if (relpath.length()) + { + int slash = relpath.find('/'); + if (slash < 0) + rest = relpath.left(relpath.length() - 1); + else { + path = relpath.left(slash); + rest = relpath.mid(slash + 1); + } + } + assert(prefix.at(prefix.length() - 1) == '/'); + +//US struct stat buff; + + if (path.contains('*') || path.contains('?')) { + QRegExp pathExp(path, true, true); +//US DIR *dp = opendir( QFile::encodeName(prefix) ); + QDir dp(QFile::encodeName(prefix)); + +//US if (!dp) + if (!dp.exists()) + { + return; + } + +//US struct dirent *ep; + + QString _dot("."); + QString _dotdot(".."); + +//US while( ( ep = readdir( dp ) ) != 0L ) + QStringList direntries = dp.entryList(); + QStringList::Iterator it = direntries.begin(); + + while ( it != list.end() ) // for each file... + { +//US QString fn( QFile::decodeName(ep->d_name)); + QString fn = (*it); // dp.entryList() already encodes the strings + it++; + + if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1) == '~') + continue; + +#ifdef DESKTOP_VERSION + + if (pathExp.search(fn) == -1) + continue; // No match + +#else +//US this should do the same: + if (pathExp.find(fn, 0) == -1) + continue; // No match +#endif + QString rfn = relPart+fn; + fn = prefix + fn; +//US if ( stat( QFile::encodeName(fn), &buff ) != 0 ) + QFileInfo fnInfo(QFile::encodeName(fn)); + if ( fnInfo.isReadable() == false ) + { +//US kdDebug() << "Error statting " << fn << " : " << perror << endl; + continue; // Couldn't stat (e.g. no permissions) + } +//US if ( S_ISDIR( buff.st_mode )) + if ( fnInfo.isDir() ) + + lookupPrefix(fn + '/', rest, rfn + '/', regexp, list, relList, recursive, uniq); + } + +//US closedir( dp ); + } else { + // Don't stat, if the dir doesn't exist we will find out + // when we try to open it. + lookupPrefix(prefix + path + '/', rest, + relPart + path + '/', regexp, list, + relList, recursive, uniq); + } +} + +QStringList +KStandardDirs::findAllResources( const char *type, + const QString& filter, + bool recursive, + bool uniq, + QStringList &relList) const +{ + QStringList list; + if (filter.at(0) == '/') // absolute paths we return + { + list.append( filter); + return list; + } + + QString filterPath; + QString filterFile; + + if (filter.length()) + { + int slash = filter.findRev('/'); + if (slash < 0) + filterFile = filter; + else { + filterPath = filter.left(slash + 1); + filterFile = filter.mid(slash + 1); + } + } + checkConfig(); + + if (d && d->restrictionsActive && (strcmp(type, "data")==0)) + applyDataRestrictions(filter); + QStringList candidates = resourceDirs(type); + if (filterFile.isEmpty()) + filterFile = "*"; + + QRegExp regExp(filterFile, true, true); + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) + { + lookupPrefix(*it, filterPath, "", regExp, list, + relList, recursive, uniq); + } + return list; +} + +QStringList +KStandardDirs::findAllResources( const char *type, + const QString& filter, + bool recursive, + bool uniq) const +{ + QStringList relList; + return findAllResources(type, filter, recursive, uniq, relList); +} + +QString +KStandardDirs::realPath(const QString &dirname) +{ +#ifdef _WIN32_ + return dirname; +#else +//US char realpath_buffer[MAXPATHLEN + 1]; +//US memset(realpath_buffer, 0, MAXPATHLEN + 1); + char realpath_buffer[250 + 1]; + memset(realpath_buffer, 0, 250 + 1); + + /* If the path contains symlinks, get the real name */ + if (realpath( QFile::encodeName(dirname).data(), realpath_buffer) != 0) { + // succes, use result from realpath + int len = strlen(realpath_buffer); + realpath_buffer[len] = '/'; + realpath_buffer[len+1] = 0; + return QFile::decodeName(realpath_buffer); + } + + return dirname; +#endif +} +/*US +void KStandardDirs::createSpecialResource(const char *type) +{ + char hostname[256]; + hostname[0] = 0; + gethostname(hostname, 255); + QString dir = QString("%1%2-%3").arg(localkdedir()).arg(type).arg(hostname); + char link[1024]; + link[1023] = 0; + int result = readlink(QFile::encodeName(dir).data(), link, 1023); + if ((result == -1) && (errno == ENOENT)) + { + QString srv = findExe(QString::fromLatin1("lnusertemp"), KDEDIR+QString::fromLatin1("/bin")); + if (srv.isEmpty()) + srv = findExe(QString::fromLatin1("lnusertemp")); + if (!srv.isEmpty()) + { + system(QFile::encodeName(srv)+" "+type); + result = readlink(QFile::encodeName(dir).data(), link, 1023); + } + } + if (result > 0) + { + link[result] = 0; + if (link[0] == '/') + dir = QFile::decodeName(link); + else + dir = QDir::cleanDirPath(dir+QFile::decodeName(link)); + } + addResourceDir(type, dir+'/'); +} +*/ + +QStringList KStandardDirs::resourceDirs(const char *type) const +{ + QStringList *candidates = dircache.find(type); + + if (!candidates) { // filling cache +/*US + if (strcmp(type, "socket") == 0) + const_cast<KStandardDirs *>(this)->createSpecialResource(type); + else if (strcmp(type, "tmp") == 0) + const_cast<KStandardDirs *>(this)->createSpecialResource(type); + else if (strcmp(type, "cache") == 0) + const_cast<KStandardDirs *>(this)->createSpecialResource(type); +*/ + QDir testdir; + + candidates = new QStringList(); + QStringList *dirs; + + bool restrictionActive = false; + if (d && d->restrictionsActive) + { + if (d->dataRestrictionActive) + restrictionActive = true; + else if (d->restrictions["all"]) + restrictionActive = true; + else if (d->restrictions[type]) + restrictionActive = true; + d->dataRestrictionActive = false; // Reset + } + + dirs = relatives.find(type); + if (dirs) + { + bool local = true; + const QStringList *prefixList = 0; + if (strncmp(type, "xdgdata-", 8) == 0) + prefixList = &(d->xdgdata_prefixes); + else if (strncmp(type, "xdgconf-", 8) == 0) + prefixList = &(d->xdgconf_prefixes); + else + prefixList = &prefixes; + + for (QStringList::ConstIterator pit = prefixList->begin(); + pit != prefixList->end(); + pit++) + { + for (QStringList::ConstIterator it = dirs->begin(); + it != dirs->end(); ++it) { + QString path = realPath(*pit + *it); + testdir.setPath(path); + if (local && restrictionActive) + continue; + if ((local || testdir.exists()) && !candidates->contains(path)) + candidates->append(path); + } + local = false; + } + } + dirs = absolutes.find(type); + if (dirs) + for (QStringList::ConstIterator it = dirs->begin(); + it != dirs->end(); ++it) + { + testdir.setPath(*it); + if (testdir.exists()) + { + QString filename = realPath(*it); + if (!candidates->contains(filename)) + candidates->append(filename); + } + } + dircache.insert(type, candidates); + } + +#if 0 + kdDebug() << "found dirs for resource " << type << ":" << endl; + for (QStringList::ConstIterator pit = candidates->begin(); + pit != candidates->end(); + pit++) + { + fprintf(stderr, "%s\n", (*pit).latin1()); + } +#endif + + + return *candidates; +} + +/*US +QString KStandardDirs::findExe( const QString& appname, + const QString& pstr, bool ignore) +{ + QFileInfo info; + + // absolute path ? + if (appname.startsWith(QString::fromLatin1("/"))) + { + info.setFile( appname ); + if( info.exists() && ( ignore || info.isExecutable() ) + && info.isFile() ) { + return appname; + } + return QString::null; + } + +//US QString p = QString("%1/%2").arg(__KDE_BINDIR).arg(appname); + QString p = QString("%1/%2").arg(appname).arg(appname); + qDebug("KStandardDirs::findExe this is probably wrong"); + + info.setFile( p ); + if( info.exists() && ( ignore || info.isExecutable() ) + && ( info.isFile() || info.isSymLink() ) ) { + return p; + } + + QStringList tokens; + p = pstr; + + if( p.isNull() ) { + p = getenv( "PATH" ); + } + + tokenize( tokens, p, ":\b" ); + + // split path using : or \b as delimiters + for( unsigned i = 0; i < tokens.count(); i++ ) { + p = tokens[ i ]; + + if ( p[ 0 ] == '~' ) + { + int len = p.find( '/' ); + if ( len == -1 ) + len = p.length(); + if ( len == 1 ) + p.replace( 0, 1, QDir::homeDirPath() ); + else + { + QString user = p.mid( 1, len - 1 ); + struct passwd *dir = getpwnam( user.local8Bit().data() ); + if ( dir && strlen( dir->pw_dir ) ) + p.replace( 0, len, QString::fromLocal8Bit( dir->pw_dir ) ); + } + } + + p += "/"; + p += appname; + + // Check for executable in this tokenized path + info.setFile( p ); + + if( info.exists() && ( ignore || info.isExecutable() ) + && ( info.isFile() || info.isSymLink() ) ) { + return p; + } + } + + // If we reach here, the executable wasn't found. + // So return empty string. + + return QString::null; +} + +int KStandardDirs::findAllExe( QStringList& list, const QString& appname, + const QString& pstr, bool ignore ) +{ + QString p = pstr; + QFileInfo info; + QStringList tokens; + + if( p.isNull() ) { + p = getenv( "PATH" ); + } + + list.clear(); + tokenize( tokens, p, ":\b" ); + + for ( unsigned i = 0; i < tokens.count(); i++ ) { + p = tokens[ i ]; + p += "/"; + p += appname; + + info.setFile( p ); + + if( info.exists() && (ignore || info.isExecutable()) + && info.isFile() ) { + list.append( p ); + } + + } + + return list.count(); +} +*/ + +static int tokenize( QStringList& tokens, const QString& str, + const QString& delim ) +{ + int len = str.length(); + QString token = ""; + + for( int index = 0; index < len; index++) + { + if ( delim.find( str[ index ] ) >= 0 ) + { + tokens.append( token ); + token = ""; + } + else + { + token += str[ index ]; + } + } + if ( token.length() > 0 ) + { + tokens.append( token ); + } + + return tokens.count(); +} + +QString KStandardDirs::kde_default(const char *type) { + if (!strcmp(type, "data")) + return "apps/"; + if (!strcmp(type, "html")) + return "share/doc/HTML/"; + if (!strcmp(type, "icon")) + return "share/icons/"; + if (!strcmp(type, "config")) + return "config/"; + if (!strcmp(type, "pixmap")) + return "share/pixmaps/"; + if (!strcmp(type, "apps")) + return "share/applnk/"; + if (!strcmp(type, "sound")) + return "share/sounds/"; + if (!strcmp(type, "locale")) + return "share/locale/"; + if (!strcmp(type, "services")) + return "share/services/"; + if (!strcmp(type, "servicetypes")) + return "share/servicetypes/"; + if (!strcmp(type, "mime")) + return "share/mimelnk/"; + if (!strcmp(type, "cgi")) + return "cgi-bin/"; + if (!strcmp(type, "wallpaper")) + return "share/wallpapers/"; + if (!strcmp(type, "templates")) + return "share/templates/"; + if (!strcmp(type, "exe")) + return "bin/"; + if (!strcmp(type, "lib")) + return "lib/"; + if (!strcmp(type, "module")) + return "lib/kde3/"; + if (!strcmp(type, "qtplugins")) + return "lib/kde3/plugins"; + if (!strcmp(type, "xdgdata-apps")) + return "applications/"; + if (!strcmp(type, "xdgdata-dirs")) + return "desktop-directories/"; + if (!strcmp(type, "xdgconf-menu")) + return "menus/"; + qFatal("unknown resource type %s", type); + return QString::null; +} + +QString KStandardDirs::saveLocation(const char *type, + const QString& suffix, + bool create) const +{ + //qDebug("KStandardDirs::saveLocation called %s %s", type,suffix.latin1() ); + //return ""; + checkConfig(); + + QString *pPath = savelocations.find(type); + if (!pPath) + { + QStringList *dirs = relatives.find(type); + if (!dirs && ( + (strcmp(type, "socket") == 0) || + (strcmp(type, "tmp") == 0) || + (strcmp(type, "cache") == 0) )) + { + (void) resourceDirs(type); // Generate socket|tmp|cache resource. + dirs = relatives.find(type); // Search again. + } + if (dirs) + { + // Check for existance of typed directory + suffix + if (strncmp(type, "xdgdata-", 8) == 0) + pPath = new QString(realPath(localxdgdatadir() + dirs->last())); + else if (strncmp(type, "xdgconf-", 8) == 0) + pPath = new QString(realPath(localxdgconfdir() + dirs->last())); + else + pPath = new QString(realPath(localkdedir() + dirs->last())); + } + else { + dirs = absolutes.find(type); + if (!dirs) + qFatal("KStandardDirs: The resource type %s is not registered", type); + pPath = new QString(realPath(dirs->last())); + } + + savelocations.insert(type, pPath); + } + + QString fullPath = *pPath + suffix; +//US struct stat st; +//US if (stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) + QFileInfo fullPathInfo(QFile::encodeName(fullPath)); + if (fullPathInfo.isReadable() || !fullPathInfo.isDir()) + + + { + if(!create) { +#ifndef NDEBUG + qDebug("save location %s doesn't exist", fullPath.latin1()); +#endif + return fullPath; + } + if(!makeDir(fullPath, 0700)) { + qWarning("failed to create %s", fullPath.latin1()); + return fullPath; + } + dircache.remove(type); + } + return fullPath; +} + +QString KStandardDirs::relativeLocation(const char *type, const QString &absPath) +{ + QString fullPath = absPath; + int i = absPath.findRev('/'); + if (i != -1) + { + fullPath = realPath(absPath.left(i+1))+absPath.mid(i+1); // Normalize + } + + QStringList candidates = resourceDirs(type); + + for (QStringList::ConstIterator it = candidates.begin(); + it != candidates.end(); it++) + if (fullPath.startsWith(*it)) + { + return fullPath.mid((*it).length()); + } + + return absPath; +} + + +bool KStandardDirs::makeDir(const QString& dir2, int mode) +{ + QString dir = QDir::convertSeparators( dir2 ); +#if 0 + //LR + + // we want an absolute path + if (dir.at(0) != '/') + return false; + + QString target = dir; + uint len = target.length(); + + // append trailing slash if missing + if (dir.at(len - 1) != '/') + target += '/'; + + QString base(""); + uint i = 1; + + while( i < len ) + { +//US struct stat st; + int pos = target.find('/', i); + base += target.mid(i - 1, pos - i + 1); + QCString baseEncoded = QFile::encodeName(base); + // bail out if we encountered a problem +//US if (stat(baseEncoded, &st) != 0) + QFileInfo baseEncodedInfo(baseEncoded); + if (!baseEncodedInfo.exists()) + { + // Directory does not exist.... + // Or maybe a dangling symlink ? +//US if (lstat(baseEncoded, &st) == 0) + if (baseEncodedInfo.isSymLink()) { +//US (void)unlink(baseEncoded); // try removing + QFile(baseEncoded).remove(); + } + +//US if ( mkdir(baseEncoded, (mode_t) mode) != 0) + QDir dirObj; + if ( dirObj.mkdir(baseEncoded) != true ) + { +//US perror("trying to create local folder"); + return false; // Couldn't create it :-( + } + } + i = pos + 1; + } + return true; +#endif + + // ******************************************** + // new code for WIN32 + QDir dirObj; + + + // we want an absolute path +#ifndef _WIN32_ + if (dir.at(0) != '/') + return false; +#endif + + QString target = dir; + uint len = target.length(); +#ifndef _WIN32_ + // append trailing slash if missing + if (dir.at(len - 1) != '/') + target += '/'; +#endif + + QString base(""); + uint i = 1; + + while( i < len ) + { +//US struct stat st; +#ifndef _WIN32_ + int pos = target.find('/', i); +#else + int pos = target.find('\\', i); +#endif + if ( pos < 0 ) + return true; + base += target.mid(i - 1, pos - i + 1); + //QMessageBox::information( 0,"cap111", base, 1 ); +/*US + QCString baseEncoded = QFile::encodeName(base); + // bail out if we encountered a problem + if (stat(baseEncoded, &st) != 0) + { + // Directory does not exist.... + // Or maybe a dangling symlink ? + if (lstat(baseEncoded, &st) == 0) + (void)unlink(baseEncoded); // try removing + + + if ( mkdir(baseEncoded, (mode_t) mode) != 0) { + perror("trying to create local folder"); + return false; // Couldn't create it :-( + } + } +*/ + + if (dirObj.exists(base) == false) + { + //qDebug("KStandardDirs::makeDir try to create : %s" , base.latin1()); + if (dirObj.mkdir(base) != true) + { + qDebug("KStandardDirs::makeDir could not create: %s" , base.latin1()); + return false; + } + } + + i = pos + 1; + } + return true; + +} + +static QString readEnvPath(const char *env) +{ +#ifdef _WIN32_ + return ""; +#else + QCString c_path = getenv(env); + if (c_path.isEmpty()) + return QString::null; + return QFile::decodeName(c_path); +#endif +} + +void KStandardDirs::addKDEDefaults() +{ + //qDebug("ERROR: KStandardDirs::addKDEDefaults() called "); + //return; + QStringList kdedirList; + + // begin KDEDIRS + QString kdedirs = readEnvPath("MICROKDEDIRS"); + if (!kdedirs.isEmpty()) + { + tokenize(kdedirList, kdedirs, ":"); + } + else + { + QString kdedir = readEnvPath("MICROKDEDIR"); + if (!kdedir.isEmpty()) + { + kdedir = KShell::tildeExpand(kdedir); + kdedirList.append(kdedir); + } + } +//US kdedirList.append(KDEDIR); + +#ifdef __KDE_EXECPREFIX + QString execPrefix(__KDE_EXECPREFIX); + if (execPrefix!="NONE") + kdedirList.append(execPrefix); +#endif + + QString localKdeDir; + +//US if (getuid()) + if (true) + { + localKdeDir = readEnvPath("MICROKDEHOME"); + if (!localKdeDir.isEmpty()) + { + if (localKdeDir.at(localKdeDir.length()-1) != '/') + localKdeDir += '/'; + } + else + { + localKdeDir = QDir::homeDirPath() + "/kdepim/"; + } + } + else + { + // We treat root different to prevent root messing up the + // file permissions in the users home directory. + localKdeDir = readEnvPath("MICROKDEROOTHOME"); + if (!localKdeDir.isEmpty()) + { + if (localKdeDir.at(localKdeDir.length()-1) != '/') + localKdeDir += '/'; + } + else + { +//US struct passwd *pw = getpwuid(0); +//US localKdeDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.microkde/"; + qDebug("KStandardDirs::addKDEDefaults: 1 has to be fixed"); + } + + } + +//US localKdeDir = appDir(); + +//US +// qDebug("KStandardDirs::addKDEDefaults: localKdeDir=%s", localKdeDir.latin1()); + if (localKdeDir != "-/") + { + localKdeDir = KShell::tildeExpand(localKdeDir); + addPrefix(localKdeDir); + } + + for (QStringList::ConstIterator it = kdedirList.begin(); + it != kdedirList.end(); it++) + { + QString dir = KShell::tildeExpand(*it); + addPrefix(dir); + } + // end KDEDIRS + + // begin XDG_CONFIG_XXX + QStringList xdgdirList; + QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS"); + if (!xdgdirs.isEmpty()) + { + tokenize(xdgdirList, xdgdirs, ":"); + } + else + { + xdgdirList.clear(); + xdgdirList.append("/etc/xdg"); + } + + QString localXdgDir = readEnvPath("XDG_CONFIG_HOME"); + if (!localXdgDir.isEmpty()) + { + if (localXdgDir.at(localXdgDir.length()-1) != '/') + localXdgDir += '/'; + } + else + { +//US if (getuid()) + if (true) + { + localXdgDir = QDir::homeDirPath() + "/.config/"; + } + else + { +//US struct passwd *pw = getpwuid(0); +//US localXdgDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.config/"; + qDebug("KStandardDirs::addKDEDefaults: 2 has to be fixed"); + } + } + + localXdgDir = KShell::tildeExpand(localXdgDir); + addXdgConfigPrefix(localXdgDir); + + for (QStringList::ConstIterator it = xdgdirList.begin(); + it != xdgdirList.end(); it++) + { + QString dir = KShell::tildeExpand(*it); + addXdgConfigPrefix(dir); + } + // end XDG_CONFIG_XXX + + // begin XDG_DATA_XXX + xdgdirs = readEnvPath("XDG_DATA_DIRS"); + if (!xdgdirs.isEmpty()) + { + tokenize(xdgdirList, xdgdirs, ":"); + } + else + { + xdgdirList.clear(); + for (QStringList::ConstIterator it = kdedirList.begin(); + it != kdedirList.end(); it++) + { + QString dir = *it; + if (dir.at(dir.length()-1) != '/') + dir += '/'; + xdgdirList.append(dir+"share/"); + } + + xdgdirList.append("/usr/local/share/"); + xdgdirList.append("/usr/share/"); + } + + localXdgDir = readEnvPath("XDG_DATA_HOME"); + if (!localXdgDir.isEmpty()) + { + if (localXdgDir.at(localXdgDir.length()-1) != '/') + localXdgDir += '/'; + } + else + { +//US if (getuid()) + if (true) + { + localXdgDir = QDir::homeDirPath() + "/.local/share/"; + } + else + { +//US struct passwd *pw = getpwuid(0); +//US localXdgDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.local/share/"; + qDebug("KStandardDirs::addKDEDefaults: 3 has to be fixed"); + } + } + + localXdgDir = KShell::tildeExpand(localXdgDir); + addXdgDataPrefix(localXdgDir); + + for (QStringList::ConstIterator it = xdgdirList.begin(); + it != xdgdirList.end(); it++) + { + QString dir = KShell::tildeExpand(*it); + + addXdgDataPrefix(dir); + } + // end XDG_DATA_XXX + + + uint index = 0; + while (types[index] != 0) { + addResourceType(types[index], kde_default(types[index])); + index++; + } + + addResourceDir("home", QDir::homeDirPath()); +} + +void KStandardDirs::checkConfig() const +{ +/*US + if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->_config) + const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::_instance->_config); +*/ + if (!addedCustoms && KGlobal::config()) + const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::config()); +} + +bool KStandardDirs::addCustomized(KConfig *config) +{ + if (addedCustoms) // there are already customized entries + return false; // we just quite and hope they are the right ones + + // save the numbers of config directories. If this changes, + // we will return true to give KConfig a chance to reparse + uint configdirs = resourceDirs("config").count(); + + // reading the prefixes in + QString oldGroup = config->group(); + config->setGroup("Directories"); + + QStringList list; + QStringList::ConstIterator it; + list = config->readListEntry("prefixes"); + for (it = list.begin(); it != list.end(); it++) + addPrefix(*it); + + // iterating over all entries in the group Directories + // to find entries that start with dir_$type +/*US + QMap<QString, QString> entries = config->entryMap("Directories"); + + QMap<QString, QString>::ConstIterator it2; + for (it2 = entries.begin(); it2 != entries.end(); it2++) + { + QString key = it2.key(); + if (key.left(4) == "dir_") { + // generate directory list, there may be more than 1. + QStringList dirs = QStringList::split(',', *it2); + QStringList::Iterator sIt(dirs.begin()); + QString resType = key.mid(4, key.length()); + for (; sIt != dirs.end(); ++sIt) { + addResourceDir(resType.latin1(), *sIt); + } + } + } + + // Process KIOSK restrictions. + config->setGroup("KDE Resource Restrictions"); + entries = config->entryMap("KDE Resource Restrictions"); + for (it2 = entries.begin(); it2 != entries.end(); it2++) + { + QString key = it2.key(); + if (!config->readBoolEntry(key, true)) + { + d->restrictionsActive = true; + d->restrictions.insert(key.latin1(), &d->restrictionsActive); // Anything will do + dircache.remove(key.latin1()); + } + } +*/ + // save it for future calls - that will return + addedCustoms = true; + config->setGroup(oldGroup); + + // return true if the number of config dirs changed + return (resourceDirs("config").count() != configdirs); +} + +QString KStandardDirs::localkdedir() const +{ + // Return the prefix to use for saving + return prefixes.first(); +} + +QString KStandardDirs::localxdgdatadir() const +{ + // Return the prefix to use for saving + return d->xdgdata_prefixes.first(); +} + +QString KStandardDirs::localxdgconfdir() const +{ + // Return the prefix to use for saving + return d->xdgconf_prefixes.first(); +} + +void KStandardDirs::setAppDir( const QString &appDir ) +{ + mAppDir = appDir; + + if ( mAppDir.right( 1 ) != "/" ) + mAppDir += "/"; +} + +QString KStandardDirs::appDir() +{ + return mAppDir; +} + +// just to make code more readable without macros +QString locate( const char *type, + const QString& filename/*US , const KInstance* inst*/ ) +{ +//US return inst->dirs()->findResource(type, filename); + return KGlobal::dirs()->findResource(type, filename); +} + +QString locateLocal( const char *type, + const QString& filename/*US , const KInstance* inst*/ ) +{ + + QString path = locateLocal(type, filename, true /*US, inst*/); + + +/* + static int ccc = 0; + ++ccc; + if ( ccc > 13 ) + abort(); +*/ + qDebug("locatelocal: %s" , path.latin1()); + return path; + +/*US why do we put all files into one directory. It is quit complicated. +why not staying with the original directorystructure ? + + + QString escapedFilename = filename; + escapedFilename.replace( QRegExp( "/" ), "_" ); + + QString path = KStandardDirs::appDir() + type + "_" + escapedFilename; + + kdDebug() << "locate: '" << path << "'" << endl; + qDebug("locate: %s" , path.latin1()); + return path; +*/ +//US so my proposal is this: + +// QString escapedFilename = filename; +// escapedFilename.replace( QRegExp( "/" ), "_" ); + +#if 0 +#ifdef _WIN32_ + QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename); +#else + QString path = KStandardDirs::appDir() + type + "/" + filename; +#endif + + //US Create the containing dir if needed + QFileInfo fi ( path ); + + // QString dir=pathurl.directory(); + // QMessageBox::information( 0,"path", path, 1 ); + +#ifdef _WIN32_ + KStandardDirs::makeDir(path); +#else + KStandardDirs::makeDir(fi.dirPath( true )); +#endif + + qDebug("locate22: %s" , path.latin1()); + return path; + +#endif + +} + +QString locateLocal( const char *type, + const QString& filename, bool createDir/*US , const KInstance* inst*/ ) +{ + // try to find slashes. If there are some, we have to + // create the subdir first + int slash = filename.findRev('/')+1; + if (!slash) // only one filename +//US return inst->dirs()->saveLocation(type, QString::null, createDir) + filename; + return KGlobal::dirs()->saveLocation(type, QString::null, createDir) + filename; + + // split path from filename + QString dir = filename.left(slash); + QString file = filename.mid(slash); +//US return inst->dirs()->saveLocation(type, dir, createDir) + file; + return KGlobal::dirs()->saveLocation(type, dir, createDir) + file; + + // *************************************************************** +#if 0 + +/*US why do we put all files into one directory. It is quit complicated. +why not staying with the original directorystructure ? + + + QString escapedFilename = filename; + escapedFilename.replace( QRegExp( "/" ), "_" ); + + QString path = KStandardDirs::appDir() + type + "_" + escapedFilename; + + kdDebug() << "locate: '" << path << "'" << endl; + qDebug("locate: %s" , path.latin1()); + return path; +*/ +//US so my proposal is this: + +// QString escapedFilename = filename; +// escapedFilename.replace( QRegExp( "/" ), "_" ); + +#ifdef _WIN32_ + QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename); +#else + QString path = KStandardDirs::appDir() + type + "/" + filename; +#endif + + //US Create the containing dir if needed + KURL pathurl; + pathurl.setPath(path); + QString dir=pathurl.directory(); + // QMessageBox::information( 0,"path", path, 1 ); +#ifdef _WIN32_ + KStandardDirs::makeDir(path); +#else + KStandardDirs::makeDir(dir); +#endif + + return path; +#endif +} diff --git a/microkde/kdecore/kstandarddirs.h b/microkde/kdecore/kstandarddirs.h new file mode 100644 index 0000000..c4e1108 --- a/dev/null +++ b/microkde/kdecore/kstandarddirs.h @@ -0,0 +1,681 @@ +/* + This file is part of the KDE libraries + Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org> + Stephan Kulow <coolo@kde.org> + Waldo Bastian <bastian@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef SSK_KSTDDIRS_H +#define SSK_KSTDDIRS_H + +#include <qstring.h> +#include <qdict.h> +#include <qstringlist.h> +#include <kglobal.h> + +class KConfig; +class KStandardDirsPrivate; + + +/** + * @short Site-independent access to standard KDE directories. + * @author Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org> + * @version $Id$ + * + * This is one of the most central classes in kdelibs as + * it provides a basic service: It knows where the files + * reside on the user's hard disk. And it's meant to be the + * only one that knows -- to make the real location as + * transparent as possible to both the user and the applications. + * + * To this end it insulates the application from all information + * and applications always refer to a file with a resource type + * (e.g. icon) and a filename (e.g. khexdit.xpm). In an ideal world + * the application would make no assumption where this file is and + * leave it up to @ref KStandardDirs::findResource("apps", "Home.desktop") + * to apply this knowledge to return /opt/kde/share/applnk/Home.desktop + * or ::locate("data", "kgame/background.jpg") to return + * /opt/kde/share/apps/kgame/background.jpg + * + * The main idea behind KStandardDirs is that there are several + * toplevel prefixes below which the files lie. One of these prefixes is + * the one where the user installed kdelibs, one is where the + * application was installed, and one is $HOME/.kde, but there + * may be even more. Under these prefixes there are several well + * defined suffixes where specific resource types are to be found. + * For example, for the resource type "html" the suffixes could be + * share/doc/HTML and share/doc/kde/HTML. + * So the search algorithm basicly appends to each prefix each registered + * suffix and tries to locate the file there. + * To make the thing even more complex, it's also possible to register + * absolute paths that KStandardDirs looks up after not finding anything + * in the former steps. They can be useful if the user wants to provide + * specific directories that aren't in his $HOME/.kde directory for, + * for example, icons. + * + * @sect Standard resources that kdelibs allocates are: + * + * @li apps - Applications menu (.desktop files). + * @li cache - Cached information (e.g. favicons, web-pages) + * @li cgi - CGIs to run from kdehelp. + * @li config - Configuration files. + * @li data - Where applications store data. + * @li exe - Executables in $prefix/bin. @ref findExe() for a function that takes $PATH into account. + * @li html - HTML documentation. + * @li icon - Icons, see @ref KIconLoader. + * @li lib - Libraries. + * @li locale - Translation files for @ref KLocale. + * @li mime - Mime types. + * @li module - Module (dynamically loaded library). + * @li qtplugins - Qt plugins (dynamically loaded objects for Qt) + * @li services - Services. + * @li servicetypes - Service types. + * @li scripts - Application scripting additions. + * @li sound - Application sounds. + * @li templates - Templates + * @li wallpaper - Wallpapers. + * @li tmp - Temporary files (specfic for both current host and current user) + * @li socket - UNIX Sockets (specific for both current host and current user) + * + * A type that is added by the class @ref KApplication if you use it, is + * appdata. This one makes the use of the type data a bit easier as it + * appends the name of the application. + * So while you had to ::locate("data", "appname/filename") so you can + * also write ::locate("appdata", "filename") if your KApplication instance + * is called "appname" (as set via KApplication's constructor or KAboutData, if + * you use the global KStandardDirs object @ref KGlobal::dirs()). + * Please note though that you cannot use the "appdata" + * type if you intend to use it in an applet for Kicker because 'appname' would + * be "Kicker" instead of the applet's name. Therefore, for applets, you've got + * to work around this by using ::locate("data", "appletname/filename"). + * + * @sect KStandardDirs supports the following environment variables: + * + * @li KDEDIRS: This may set an additional number of directory prefixes to + * search for resources. The directories should be seperated + * by ':'. The directories are searched in the order they are + * specified. + * @li KDEDIR: Used for backwards compatibility. As KDEDIRS but only a single + * directory may be specified. If KDEDIRS is set KDEDIR is + * ignored. + * @li KDEHOME: The directory where changes are saved to. This directory is + * used to search for resources first. If KDEHOME is not + * specified it defaults to "$HOME/.kde" + * @li KDEROOTHOME: Like KDEHOME, but used for the root user. + * If KDEROOTHOME is not set it defaults to the .kde directory in the + * home directory of root, usually "/root/.kde". + * Note that the setting of $HOME is ignored in this case. + * + * @see KGlobalSettings + */ +class KStandardDirs +{ +public: + /** + * KStandardDirs' constructor. It just initializes the caches. + **/ + KStandardDirs( ); + + /** + * KStandardDirs' destructor. + */ + virtual ~KStandardDirs(); + + /** + * Adds another search dir to front of the @p fsstnd list. + * + * @li When compiling kdelibs, the prefix is added to this. + * @li KDEDIRS or KDEDIR is taking into account + * @li Additional dirs may be loaded from kdeglobals. + * + * @param dir The directory to append relative paths to. + */ + void addPrefix( const QString& dir ); + + /** + * Adds another search dir to front of the XDG_CONFIG_XXX list + * of prefixes. + * This prefix is only used for resources that start with "xdgconf-" + * + * @param dir The directory to append relative paths to. + */ + void addXdgConfigPrefix( const QString& dir ); + + /** + * Adds another search dir to front of the XDG_DATA_XXX list + * of prefixes. + * This prefix is only used for resources that start with "xdgdata-" + * + * @param dir The directory to append relative paths to. + */ + void addXdgDataPrefix( const QString& dir ); + + /** + * Adds suffixes for types. + * + * You may add as many as you need, but it is advised that there + * is exactly one to make writing definite. + * All basic types (@ref kde_default) are added by @ref addKDEDefaults(), + * but for those you can add more relative paths as well. + * + * The later a suffix is added, the higher its priority. Note, that the + * suffix should end with / but doesn't have to start with one (as prefixes + * should end with one). So adding a suffix for app_pics would look + * like KGlobal::dirs()->addResourceType("app_pics", "share/app/pics"); + * + * @param type Specifies a short descriptive string to access + * files of this type. + * @param relativename Specifies a directory relative to the root + * of the KFSSTND. + * @return true if successful, false otherwise. + */ + bool addResourceType( const char *type, + const QString& relativename ); + + /** + * Adds absolute path at the end of the search path for + * particular types (for example in case of icons where + * the user specifies extra paths). + * + * You shouldn't need this + * function in 99% of all cases besides adding user-given + * paths. + * + * @param type Specifies a short descriptive string to access files + * of this type. + * @param absdir Points to directory where to look for this specific + * type. Non-existant directories may be saved but pruned. + * @return true if successful, false otherwise. + */ + bool addResourceDir( const char *type, + const QString& absdir); + + /** + * Tries to find a resource in the following order: + * @li All PREFIX/\<relativename> paths (most recent first). + * @li All absolute paths (most recent first). + * + * The filename should be a filename relative to the base dir + * for resources. So is a way to get the path to libkdecore.la + * to findResource("lib", "libkdecore.la"). KStandardDirs will + * then look into the subdir lib of all elements of all prefixes + * ($KDEDIRS) for a file libkdecore.la and return the path to + * the first one it finds (e.g. /opt/kde/lib/libkdecore.la) + * + * @param type The type of the wanted resource + * @param filename A relative filename of the resource. + * + * @return A full path to the filename specified in the second + * argument, or QString::null if not found. + */ + QString findResource( const char *type, + const QString& filename ) const; + + /** + * Checks whether a resource is restricted as part of the KIOSK + * framework. When a resource is restricted it means that user- + * specific files in the resource are ignored. + * + * E.g. by restricting the "wallpaper" resource, only system-wide + * installed wallpapers will be found by this class. Wallpapers + * installed under the $KDEHOME directory will be ignored. + * + * @param type The type of the resource to check + * @param relPath A relative path in the resource. + * + * @return True if the resource is restricted. + * @since 3.1 + */ + bool isRestrictedResource( const char *type, + const QString& relPath=QString::null ) const; + + /** + * Returns a number that identifies this version of the resource. + * When a change is made to the resource this number will change. + * + * @param type The type of the wanted resource + * @param filename A relative filename of the resource. + * @param deep If true, all resources are taken into account + * otherwise only the one returned by findResource(). + * + * @return A number identifying the current version of the + * resource. + */ +/*US + Q_UINT32 calcResourceHash( const char *type, + const QString& filename, bool deep) const; +*/ + /** + * Tries to find all directories whose names consist of the + * specified type and a relative path. So would + * findDirs("apps", "Settings") return + * @li /opt/kde/share/applnk/Settings/ + * @li /home/joe/.kde/share/applnk/Settings/ + * + * Note that it appends / to the end of the directories, + * so you can use this right away as directory names. + * + * @param type The type of the base directory. + * @param reldir Relative directory. + * + * @return A list of matching directories, or an empty + * list if the resource specified is not found. + */ + QStringList findDirs( const char *type, + const QString& reldir ) const; + + /** + * Tries to find the directory the file is in. + * It works the same as @ref findResource(), but it doesn't + * return the filename but the name of the directory. + * + * This way the application can access a couple of files + * that have been installed into the same directory without + * having to look for each file. + * + * findResourceDir("lib", "libkdecore.la") would return the + * path of the subdir libkdecore.la is found first in + * (e.g. /opt/kde/lib/) + * + * @param type The type of the wanted resource + * @param filename A relative filename of the resource. + * @return The directory where the file specified in the second + * argument is located, or QString::null if the type + * of resource specified is unknown or the resource + * cannot be found. + */ + QString findResourceDir( const char *type, + const QString& filename) const; + + + /** + * Tries to find all resources with the specified type. + * + * The function will look into all specified directories + * and return all filenames in these directories. + * + * @param type The type of resource to locate directories for. + * @param filter Only accept filenames that fit to filter. The filter + * may consist of an optional directory and a @ref QRegExp + * wildcard expression. E.g. "images\*.jpg". Use QString::null + * if you do not want a filter. + * @param recursive Specifies if the function should decend + * into subdirectories. + * @param uniq If specified, only return items which have + * unique suffixes - suppressing duplicated filenames. + * + * @return A list of directories matching the resource specified, + * or an empty list if the resource type is unknown. + */ + QStringList findAllResources( const char *type, + const QString& filter = QString::null, + bool recursive = false, + bool uniq = false) const; + + /** + * Tries to find all resources with the specified type. + * + * The function will look into all specified directories + * and return all filenames (full and relative paths) in + * these directories. + * + * @param type The type of resource to locate directories for. + * @param filter Only accept filenames that fit to filter. The filter + * may consist of an optional directory and a @ref QRegExp + * wildcard expression. E.g. "images\*.jpg". Use QString::null + * if you do not want a filter. + * @param recursive Specifies if the function should decend + * into subdirectories. + * @param uniq If specified, only return items which have + * unique suffixes. + * @param list Of relative paths for the given type. + * @param relPaths The list to store the relative paths into + * These can be used later to ::locate() the file + * + * @return A list of directories matching the resource specified, + * or an empty list if the resource type is unknown. + */ + QStringList findAllResources( const char *type, + const QString& filter, + bool recursive, + bool uniq, + QStringList &relPaths) const; + + /** + * Finds the executable in the system path. + * + * A valid executable must + * be a file and have its executable bit set. + * + * @param appname The name of the executable file for which to search. + * @param pathstr The path which will be searched. If this is + * null (default), the $PATH environment variable will + * be searched. + * @param ignoreExecBit If true, an existing file will be returned + * even if its executable bit is not set. + * + * @return The path of the executable. If it was not found, + * it will return QString::null. + * @see findAllExe() + */ +/*US + static QString findExe( const QString& appname, + const QString& pathstr=QString::null, + bool ignoreExecBit=false ); +*/ + + /** + * Finds all occurences of an executable in the system path. + * + * @param list Will be filled with the pathnames of all the + * executables found. Will be empty if the executable + * was not found. + * @param appname The name of the executable for which to + * search. + * @param pathstr The path list which will be searched. If this + * is 0 (default), the $PATH environment variable will + * be searched. + * @param ignoreExecBit If true, an existing file will be returned + * even if its executable bit is not set. + * + * @return The number of executables found, 0 if none were found. + * + * @see findExe() + */ + static int findAllExe( QStringList& list, const QString& appname, + const QString& pathstr=QString::null, + bool ignoreExecBit=false ); + + /** + * This function adds the defaults that are used by the current + * KDE version. + * + * It's a series of @ref addResourceTypes() + * and @ref addPrefix() calls. + * You normally wouldn't call this function because it's called + * for you from @ref KGlobal. + */ + void addKDEDefaults(); + + /** + * Reads customized entries out of the given config object and add + * them via @ref addResourceDirs(). + * + * @param config The object the entries are read from. This should + * contain global config files + * @return true if new config paths have been added + * from @p config. + **/ + bool addCustomized(KConfig *config); + + /** + * This function is used internally by almost all other function as + * it serves and fills the directories cache. + * + * @param type The type of resource + * @return The list of possible directories for the specified @p type. + * The function updates the cache if possible. If the resource + * type specified is unknown, it will return an empty list. + * Note, that the directories are assured to exist beside the save + * location, which may not exist, but is returned anyway. + */ + QStringList resourceDirs(const char *type) const; + + /** + * This function will return a list of all the types that KStandardDirs + * supports. + * + * @return All types that KDE supports + */ + QStringList allTypes() const; + + /** + * Finds a location to save files into for the given type + * in the user's home directory. + * + * @param type The type of location to return. + * @param suffix A subdirectory name. + * Makes it easier for you to create subdirectories. + * You can't pass filenames here, you _have_ to pass + * directory names only and add possible filename in + * that directory yourself. A directory name always has a + * trailing slash ('/'). + * @param create If set, saveLocation() will create the directories + * needed (including those given by @p suffix). + * + * @return A path where resources of the specified type should be + * saved, or QString::null if the resource type is unknown. + */ + QString saveLocation(const char *type, + const QString& suffix = QString::null, + bool create = true) const; + + /** + * Converts an absolute path to a path relative to a certain + * resource. + * + * If "abs = ::locate(resource, rel)" + * then "rel = relativeLocation(resource, abs)" and vice versa. + * + * @param type The type of resource. + * + * @param absPath An absolute path to make relative. + * + * @return A relative path relative to resource @p type that + * will find @p absPath. If no such relative path exists, absPath + * will be returned unchanged. + */ + QString relativeLocation(const char *type, const QString &absPath); + + /** + * Recursively creates still-missing directories in the given path. + * + * The resulting permissions will depend on the current umask setting. + * permission = mode & ~umask. + * + * @param dir Absolute path of the directory to be made. + * @param mode Directory permissions. + * @return true if successful, false otherwise + */ + static bool makeDir(const QString& dir, int mode = 0755); + + /** + * This returns a default relative path for the standard KDE + * resource types. Below is a list of them so you get an idea + * of what this is all about. + * + * @li data - share/apps + * @li html - share/doc/HTML + * @li icon - share/icon + * @li config - share/config + * @li pixmap - share/pixmaps + * @li apps - share/applnk + * @li sound - share/sounds + * @li locale - share/locale + * @li services - share/services + * @li servicetypes - share/servicetypes + * @li mime - share/mimelnk + * @li wallpaper - share/wallpapers + * @li templates - share/templates + * @li exe - bin + * @li lib - lib + * + * @returns Static default for the specified resource. You + * should probably be using locate() or locateLocal() + * instead. + * @see locate() + * @see locateLocal() + */ + static QString kde_default(const char *type); + + /** + * @internal (for use by sycoca only) + */ + QString kfsstnd_prefixes(); + + /** + * Returns the toplevel directory in which KStandardDirs + * will store things. Most likely $HOME/.kde + * Don't use this function if you can use locateLocal + * @return the toplevel directory + */ + QString localkdedir() const; + + /** + * @return $XDG_DATA_HOME + * See also http://www.freedesktop.org/standards/basedir/draft/basedir-spec/basedir-spec.html + */ + QString localxdgdatadir() const; + + /** + * @return $XDG_CONFIG_HOME + * See also http://www.freedesktop.org/standards/basedir/draft/basedir-spec/basedir-spec.html + */ + QString localxdgconfdir() const; + + /** + * Checks for existence and accessability. + * Faster than creating a QFileInfo first. + * @param fullPath the path to check + * @return true if the directory exists + */ + static bool exists(const QString &fullPath); + + /** + * Expands all symbolic links and resolves references to + * '/./', '/../' and extra '/' characters in @p dirname + * and returns the canonicalized absolute pathname. + * The resulting path will have no symbolic link, '/./' + * or '/../' components. + * @since 3.1 + */ + static QString realPath(const QString &dirname); + + static void setAppDir( const QString & ); + static QString appDir(); + + private: + + QStringList prefixes; + + // Directory dictionaries + QDict<QStringList> absolutes; + QDict<QStringList> relatives; + + mutable QDict<QStringList> dircache; + mutable QDict<QString> savelocations; + + // Disallow assignment and copy-construction + KStandardDirs( const KStandardDirs& ); + KStandardDirs& operator= ( const KStandardDirs& ); + + bool addedCustoms; + + class KStandardDirsPrivate; + KStandardDirsPrivate *d; +//US + static QString mAppDir; + + void checkConfig() const; + void applyDataRestrictions(const QString &) const; +//US void createSpecialResource(const char*); +}; + +/** + * \addtogroup locates Locate Functions + * @{ + * On The Usage Of 'locate' and 'locateLocal' + * + * Typical KDE applications use resource files in one out of + * three ways: + * + * 1) A resource file is read but is never written. A system + * default is supplied but the user can override this + * default in his local .kde directory: + * + * \code + * // Code example + * myFile = locate("appdata", "groups.lst"); + * myData = myReadGroups(myFile); // myFile may be null + * \endcode + * + * 2) A resource file is read and written. If the user has no + * local version of the file the system default is used. + * The resource file is always written to the users local + * .kde directory. + * + * \code + * // Code example + * myFile = locate("appdata", "groups.lst") + * myData = myReadGroups(myFile); + * ... + * doSomething(myData); + * ... + * myFile = locateLocal("appdata", "groups.lst"); + * myWriteGroups(myFile, myData); + * \endcode + * + * 3) A resource file is read and written. No system default + * is used if the user has no local version of the file. + * The resource file is always written to the users local + * .kde directory. + * + * \code + * // Code example + * myFile = locateLocal("appdata", "groups.lst"); + * myData = myReadGroups(myFile); + * ... + * doSomething(myData); + * ... + * myFile = locateLocal("appdata", "groups.lst"); + * myWriteGroups(myFile, myData); + * \endcode + **/ + +/*! + * \relates KStandardDirs + * This function is just for convenience. It simply calls + *instance->dirs()->\link KStandardDirs::findResource() findResource\endlink(type, filename). + **/ +QString locate( const char *type, const QString& filename /*US , const KInstance* instance = KGlobal::instance()*/ ); + +/*! + * \relates KStandardDirs + * This function is much like locate. However it returns a + * filename suitable for writing to. No check is made if the + * specified filename actually exists. Missing directories + * are created. If filename is only a directory, without a + * specific file, filename must have a trailing slash. + * + **/ +QString locateLocal( const char *type, const QString& filename /*US , const KInstance* instance = KGlobal::instance() */ ); + +/*! + * \relates KStandardDirs + * This function is much like locate. No check is made if the + * specified filename actually exists. Missing directories + * are created if @p createDir is true. If filename is only + * a directory, without a specific file, + * filename must have a trailing slash. + * + **/ +QString locateLocal( const char *type, const QString& filename, bool createDir /*US , const KInstance* instance = KGlobal::instance() */); + +/*! @} */ + +#endif // SSK_KSTDDIRS_H diff --git a/microkde/kdecore/kstringhandler.cpp b/microkde/kdecore/kstringhandler.cpp new file mode 100644 index 0000000..b737e97 --- a/dev/null +++ b/microkde/kdecore/kstringhandler.cpp @@ -0,0 +1,650 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Ian Zepp (icszepp@islc.net) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* AIX needs strings.h for str*casecmp(), and our config.h loads it on AIX + So we don't need to include strings.h explicitly */ + +//US #include "config.h" + +#include "kstringhandler.h" +/*US +QString KStringHandler::word( const QString &text , uint pos ) +{ + QStringList list = QStringList::split( " ", text , true ); + + if ( pos < list.count() ) + return list[ pos ]; + + return ""; +} + +QString KStringHandler::word( const QString &text , const char *range ) +{ + // Format in: START:END + // Note index starts a 0 (zero) + // + // 0: first word to end + // 1:3 second to fourth words + QStringList list = QStringList::split( " ", text , true ); + QString tmp = ""; + QString r = range; + + if ( text.isEmpty() ) + return tmp; + + // do stuff here + QRegExp reg; + + int at = 0; + int pos = 0; + int cnt = 0; + + if ( r.find(QRegExp("[0-9]+:[0-9]+")) != -1 ) + { + at = r.find(":"); + pos = atoi( r.left(at).ascii() ); + cnt = atoi( r.remove(0,at+1).ascii() ); + } + else if ( r.find(QRegExp(":+[0-9]+")) != -1 ) + { + at = r.find(":"); + pos = 0; + cnt = atoi( r.remove(0,at+1).ascii() ); + } + else if ( r.find(QRegExp("[0-9]+:+")) != -1 ) + { + at = r.find(":"); + pos = atoi( r.left(at).ascii() ); + cnt = list.count(); // zero index + } + else if ( r.find(QRegExp("[0-9]+")) != -1 ) + { + pos = atoi( r.ascii() ); + cnt = pos; + } + else + { + return tmp; // not found/implemented + } + + // + // Extract words + // + int wordsToExtract = cnt-pos+1; + QStringList::Iterator it = list.at( pos); + + while ( (it != list.end()) && (wordsToExtract-- > 0)) + { + tmp += *it; + tmp += " "; + it++; + } + + return tmp.stripWhiteSpace(); +} + +// +// Insertion and removal routines +// +QString KStringHandler::insword( const QString &text , const QString &word , uint pos ) +{ + if ( text.isEmpty() ) + return word; + + if ( word.isEmpty() ) + return text; + + // Split words and add into list + QStringList list = QStringList::split( " ", text, true ); + + if ( pos >= list.count() ) + list.append( word ); + else + list.insert( list.at(pos) , word ); + + // Rejoin + return list.join( " " ); +} + +QString KStringHandler::setword( const QString &text , const QString &word , uint pos ) +{ + if ( text.isEmpty() ) + return word; + + if ( word.isEmpty() ) + return text; + + // Split words and add into list + QStringList list = QStringList::split( " ", text, true ); + + if ( pos >= list.count() ) + list.append( word ); + else + { + list.insert( list.remove( list.at(pos) ) , word ); + } + + // Rejoin + return list.join( " " ); +} + +QString KStringHandler::remrange( const QString &text , const char *range ) +{ + // Format in: START:END + // Note index starts a 0 (zero) + // + // 0: first word to end + // 1:3 second to fourth words + QStringList list = QStringList::split( " ", text , true ); + QString tmp = ""; + QString r = range; + + if ( text.isEmpty() ) + return tmp; + + // do stuff here + QRegExp reg; + + int at = 0; + int pos = 0; + int cnt = 0; + + if ( r.find(QRegExp("[0-9]+:[0-9]+")) != -1 ) + { + at = r.find(':'); + pos = atoi( r.left(at).ascii() ); + cnt = atoi( r.remove(0,at+1).ascii() ); + } + else if ( r.find(QRegExp(":+[0-9]+")) != -1 ) + { + at = r.find(':'); + pos = 0; + cnt = atoi( r.remove(0,at+1).ascii() ); + } + else if ( r.find(QRegExp("[0-9]+:+")) != -1 ) + { + at = r.find(':'); + pos = atoi( r.left(at).ascii() ); + cnt = list.count(); // zero index + } + else if ( r.find(QRegExp("[0-9]+")) != -1 ) + { + pos = atoi( r.ascii() ); + cnt = pos; + } + else + { + return text; // not found/implemented + } + + // + // Remove that range of words + // + int wordsToDelete = cnt-pos+1; + QStringList::Iterator it = list.at( pos); + + while ( (it != list.end()) && (wordsToDelete-- > 0)) + it = list.remove( it ); + + return list.join( " " ); +} + +QString KStringHandler::remword( const QString &text , uint pos ) +{ + QString tmp = ""; + + if ( text.isEmpty() ) + return tmp; + + // Split words and add into list + QStringList list = QStringList::split( " ", text, true ); + + if ( pos < list.count() ) + list.remove( list.at( pos ) ); + + // Rejoin + return list.join( " " ); +} + +QString KStringHandler::remword( const QString &text , const QString &word ) +{ + QString tmp = ""; + + if ( text.isEmpty() ) + return tmp; + + if ( word.isEmpty() ) + return text; + + // Split words and add into list + QStringList list = QStringList::split( " ", text, true ); + + QStringList::Iterator it = list.find(word); + + if (it != list.end()) + list.remove( it ); + + // Rejoin + return list.join( " " ); +} + +// +// Capitalization routines +// +QString KStringHandler::capwords( const QString &text ) +{ + QString tmp = ""; + + if ( text.isEmpty() ) + return tmp; + + QStringList list = QStringList::split( " ", text, true ); + + return capwords( QStringList::split( " ", text, true )).join( " " ); +} + +QStringList KStringHandler::capwords( const QStringList &list ) +{ + QStringList tmp; + QString word; + + if ( list.count() == 0 ) + return tmp; + + for ( QStringList::ConstIterator it= list.begin(); + it != list.end(); + it++) + { + word = *it; + word = word.left(1).upper() + word.remove(0,1); + + tmp.append( word ); // blank list to start with + } + + return tmp; +} + +// +// Reverse routines +// +QString KStringHandler::reverse( const QString &text ) +{ + QString tmp; + + if ( text.isEmpty() ) + return tmp; + + QStringList list; + list = QStringList::split( " ", text, true ); + list = reverse( list ); + + return list.join( " " ); +} + +QStringList KStringHandler::reverse( const QStringList &list ) +{ + QStringList tmp; + + if ( list.count() == 0 ) + return tmp; + + for ( QStringList::ConstIterator it= list.begin(); + it != list.end(); + it++) + tmp.prepend( *it ); + + return tmp; +} + +// +// Left, Right, Center justification +// +QString KStringHandler::ljust( const QString &text , uint width ) +{ + QString tmp = text; + tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces + + if ( tmp.length() >= width ) + return tmp; + + for ( uint pos = tmp.length() ; pos < width ; pos++ ) + tmp.append(" "); + + return tmp; +} + +QString KStringHandler::rjust( const QString &text , uint width ) +{ + QString tmp = text; + tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces + + if ( tmp.length() >= width ) + return tmp; + + for ( uint pos = tmp.length() ; pos < width ; pos++ ) + tmp.prepend(" "); + + return tmp; +} + +QString KStringHandler::center( const QString &text , uint width ) +{ + // Center is slightly different, in that it will add + // spaces to the RIGHT side (left-justified) before + // it adds a space to the LEFT side. + + QString tmp = text; + tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces + + if ( tmp.length() >= width ) + return tmp; + + bool left = false; // start at right side. + + for ( uint pos = tmp.length() ; pos < width ; pos++ ) + { + if ( left ) + tmp.prepend(" "); + else + tmp.append(" "); + + // Reverse bool + left = !left; + } + + return tmp; +} + +QString KStringHandler::lsqueeze( const QString & str, uint maxlen ) +{ + if (str.length() > maxlen) { + int part = maxlen-3; + return QString("..." + str.right(part)); + } + else return str; +} + +QString KStringHandler::csqueeze( const QString & str, uint maxlen ) +{ + if (str.length() > maxlen && maxlen > 3) { + int part = (maxlen-3)/2; + return QString(str.left(part) + "..." + str.right(part)); + } + else return str; +} + +QString KStringHandler::rsqueeze( const QString & str, uint maxlen ) +{ + if (str.length() > maxlen) { + int part = maxlen-3; + return QString(str.left(part) + "..."); + } + else return str; +} + +QString KStringHandler::lEmSqueeze(const QString &name, const QFontMetrics& fontMetrics, uint maxlen) +{ + return lPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen); +} + +static inline int emSqueezeLimit(int delta, int min, int max) +{ + if (delta < min) return min; + if (delta > max) return max; + return delta; +} + +QString KStringHandler::lPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels) +{ + uint nameWidth = fontMetrics.width(name); + + if (maxPixels < nameWidth) + { + QString tmp = name; + const uint em = fontMetrics.maxWidth(); + maxPixels -= fontMetrics.width("..."); + + while (maxPixels < nameWidth && !tmp.isEmpty()) + { + int delta = (nameWidth - maxPixels) / em; + delta = emSqueezeLimit(delta, 1, delta); // no max + + tmp.remove(0, delta); + nameWidth = fontMetrics.width(tmp); + } + + return ("..." + tmp); + } + + return name; +} + +QString KStringHandler::cEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen) +{ + return cPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen); +} + +QString KStringHandler::cPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels) +{ + uint nameWidth = fontMetrics.width(name); + + if (maxPixels < nameWidth) + { + QString tmp = name; + const uint em = fontMetrics.maxWidth(); + maxPixels -= fontMetrics.width("..."); + + while (maxPixels < nameWidth && !tmp.isEmpty()) + { + int length = tmp.length(); + int delta = (nameWidth - maxPixels) / em; + delta = emSqueezeLimit(delta, 1, length) ; + + tmp.remove((length / 2) - (delta / 2), delta); + nameWidth = fontMetrics.width(tmp); + } + + return tmp.insert((tmp.length() + 1) / 2, "..."); + } + + return name; +} + +QString KStringHandler::rEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen) +{ + return rPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen); +} + +QString KStringHandler::rPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels) +{ + uint nameWidth = fontMetrics.width(name); + + if (maxPixels < nameWidth) + { + QString tmp = name; + const uint em = fontMetrics.maxWidth(); + maxPixels -= fontMetrics.width("..."); + + while (maxPixels < nameWidth && !tmp.isEmpty()) + { + int length = tmp.length(); + int delta = (nameWidth - maxPixels) / em; + delta = emSqueezeLimit(delta, 1, length) ; + + tmp.remove(length - delta, delta); + nameWidth = fontMetrics.width(tmp); + } + + return (tmp + "..."); + } + + return name; +} + +///// File name patterns (like *.txt) + +bool KStringHandler::matchFileName( const QString& filename, const QString& pattern ) +{ + int len = filename.length(); + int pattern_len = pattern.length(); + + if (!pattern_len) + return false; + + // Patterns like "Makefile*" + if ( pattern[ pattern_len - 1 ] == '*' && len + 1 >= pattern_len ) { + const QChar *c1 = pattern.unicode(); + const QChar *c2 = filename.unicode(); + int cnt = 1; + while ( cnt < pattern_len && *c1++ == *c2++ ) + ++cnt; + return cnt == pattern_len; + } + + // Patterns like "*~", "*.extension" + if ( pattern[ 0 ] == '*' && len + 1 >= pattern_len ) + { + const QChar *c1 = pattern.unicode() + pattern_len - 1; + const QChar *c2 = filename.unicode() + len - 1; + int cnt = 1; + while ( cnt < pattern_len && *c1-- == *c2-- ) + ++cnt; + return cnt == pattern_len; + } + + // Patterns like "Makefile" + return ( filename == pattern ); +} + + QStringList +KStringHandler::perlSplit(const QString & sep, const QString & s, uint max) +{ + bool ignoreMax = 0 == max; + + QStringList l; + + int searchStart = 0; + + int tokenStart = s.find(sep, searchStart); + + while (-1 != tokenStart && (ignoreMax || l.count() < max - 1)) + { + if (!s.mid(searchStart, tokenStart - searchStart).isEmpty()) + l << s.mid(searchStart, tokenStart - searchStart); + + searchStart = tokenStart + sep.length(); + tokenStart = s.find(sep, searchStart); + } + + if (!s.mid(searchStart, s.length() - searchStart).isEmpty()) + l << s.mid(searchStart, s.length() - searchStart); + + return l; +} + + QStringList +KStringHandler::perlSplit(const QChar & sep, const QString & s, uint max) +{ + bool ignoreMax = 0 == max; + + QStringList l; + + int searchStart = 0; + + int tokenStart = s.find(sep, searchStart); + + while (-1 != tokenStart && (ignoreMax || l.count() < max - 1)) + { + if (!s.mid(searchStart, tokenStart - searchStart).isEmpty()) + l << s.mid(searchStart, tokenStart - searchStart); + + searchStart = tokenStart + 1; + tokenStart = s.find(sep, searchStart); + } + + if (!s.mid(searchStart, s.length() - searchStart).isEmpty()) + l << s.mid(searchStart, s.length() - searchStart); + + return l; +} + + QStringList +KStringHandler::perlSplit(const QRegExp & sep, const QString & s, uint max) +{ + bool ignoreMax = 0 == max; + + QStringList l; + + int searchStart = 0; + int tokenStart = sep.search(s, searchStart); + int len = sep.matchedLength(); + + while (-1 != tokenStart && (ignoreMax || l.count() < max - 1)) + { + if (!s.mid(searchStart, tokenStart - searchStart).isEmpty()) + l << s.mid(searchStart, tokenStart - searchStart); + + searchStart = tokenStart + len; + tokenStart = sep.search(s, searchStart); + len = sep.matchedLength(); + } + + if (!s.mid(searchStart, s.length() - searchStart).isEmpty()) + l << s.mid(searchStart, s.length() - searchStart); + + return l; +} +US end */ + +/*US + QString +KStringHandler::tagURLs( const QString& text ) +{ + QRegExp urlEx("(www\\.(?!\\.)|(f|ht)tp(|s)://)[\\d\\w\\./,:_~\\?=&;#@\\-\\+\\%]+[\\d\\w/]"); + + QString richText( text ); + int urlPos = 0, urlLen; + while ((urlPos = urlEx.search(richText, urlPos)) >= 0) + { + urlLen = urlEx.matchedLength(); + QString href = richText.mid( urlPos, urlLen ); + // Qt doesn't support (?<=pattern) so we do it here + if((urlPos > 0) && richText[urlPos-1].isLetterOrNumber()){ + urlPos++; + continue; + } + // Don't use QString::arg since %01, %20, etc could be in the string + QString anchor = "<a href=\"" + href + "\">" + href + "</a>"; + richText.replace( urlPos, urlLen, anchor ); + + + urlPos += anchor.length(); + } + return richText; +} +*/ +QString KStringHandler::obscure( const QString &str ) +{ + QString result; + for ( uint i = 0; i < str.length(); ++i ) + result += ( str.at( i ).unicode() < 0x20 ) ? str.at( i ) : + QChar( 0x1001F - str.at( i ).unicode() ); + + return result; +} diff --git a/microkde/kdecore/kstringhandler.h b/microkde/kdecore/kstringhandler.h new file mode 100644 index 0000000..d07b1e2 --- a/dev/null +++ b/microkde/kdecore/kstringhandler.h @@ -0,0 +1,417 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Ian Zepp (icszepp@islc.net) + Copyright (C) 2000 Rik Hemsley (rikkus) <rik@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KSTRINGHANDLER_H +#define KSTRINGHANDLER_H + +#include <stdlib.h> // for atoi() +#include <qstring.h> +#include <qstringlist.h> +#include <qregexp.h> // for the word ranges +#include <qfontmetrics.h> + +/** + * This class contains utility functions for handling strings. + * + * This class is @em not a substitute for the @ref QString class. What + * I tried to do with this class is provide an easy way to + * cut/slice/splice words inside sentences in whatever order desired. + * While the main focus of this class are words (ie characters + * separated by spaces/tabs), the two core functions here (@ref split() + * and @ref join() ) will function given any char to use as a separator. + * This will make it easy to redefine what a 'word' means in the + * future if needed. + * + * I freely stole some of the function names from python. I also think + * some of these were influenced by mIRC (yes, believe it if you will, I + * used to write a LOT of scripts in mIRC). + * + * The ranges are a fairly powerful way of getting/stripping words from + * a string. These ranges function, for the large part, as they would in + * python. See the @ref word(const QString&, int) and @ref remword(const QString&, int) functions for more detail. + * + * This class contains no data members of it own. All strings are cut + * on the fly and returned as new qstrings/qstringlists. + * + * Quick example on how to use: + * + * <pre> + * KStringHandler kstr; + * QString line = "This is a test of the strings"; + * + * cout << "1> " << kstr.word( line , "4:" ) << "\n"; + * cout << "2> " << kstr.remrange( line , "2:5" ) << "\n"; + * cout << "2> " << kstr.reverse( line ) << "\n"; + * cout << "2> " << kstr.center( kstr.word( line , 4 ) , 15 ) << "\n"; + * </pre> + * + * and so forth. + * + * @short Class for manipulating words and sentences in strings + * @author Ian Zepp <icszepp@islc.net> + */ +class KStringHandler +{ +public: + /** Returns the nth word in the string if found + * Returns a EMPTY (not null) string otherwise. + * Note that the FIRST index is 0. + * @param text the string to search for the words + * @param pos the position of the word to search + * @return the word, or an empty string if not found + */ +//US static QString word( const QString &text , uint pos ); + + /** Returns a range of words from that string. + * Ie: + * @li "0" returns the very first word + * @li "0:" returns the first to the last word + * @li "0:3" returns the first to fourth words + * @li ":3" returns everything up to the fourth word + * + * If you grok python, you're set. + * @param text the string to search for the words + * @param range the words to return (see description) + * @return the words, or an empty string if not found + */ +//US static QString word( const QString &text , const char *range ); + + /** Inserts a word into the string, and returns + * a new string with the word included. the first + * index is zero (0). If there are not @p pos words in the original + * string, the new word will be appended to the end. + * @param text the original text + * @param word the word to insert + * @param pos the position (in words) for the new word + * @return the resulting string + */ +//US static QString insword( const QString &text , const QString &word , uint pos ); + + /** Replaces a word in the string, and returns + * a new string with the word included. the first + * index is zero (0). If there are not @p pos words in the original + * string, the new word will be appended to the end. + * @param text the original text + * @param word the word to insert + * @param pos the position (in words) for the new word + * @return the resulting string + */ +//US static QString setword( const QString &text , const QString &word , uint pos ); + + /** Removes a word or ranges of words from the string, + * and returns a new string. The ranges definitions + * follow the definitions for the word() function. + * + * @li "0" removes the very first word + * @li "0:" removes the first the the last word + * @li "0:3" removes the first to fourth words + * @li ":3" removes everything up to the fourth word + * @param text the original text + * @param range the words to remove (see description) + * @return the resulting string + */ +//US static QString remrange( const QString &text , const char *range ); + + + /** Removes a word at the given index, and returns a + * new string. The first index is zero (0). + * @param text the original text + * @param pos the position (in words) of thw word to delete + * @return the resulting string + */ +//US static QString remword( const QString &text , uint pos ); + + /** Removes a matching word from the string, and returns + * a new string. Note that only ONE match is removed. + * @param text the original text + * @param word the word to remove + * @return the resulting string + */ +//US static QString remword( const QString &text , const QString &word ); + + /** Capitalizes each word in the string + * "hello there" becomes "Hello There" (string) + * @param text the text to capitalize + * @return the resulting string + */ +//US static QString capwords( const QString &text ); + + /** Capitalizes each word in the list + * [hello, there] becomes [Hello, There] (list) + * @param list the list to capitalize + * @return the resulting list + */ +//US static QStringList capwords( const QStringList &list ); + + /** Reverses the order of the words in a string + * "hello there" becomes "there hello" (string) + * @param text the text to reverse + * @return the resulting string + */ +//US static QString reverse( const QString &text ); + + /** Reverses the order of the words in a list + * [hello, there] becomes [there, hello] (list) + * @param list the list to reverse + * @return the resulting list + */ +//US static QStringList reverse( const QStringList &list ); + + /** Left-justifies a string and returns a string at least 'width' characters + * wide. + * If the string is longer than the @p width, the original + * string is returned. It is never truncated. + * @param text the text to justify + * @param width the desired width of the new string + * @return the resulting string + */ +//US static QString ljust( const QString &text , uint width ); + + /** Right-justifies a string and returns a string at least 'width' characters + * wide. + * If the string is longer than the @p width, the original + * string is returned. It is never truncated. + * @param text the text to justify + * @param width the desired width of the new string + * @return the resulting string + */ +//US static QString rjust( const QString &text , uint width ); + + /** Centers a string and returns a string at least 'width' characters + * wide. + * If the string is longer than the @p width, the original + * string is returned. It is never truncated. + * @param text the text to justify + * @param width the desired width of the new string + * @return the resulting string + */ +//US static QString center( const QString &text , uint width ); + + /** Substitute characters at the beginning of a string by "...". + * @param str is the string to modify + * @param maxlen is the maximum length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + */ +//US static QString lsqueeze( const QString & str, uint maxlen = 40 ); + + /** Substitute characters at the beginning of a string by "...". Similar to + * method above, except that it truncates based on pixel width rather than + * the number of characters + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxlen is the maximum length in ems the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString lEmSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxlen = 30 ); + + /** Substitute characters at the beginning of a string by "...". Similar to + * method above, except that maxlen is the width in pixels to truncate to + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxPixels is the maximum pixel length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString lPixelSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxPixels ); + + /** Substitute characters at the middle of a string by "...". + * @param str is the string to modify + * @param maxlen is the maximum length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + */ +//US static QString csqueeze( const QString & str, uint maxlen = 40 ); + + /** Substitute characters in the middle of a string by "...". Similar to + * method above, except that it truncates based on pixel width rather than + * the number of characters + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxlen is the maximum length in ems the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString cEmSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxlen = 30 ); + + /** Substitute characters in the middle of a string by "...". Similar to + * method above, except that maxlen is the width in pixels to truncate to + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxPixels is the maximum pixel length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString cPixelSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxPixels ); + + /** Substitute characters at the end of a string by "...". + * @param str is the string to modify + * @param maxlen is the maximum length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + */ + static QString rsqueeze( const QString & str, uint maxlen = 40 ); + + /** Substitute characters at the end of a string by "...". Similar to + * method above, except that it truncates based on pixel width rather than + * the number of characters + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxlen is the maximum length in ems the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString rEmSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxlen = 30 ); + + /** Substitute characters at the end of a string by "...". Similar to + * method above, except that maxlen is the width in pixels to truncate to + * @param name is the string to modify + * @param fontMetrics is the font metrics to use to calculate character sizes + * @param maxPixels is the maximum pixel length the modified string will have + * If the original string is shorter than "maxlen", it is returned verbatim + * @return the modified string + * @since 3.2 + */ +//US static QString rPixelSqueeze( const QString & name, +//US const QFontMetrics& fontMetrics, +//US uint maxPixels ); + + /** + * Match a filename. + * @param filename is the real decoded filename (or dirname + * without trailing '/'). + * @param pattern is a pattern like *.txt, *.tar.gz, Makefile.*, etc. + * Patterns with two asterisks like "*.*pk" are not supported. + * @return true if the given filename matches the given pattern + */ +//US static bool matchFileName( const QString& filename, const QString& pattern ); + + /** + * Split a QString into a QStringList in a similar fashion to the static + * QStringList function in Qt, except you can specify a maximum number + * of tokens. If max is specified (!= 0) then only that number of tokens + * will be extracted. The final token will be the remainder of the string. + * + * Example: + * <pre> + * perlSplit("__", "some__string__for__you__here", 4) + * QStringList contains: "some", "string", "for", "you__here" + * </pre> + * + * @param sep is the string to use to delimit s. + * @param s is the input string + * @param max is the maximum number of extractions to perform, or 0. + * @return A QStringList containing tokens extracted from s. + */ +//US static QStringList perlSplit +//US (const QString & sep, const QString & s, uint max = 0); + + /** + * Split a QString into a QStringList in a similar fashion to the static + * QStringList function in Qt, except you can specify a maximum number + * of tokens. If max is specified (!= 0) then only that number of tokens + * will be extracted. The final token will be the remainder of the string. + * + * Example: + * <pre> + * perlSplit(' ', "kparts reaches the parts other parts can't", 3) + * QStringList contains: "kparts", "reaches", "the parts other parts can't" + * </pre> + * + * @param sep is the character to use to delimit s. + * @param s is the input string + * @param max is the maximum number of extractions to perform, or 0. + * @return A QStringList containing tokens extracted from s. + */ +//US static QStringList perlSplit +//US (const QChar & sep, const QString & s, uint max = 0); + + /** + * Split a QString into a QStringList in a similar fashion to the static + * QStringList function in Qt, except you can specify a maximum number + * of tokens. If max is specified (!= 0) then only that number of tokens + * will be extracted. The final token will be the remainder of the string. + * + * Example: + * <pre> + * perlSplit(QRegExp("[! ]", "Split me up ! I'm bored ! OK ?", 3) + * QStringList contains: "Split", "me", "up ! I'm bored, OK ?" + * </pre> + * + * @param sep is the regular expression to use to delimit s. + * @param s is the input string + * @param max is the maximum number of extractions to perform, or 0. + * @return A QStringList containing tokens extracted from s. + */ +//US static QStringList perlSplit +//US (const QRegExp & sep, const QString & s, uint max = 0); + + /** + * This method auto-detects URLs in strings, and adds HTML markup to them + * so that richtext or HTML-enabled widgets (such as KActiveLabel) + * will display the URL correctly. + * @param text the string which may contain URLs + * @return the resulting text + * @since 3.1 + */ +//US static QString tagURLs( const QString& text ); + + /** + Obscure string by using a simple symmetric encryption. Applying the + function to a string obscured by this function will result in the original + string. + + The function can be used to obscure passwords stored to configuration + files. Note that this won't give you any more security than preventing + that the password is directly copied and pasted. + + @param str string to be obscured + @return obscured string + @since 3.2 + */ + static QString obscure( const QString &str ); + +#ifdef KDE_NO_COMPAT +private: +#endif + /** + * @deprecated Use @see matchFileName () instead. + */ +/*US static bool matchFilename( const QString& filename, const QString& pattern ) + { + return matchFileName (filename, pattern); + }; +*/ +}; +#endif diff --git a/microkde/kdemacros.h b/microkde/kdemacros.h new file mode 100644 index 0000000..698a15a --- a/dev/null +++ b/microkde/kdemacros.h @@ -0,0 +1,105 @@ +/* This file is part of the KDE libraries + Copyright (c) 2002-2003 KDE Team + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _KDE_MACROS_H_ +#define _KDE_MACROS_H_ + +/** + * The KDE_NO_EXPORT macro marks the symbol of the given variable + * to be hidden. A hidden symbol is stripped during the linking step, + * so it can't be used from outside the resulting library, which is similiar + * to static. However, static limits the visibility to the current + * compilation unit. hidden symbols can still be used in multiple compilation + * units. + * + * \code + * int KDE_NO_EXPORT foo; + * int KDE_EXPORT bar; + * \end + */ + +#if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 > 2) +#define KDE_NO_EXPORT __attribute__ ((visibility("hidden"))) +#define KDE_EXPORT __attribute__ ((visibility("visible"))) +#else +#define KDE_NO_EXPORT +#define KDE_EXPORT +#endif + +/** + * The KDE_PACKED can be used to hint the compiler that a particular + * structure or class should not contain unnecessary paddings. + */ + +#ifdef __GNUC__ +#define KDE_PACKED __attribute__((__packed__)) +#else +#define KDE_PACKED +#endif + +/** + * The KDE_DEPRECATED macro can be used to trigger compile-time warnings + * with gcc >= 3.2 when deprecated functions are used. + * + * For non-inline functions, the macro gets inserted at the very end of the + * function declaration, right before the semicolon: + * + * \code + * DeprecatedConstructor() KDE_DEPRECATED; + * void deprecatedFunctionA() KDE_DEPRECATED; + * int deprecatedFunctionB() const KDE_DEPRECATED; + * \endcode + * + * Functions which are implemented inline are handled differently: for them, + * the KDE_DEPRECATED macro is inserted at the front, right before the return + * type, but after "static" or "virtual": + * + * \code + * KDE_DEPRECATED void deprecatedInlineFunctionA() { .. } + * virtual KDE_DEPRECATED int deprecatedInlineFunctionB() { .. } + * static KDE_DEPRECATED bool deprecatedInlineFunctionC() { .. } + * \end + * + * You can also mark whole structs or classes as deprecated, by inserting the + * KDE_DEPRECATED macro after the struct/class keyword, but before the + * name of the struct/class: + * + * \code + * class KDE_DEPRECATED DeprecatedClass { }; + * struct KDE_DEPRECATED DeprecatedStruct { }; + * \endcode + * + * \note + * It does not make much sense to use the KDE_DEPRECATED keyword for a Qt signal + * or a slot; this is because signals and slots always get referenced by the + * code generated by moc. + * + * \par + * Also note that it is not possible to use KDE_DEPRECATED for classes which + * use the k_dcop keyword (to indicate a DCOP interface declaration); this is + * because the dcopidl program would choke on the unexpected declaration + * syntax. + */ +#if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2) +# define KDE_DEPRECATED __attribute__ ((deprecated)) +#else +# define KDE_DEPRECATED +#endif + +#endif // _KDE_MACROS_H_ diff --git a/microkde/kdeui/kaction.cpp b/microkde/kdeui/kaction.cpp new file mode 100644 index 0000000..77d36a5 --- a/dev/null +++ b/microkde/kdeui/kaction.cpp @@ -0,0 +1,1215 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + (C) 2002 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kaction.h" + +#include <assert.h> + +#include <qtooltip.h> +//US#include <qwhatsthis.h> +//US#include <kaccel.h> +//US#include <kaccelbase.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kguiitem.h> +//US#include <kmainwindow.h> +//US#include <kmenubar.h> +//US#include <kpopupmenu.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> + +//US added this includefiles +#include <qmenubar.h> +#include <qtoolbar.h> +#include <qpopupmenu.h> +#include <qiconset.h> + +/** +* How it works. +* KActionCollection is an organizing container for KActions. +* KActionCollection keeps track of the information necessary to handle +* configuration and shortcuts. +* +* Focus Widget pointer: +* This is the widget which is the focus for action shortcuts. +* It is set either by passing a QWidget* to the KActionCollection constructor +* or by calling setWidget() if the widget wasn't known when the object was +* initially constructed (as in KXMLGUIClient and KParts::PartBase) +* +* Shortcuts: +* An action's shortcut will not not be connected unless a focus widget has +* been specified in KActionCollection. +* +* XML Filename: +* This is used to save user-modified settings back to the *ui.rc file. +* It is set by KXMLGUIFactory. +*/ + +int KAction::getToolButtonID() +{ + static int toolbutton_no = -2; + return toolbutton_no--; +} + +//--------------------------------------------------------------------- +// KAction::KActionPrivate +//--------------------------------------------------------------------- + +class KAction::KActionPrivate : public KGuiItem +{ +public: + KActionPrivate() : KGuiItem() + { + m_kaccel = 0; + m_configurable = true; + } + + KAccel *m_kaccel; + QValueList<KAccel*> m_kaccelList; + + QString m_groupText; + QString m_group; + + KShortcut m_cut; + KShortcut m_cutDefault; + + bool m_configurable; + + struct Container + { + Container() { m_container = 0; m_representative = 0; m_id = 0; } + Container( const Container& s ) { m_container = s.m_container; + m_id = s.m_id; m_representative = s.m_representative; } + QWidget* m_container; + int m_id; + QWidget* m_representative; + }; + + QValueList<Container> m_containers; +}; + +//--------------------------------------------------------------------- +// KAction +//--------------------------------------------------------------------- +KAction::KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); +} + +KAction::KAction( const QString& text, const QString& sIconName, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconName( sIconName ); +} + +KAction::KAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconSet( pix ); +} +KAction::KAction( const KGuiItem& item, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( item.text(), cut, receiver, slot ); + if( item.hasIconSet() ) + setIcon( item.iconName() ); + setToolTip( item.toolTip() ); + setWhatsThis( item.whatsThis() ); +} + +// KDE 4: remove +KAction::KAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, 0, 0 ); +} +KAction::KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); +} +KAction::KAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, 0, 0 ); + setIconSet( pix ); +} + +KAction::KAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) +: QObject( parent, name ) +{ + initPrivate( text, cut, 0, 0 ); + d->setIconName( pix ); +} + +KAction::KAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); + setIconSet( pix ); +} + +KAction::KAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name ) + : QObject( parent, name ) +{ + initPrivate( text, cut, receiver, slot ); + d->setIconName(pix); +} + +KAction::KAction( QObject* parent, const char* name ) + : QObject( parent, name ) +{ + + initPrivate( QString::null, KShortcut(), 0, 0 ); +} +// KDE 4: remove end + +KAction::~KAction() +{ + kdDebug(129) << "KAction::~KAction( this = \"" << name() << "\" )" << endl; // -- ellis +#ifndef KDE_NO_COMPAT + if (d->m_kaccel) + unplugAccel(); +#endif + + // If actionCollection hasn't already been destructed, + if ( m_parentCollection ) { + m_parentCollection->take( this ); + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) +//US d->m_kaccelList[i]->remove( name() ); + qDebug("KAction::KAction~ ...1 has top be fixed"); + } + + // Do not call unplugAll from here, as tempting as it sounds. + // KAction is designed around the idea that you need to plug + // _and_ to unplug it "manually". Unplugging leads to an important + // slowdown when e.g. closing the window, in which case we simply + // want to destroy everything asap, not to remove actions one by one + // from the GUI. + + delete d; d = 0; +} + +void KAction::initPrivate( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot ) +{ + d = new KActionPrivate; + + d->m_cutDefault = cut; + +//US m_parentCollection = dynamic_cast<KActionCollection *>( parent() ); + m_parentCollection = (KActionCollection *)( parent() ); + kdDebug(129) << "KAction::initPrivate(): this = " << this << " name = \"" << name() << "\" cut = " << cut.toStringInternal() << " m_parentCollection = " << m_parentCollection << endl; + if ( m_parentCollection ) + m_parentCollection->insert( this ); + + if ( receiver && slot ) + connect( this, SIGNAL( activated() ), receiver, slot ); + + if( !cut.isNull() && qstrcmp( name(), "unnamed" ) == 0 ) + kdWarning(129) << "KAction::initPrivate(): trying to assign a shortcut (" << cut.toStringInternal() << ") to an unnamed action." << endl; + d->setText( text ); + initShortcut( cut ); + +} + +bool KAction::isPlugged() const +{ + return (containerCount() > 0) || d->m_kaccel; +} + +bool KAction::isPlugged( const QWidget *container ) const +{ + return findContainer( container ) > -1; +} + +bool KAction::isPlugged( const QWidget *container, int id ) const +{ + int i = findContainer( container ); + return ( i > -1 && itemId( i ) == id ); +} + +bool KAction::isPlugged( const QWidget *container, const QWidget *_representative ) const +{ + int i = findContainer( container ); + return ( i > -1 && representative( i ) == _representative ); +} + + +/* +Three actionCollection conditions: + 1) Scope is known on creation and KAccel object is created (e.g. KMainWindow) + 2) Scope is unknown and no KAccel object is available (e.g. KXMLGUIClient) + a) addClient() will be called on object + b) we just want to add the actions to another KXMLGUIClient object + +The question is how to do we incorporate #2b into the XMLGUI framework? + + +We have a KCommandHistory object with undo and redo actions in a passed actionCollection +We have a KoDoc object which holds a KCommandHistory object and the actionCollection +We have two KoView objects which both point to the same KoDoc object +Undo and Redo should be available in both KoView objects, and + calling the undo->setEnabled() should affect both KoViews + +When addClient is called, it needs to be able to find the undo and redo actions +When it calls plug() on them, they need to be inserted into the KAccel object of the appropriate KoView + +In this case, the actionCollection belongs to KoDoc and we need to let it know that its shortcuts +have the same scope as the KoView actionCollection + +KXMLGUIClient::addSubActionCollection + +Document: + create document actions + +View + create view actions + add document actionCollection as sub-collection + +A parentCollection is created +Scenario 1: parentCollection has a focus widget set (e.g. via KMainWindow) + A KAccel object is created in the parentCollection + A KAction is created with parent=parentCollection + The shortcut is inserted into this actionCollection + Scenario 1a: xml isn't used + done + Scenario 1b: KXMLGUIBuilder::addClient() called + setWidget is called -- ignore + shortcuts are set +Scenario 2: parentCollection has no focus widget (e.g., KParts) + A KAction is created with parent=parentCollection + Scenario 2a: xml isn't used + no shortcuts + Scenario 2b: KXMLGUIBuilder::addClient() called + setWidget is called + shortcuts are inserted into current KAccel + shortcuts are set in all other KAccels, if the action is present in the other KAccels +*/ + +/* +shortcut may be set: + - on construction + - on plug + - on reading XML + - on plugAccel (deprecated) + +On Construction: [via initShortcut()] + insert into KAccel of m_parentCollection, + if kaccel() && isAutoConnectShortcuts() exists + +On Plug: [via plug() -> plugShortcut()] + insert into KAccel of m_parentCollection, if exists and not already inserted into + +On Read XML: [via setShortcut()] + set in all current KAccels + insert into KAccel of m_parentCollection, if exists and not already inserted into +*/ + +KAccel* KAction::kaccelCurrent() +{ + if( m_parentCollection && m_parentCollection->builderKAccel() ) + return m_parentCollection->builderKAccel(); + else if( m_parentCollection && m_parentCollection->kaccel() ) + return m_parentCollection->kaccel(); + else + return 0L; +} + +// Only to be called from initPrivate() +bool KAction::initShortcut( const KShortcut& cut ) +{ + d->m_cut = cut; + + // Only insert action into KAccel if it has a valid name, + if( qstrcmp( name(), "unnamed" ) != 0 && + m_parentCollection && + m_parentCollection->isAutoConnectShortcuts() && + m_parentCollection->kaccel() ) + { + insertKAccel( m_parentCollection->kaccel() ); + return true; + } + return false; + } + +// Only to be called from plug() +void KAction::plugShortcut() +{ + KAccel* kaccel = kaccelCurrent(); + + //kdDebug(129) << "KAction::plugShortcut(): this = " << this << " kaccel() = " << (m_parentCollection ? m_parentCollection->kaccel() : 0) << endl; + if( kaccel && qstrcmp( name(), "unnamed" ) != 0 ) { + // Check if already plugged into current KAccel object + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + if( d->m_kaccelList[i] == kaccel ) + return; + } + + insertKAccel( kaccel ); + } +} + +bool KAction::setShortcut( const KShortcut& cut ) +{ + qDebug("KAction::setShortcut~ ...1 has top be fixed"); +/*US + bool bChanged = (d->m_cut != cut); + d->m_cut = cut; + + KAccel* kaccel = kaccelCurrent(); + bool bInsertRequired = true; + // Apply new shortcut to all existing KAccel objects + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + // Check whether shortcut has already been plugged into + // the current kaccel object. + if( d->m_kaccelList[i] == kaccel ) + bInsertRequired = false; + if( bChanged ) + updateKAccelShortcut( d->m_kaccelList[i] ); + } + + // Only insert action into KAccel if it has a valid name, + if( kaccel && bInsertRequired && qstrcmp( name(), "unnamed" ) ) + insertKAccel( kaccel ); + + if( bChanged ) { + // KDE 4: remove + if ( d->m_kaccel ) + d->m_kaccel->setShortcut( name(), cut ); + // KDE 4: remove end + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateShortcut( i ); + } +*/ + + return true; +} + +bool KAction::updateKAccelShortcut( KAccel* kaccel ) +{ + qDebug("KAction::updateKAccelShortcut~ ...1 has top be fixed"); + // Check if action is permitted +/*US + if (kapp && !kapp->authorizeKAction(name())) + return false; + + bool b = true; + + if ( !kaccel->actions().actionPtr( name() ) ) { + if(!d->m_cut.isNull() ) { + kdDebug(129) << "Inserting " << name() << ", " << d->text() << ", " << d->plainText() << endl; + b = kaccel->insert( name(), d->plainText(), QString::null, + d->m_cut, + this, SLOT(slotActivated()), + isShortcutConfigurable(), isEnabled() ); + } + } + else + b = kaccel->setShortcut( name(), d->m_cut ); + + return b; +*/ + return true; +} + +void KAction::insertKAccel( KAccel* kaccel ) +{ + qDebug("KAction::updateKAccelShortcut~ ...1 has top be fixed"); +/*US + //kdDebug(129) << "KAction::insertKAccel( " << kaccel << " ): this = " << this << endl; + if ( !kaccel->actions().actionPtr( name() ) ) { + if( updateKAccelShortcut( kaccel ) ) { + d->m_kaccelList.append( kaccel ); + connect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) ); + } + } + else + kdWarning(129) << "KAction::insertKAccel( kaccel = " << kaccel << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis +*/ +} + +void KAction::removeKAccel( KAccel* kaccel ) +{ + qDebug("KAction::removeKAccel~ ...1 has top be fixed"); +/*US + //kdDebug(129) << "KAction::removeKAccel( " << i << " ): this = " << this << endl; + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + if( d->m_kaccelList[i] == kaccel ) { + kaccel->remove( name() ); + d->m_kaccelList.remove( d->m_kaccelList.at( i ) ); + disconnect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) ); + break; + } + } +*/ +} + +// KDE 4: remove +void KAction::setAccel( int keyQt ) +{ + setShortcut( KShortcut(keyQt) ); +} +// KDE 4: remove end + +void KAction::updateShortcut( int i ) +{ + int id = itemId( i ); + + QWidget* w = container( i ); + if ( w->inherits( "QPopupMenu" ) ) { + QPopupMenu* menu = static_cast<QPopupMenu*>(w); + updateShortcut( menu, id ); + } + else if ( w->inherits( "QMenuBar" ) ) +//US static_cast<QMenuBar*>(w)->setAccel( d->m_cut.keyCodeQt(), id ); +//US (QMenuBar*)(w)->setAccel( d->m_cut.keyCodeQt(), id ); + qDebug("KAction::updateShortcut( int i ) ...1 has top be fixed"); + +} + +void KAction::updateShortcut( QPopupMenu* menu, int id ) +{ +/*US + //kdDebug(129) << "KAction::updateShortcut(): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl; + // If the action has a KAccel object, + // show the string representation of its shortcut. + if ( d->m_kaccel || d->m_kaccelList.count() ) { + QString s = menu->text( id ); + int i = s.find( '\t' ); + if ( i >= 0 ) + s.replace( i+1, s.length()-i, d->m_cut.seq(0).toString() ); + else + s += "\t" + d->m_cut.seq(0).toString(); + + menu->changeItem( id, s ); + } + // Otherwise insert the shortcut itself into the popup menu. + else { + // This is a fall-hack in case the KAction is missing a proper parent collection. + // It should be removed eventually. --ellis + menu->setAccel( d->m_cut.keyCodeQt(), id ); + kdWarning(129) << "KAction::updateShortcut(): name = \"" << name() << "\", cut = " << d->m_cut.toStringInternal() << "; No KAccel, probably missing a parent collection." << endl; + } +*/ + qDebug("KAction::updateShortcut( QPopupMenu* menu, int id ) ...1 has top be fixed"); + +} + +const KShortcut& KAction::shortcut() const +{ + return d->m_cut; +} + +const KShortcut& KAction::shortcutDefault() const +{ + return d->m_cutDefault; +} + +QString KAction::shortcutText() const +{ + return d->m_cut.toStringInternal(); +} + +void KAction::setShortcutText( const QString& s ) +{ + setShortcut( KShortcut(s) ); +} + +int KAction::accel() const +{ + qDebug("KAction::accel() ...1 has top be fixed"); +//US return d->m_cut.keyCodeQt(); + return 0; +} + +void KAction::setGroup( const QString& grp ) +{ + d->m_group = grp; + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateGroup( i ); +} + +void KAction::updateGroup( int ) +{ + // DO SOMETHING +} + +QString KAction::group() const +{ + return d->m_group; +} + +bool KAction::isEnabled() const +{ + return d->isEnabled(); +} + +bool KAction::isShortcutConfigurable() const +{ + return d->m_configurable; +} + +void KAction::setToolTip( const QString& tt ) +{ + qDebug("KAction::setToolTip ...1 has top be fixed"); + d->setToolTip( tt ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateToolTip( i ); +} + +void KAction::updateToolTip( int i ) +{ + qDebug("KAction::updateToolTip ...1 has top be fixed"); + QWidget *w = container( i ); + + if ( w->inherits( "KToolBar" ) ) + QToolTip::add( static_cast<KToolBar*>(w)->getWidget( itemId( i ) ), d->toolTip() ); + else if ( w->inherits( "QToolBar" ) ) + QToolTip::add( static_cast<KToolBar*>(w)->getWidget( itemId( i ) ), d->toolTip() ); +} + +QString KAction::toolTip() const +{ + return d->toolTip(); +} + +int KAction::plug( QWidget *w, int index ) +{ + //kdDebug(129) << "KAction::plug( " << w << ", " << index << " )" << endl; + if (w == 0) { + kdWarning(129) << "KAction::plug called with 0 argument\n"; + return -1; + } + +#ifndef NDEBUG + KAccel* kaccel = kaccelCurrent(); + // If there is a shortcut, but no KAccel available + if( !d->m_cut.isNull() && kaccel == 0 ) { + kdWarning(129) << "KAction::plug(): has no KAccel object; this = " << this << " name = " << name() << " parentCollection = " << m_parentCollection << endl; // ellis +//US kdDebug(129) << kdBacktrace() << endl; + } +#endif + + // Check if action is permitted +//US if (kapp && !kapp->authorizeKAction(name())) +//US return -1; + + plugShortcut(); + + if ( w->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( w ); + int id; + // Don't insert shortcut into menu if it's already in a KAccel object. + //qDebug("KAction::plug warning: real shortcuts not available yet. "); +//US int keyQt = (d->m_kaccelList.count() || d->m_kaccel) ? 0 : d->m_cut.keyCodeQt(); + int keyQt = 0; + + if ( d->hasIcon() ) + { +/*US + KInstance *instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + id = menu->insertItem( d->iconSet( KIcon::Small, 0/*US , instance */), d->text(), this,//dsweet + SLOT( slotActivated() ), keyQt, + -1, index ); + } + else + id = menu->insertItem( d->text(), this, + SLOT( slotActivated() ), //dsweet + keyQt, -1, index ); + + // If the shortcut is already in a KAccel object, then + // we need to set the menu item's shortcut text. +/*US if ( d->m_kaccelList.count() || d->m_kaccel ) + updateShortcut( menu, id ); +*/ + // call setItemEnabled only if the item really should be disabled, + // because that method is slow and the item is per default enabled + if ( !d->isEnabled() ) + menu->setItemEnabled( id, false ); + + if ( !d->whatsThis().isEmpty() ) + menu->setWhatsThis( id, whatsThisWithIcon() ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( menu, this ); + + return d->m_containers.count() - 1; + } + else if ( w->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( w ); + + int id_ = getToolButtonID(); +/*US + KInstance *instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + if ( icon().isEmpty() && !iconSet().pixmap().isNull() ) // old code using QIconSet directly + { + bar->insertButton( iconSet().pixmap(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + d->isEnabled(), d->plainText(), index ); + } + else + { + QString icon = d->iconName(); + if ( icon.isEmpty() ) + icon = "unknown"; + bar->insertButton( icon, id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + d->isEnabled(), d->plainText(), index/*US, instance*/ ); + } + bar->getButton( id_ )->setName( QCString("toolbutton_")+name() ); + +//US if ( !d->whatsThis().isEmpty() ) +//US QWhatsThis::add( bar->getButton(id_), whatsThisWithIcon() ); + if ( !d->toolTip().isEmpty() ) + QToolTip::add( bar->getButton(id_), d->toolTip() ); + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( bar, this ); + + return containerCount() - 1; + + } + + return -1; +} + +void KAction::unplug( QWidget *w ) +{ + int i = findContainer( w ); + if ( i == -1 ) + return; + int id = itemId( i ); + + if ( w->inherits( "QPopupMenu" ) ) + { + QPopupMenu *menu = static_cast<QPopupMenu *>( w ); + menu->removeItem( id ); + } + else if ( w->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( w ); + bar->removeItemDelayed( id ); + } + else if ( w->inherits( "QMenuBar" ) ) + { + QMenuBar *bar = static_cast<QMenuBar *>( w ); + bar->removeItem( id ); + } + + removeContainer( i ); + + if ( m_parentCollection ) + m_parentCollection->disconnectHighlight( w, this ); +} + +void KAction::plugAccel(KAccel *kacc, bool configurable) +{ + qDebug("KAction::plugAccel ...1 has top be fixed"); +/*US + kdWarning(129) << "KAction::plugAccel(): call to deprecated action." << endl; + kdDebug(129) << kdBacktrace() << endl; + //kdDebug(129) << "KAction::plugAccel( kacc = " << kacc << " ): name \"" << name() << "\"" << endl; + if ( d->m_kaccel ) + unplugAccel(); + + // If the parent collection's accel ptr isn't set yet + //if ( m_parentCollection && !m_parentCollection->accel() ) + // m_parentCollection->setAccel( kacc ); + + // We can only plug this action into the given KAccel object + // if it does not already contain an action with the same name. + if ( !kacc->actions().actionPtr(name()) ) + { + d->m_kaccel = kacc; + d->m_kaccel->insert(name(), d->plainText(), QString::null, + KShortcut(d->m_cut), + this, SLOT(slotActivated()), + configurable, isEnabled()); + connect(d->m_kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed())); + //connect(d->m_kaccel, SIGNAL(keycodeChanged()), this, SLOT(slotKeycodeChanged())); + } + else + kdWarning(129) << "KAction::plugAccel( kacc = " << kacc << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis +*/ +} + +void KAction::unplugAccel() +{ + qDebug("KAction::unplugAccel ...1 has top be fixed"); +/*US + //kdDebug(129) << "KAction::unplugAccel() " << this << " " << name() << endl; + if ( d->m_kaccel ) + { + d->m_kaccel->remove(name()); + d->m_kaccel = 0; + } +*/ +} + +void KAction::plugMainWindowAccel( QWidget *w ) +{ + qDebug("KAction::plugMainWindowAccel ...1 has top be fixed"); +/*US + // Note: topLevelWidget() stops too early, we can't use it. + QWidget * tl = w; + QWidget * n; + while ( !tl->isDialog() && ( n = tl->parentWidget() ) ) // lookup parent and store + tl = n; + + KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow + if (mw) + plugAccel( mw->accel() ); + else + kdDebug(129) << "KAction::plugMainWindowAccel: Toplevel widget isn't a KMainWindow, can't plug accel. " << tl << endl; +*/ +} + +void KAction::setEnabled(bool enable) +{ + //kdDebug(129) << "KAction::setEnabled( " << enable << " ): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl; + if ( enable == d->isEnabled() ) + return; + + // KDE 4: remove +//US if (d->m_kaccel) +//US d->m_kaccel->setEnabled(name(), enable); + // KDE 4: remove end + +//US for ( uint i = 0; i < d->m_kaccelList.count(); i++ ) +//US d->m_kaccelList[i]->setEnabled( name(), enable ); + + d->setEnabled( enable ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateEnabled( i ); + + emit enabled( d->isEnabled() ); +} + +void KAction::updateEnabled( int i ) +{ + QWidget *w = container( i ); + + if ( w->inherits("QPopupMenu") ) + static_cast<QPopupMenu*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + else if ( w->inherits("QMenuBar") ) + static_cast<QMenuBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + else if ( w->inherits( "KToolBar" ) ) + { + static_cast<KToolBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() ); + } +} + +void KAction::setShortcutConfigurable( bool b ) +{ + d->m_configurable = b; +} + +void KAction::setText( const QString& text ) +{ +/*US + // KDE 4: remove + if (d->m_kaccel) { + KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name()); + if (pAction) + pAction->setLabel( text ); + } + // KDE 4: remove end + + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) { + KAccelAction* pAction = d->m_kaccelList[i]->actions().actionPtr(name()); + if (pAction) + pAction->setLabel( text ); + } +*/ + d->setText( text ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateText( i ); + +} + +void KAction::updateText( int i ) +{ + QWidget *w = container( i ); + + if ( w->inherits( "QPopupMenu" ) ) { + int id = itemId( i ); + static_cast<QPopupMenu*>(w)->changeItem( id, d->text() ); + updateShortcut( static_cast<QPopupMenu*>(w), id ); + } + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->changeItem( itemId( i ), d->text() ); + else if ( w->inherits( "KToolBar" ) ) + { + qDebug("KAction::updateText ...3 has top be fixed"); + QWidget *button = static_cast<KToolBar *>(w)->getWidget( itemId( i ) ); + if ( button->inherits( "KToolBarButton" ) ) + static_cast<KToolBarButton *>(button)->setText( d->plainText() ); + + } +} + +QString KAction::text() const +{ + return d->text(); +} + +QString KAction::plainText() const +{ + return d->plainText( ); +} + +void KAction::setIcon( const QString &icon ) +{ + d->setIconName( icon ); + + // now handle any toolbars + int len = containerCount(); + for ( int i = 0; i < len; ++i ) + updateIcon( i ); +} + +void KAction::updateIcon( int id ) +{ + QWidget* w = container( id ); + + if ( w->inherits( "QPopupMenu" ) ) { + int itemId_ = itemId( id ); + static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet( KIcon::Small ), d->text() ); + updateShortcut( static_cast<QPopupMenu*>(w), itemId_ ); + } + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet( KIcon::Small ), d->text() ); + else if ( w->inherits( "KToolBar" ) ) + static_cast<KToolBar *>(w)->setButtonIcon( itemId( id ), d->iconName() ); + else if ( w->inherits( "QToolBar" ) ) + { + qDebug("KAction::updateIcon has top be fixed"); +//US static_cast<QToolBar *>(w)->setButtonIcon( itemId( id ), d->iconName() ); + } +} + +QString KAction::icon() const +{ + return d->iconName( ); +} + +void KAction::setIconSet( const QIconSet &iconset ) +{ + d->setIconSet( iconset ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateIconSet( i ); +} + + +void KAction::updateIconSet( int id ) +{ + QWidget *w = container( id ); + + if ( w->inherits( "QPopupMenu" ) ) + { + int itemId_ = itemId( id ); + static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet(), d->text() ); + updateShortcut( static_cast<QPopupMenu*>(w), itemId_ ); + } + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet(), d->text() ); + else if ( w->inherits( "KToolBar" ) ) + { + if ( icon().isEmpty() && d->hasIconSet() ) // only if there is no named icon ( scales better ) + static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet() ); + else + static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet( KIcon::Small ) ); + } +} + +QIconSet KAction::iconSet( KIcon::Group group, int size ) const +{ + return d->iconSet( group, size ); +} + +bool KAction::hasIcon() const +{ + return d->hasIcon(); +} + + +void KAction::setWhatsThis( const QString& text ) +{ + d->setWhatsThis( text ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateWhatsThis( i ); +} + +void KAction::updateWhatsThis( int i ) +{ + qDebug("KAction::updateWhatsThis ...1 has top be fixed"); + QPopupMenu* pm = popupMenu( i ); + if ( pm ) + { + pm->setWhatsThis( itemId( i ), d->whatsThis() ); + return; + } + + KToolBar *tb = toolBar( i ); + if ( tb ) + { + QWidget *w = tb->getButton( itemId( i ) ); +//US QWhatsThis::remove( w ); +//US QWhatsThis::add( w, d->whatsThis() ); + return; + } +} + +QString KAction::whatsThis() const +{ + return d->whatsThis(); +} + +QString KAction::whatsThisWithIcon() const +{ + QString text = whatsThis(); + if (!d->iconName().isEmpty()) + return QString::fromLatin1("<img source=\"small|%1\"> %2").arg(d->iconName() ).arg(text); + return text; +} + +QWidget* KAction::container( int index ) const +{ + assert( index < containerCount() ); + return d->m_containers[ index ].m_container; +} + +KToolBar* KAction::toolBar( int index ) const +{ +//US return dynamic_cast<KToolBar *>( d->m_containers[ index ].m_container ); + return (KToolBar *)( d->m_containers[ index ].m_container ); +} + +QPopupMenu* KAction::popupMenu( int index ) const +{ +//US return dynamic_cast<QPopupMenu *>( d->m_containers[ index ].m_container ); + return (QPopupMenu *)( d->m_containers[ index ].m_container ); +} + +QWidget* KAction::representative( int index ) const +{ + return d->m_containers[ index ].m_representative; +} + +int KAction::itemId( int index ) const +{ + return d->m_containers[ index ].m_id; +} + +int KAction::containerCount() const +{ + return d->m_containers.count(); +} + +uint KAction::kaccelCount() const +{ + return d->m_kaccelList.count(); +} + +void KAction::addContainer( QWidget* c, int id ) +{ + KActionPrivate::Container p; + p.m_container = c; + p.m_id = id; + d->m_containers.append( p ); +} + +void KAction::addContainer( QWidget* c, QWidget* w ) +{ + KActionPrivate::Container p; + p.m_container = c; + p.m_representative = w; + d->m_containers.append( p ); +} + +void KAction::activate() +{ + slotActivated(); +} + +void KAction::slotActivated() +{ + emit activated(); +} + +void KAction::slotDestroyed() +{ + kdDebug(129) << "KAction::slotDestroyed(): this = " << this << ", name = \"" << name() << "\", sender = " << sender() << endl; + const QObject* o = sender(); + +/* + + + // KDE 4: remove + if ( o == d->m_kaccel ) + { + d->m_kaccel = 0; + return; + } + // KDE 4: remove end + + for( uint i = 0; i < d->m_kaccelList.count(); i++ ) + { + if ( o == d->m_kaccelList[i] ) + { + disconnect( d->m_kaccelList[i], SIGNAL(destroyed()), this, SLOT(slotDestroyed()) ); + d->m_kaccelList.remove( d->m_kaccelList.at( i ) ); + return; + } + } +*/ + int i; + do + { + i = findContainer( static_cast<const QWidget*>( o ) ); + if ( i != -1 ) + removeContainer( i ); + } while ( i != -1 ); + +} + +int KAction::findContainer( const QWidget* widget ) const +{ + int pos = 0; + QValueList<KActionPrivate::Container>::ConstIterator it = d->m_containers.begin(); + while( it != d->m_containers.end() ) + { + if ( (*it).m_representative == widget || (*it).m_container == widget ) + return pos; + ++it; + ++pos; + } + + return -1; +} + +void KAction::removeContainer( int index ) +{ + int i = 0; + QValueList<KActionPrivate::Container>::Iterator it = d->m_containers.begin(); + while( it != d->m_containers.end() ) + { + if ( i == index ) + { + d->m_containers.remove( it ); + return; + } + ++it; + ++i; + } +} + +// FIXME: Remove this (ellis) +void KAction::slotKeycodeChanged() +{ + qDebug("KAction::slotKeycodeChanged() ...44 has top be fixed"); +/*US + kdDebug(129) << "KAction::slotKeycodeChanged()" << endl; // -- ellis + KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name()); + if( pAction ) + setShortcut(pAction->shortcut()); +*/ +} + +KActionCollection *KAction::parentCollection() const +{ + return m_parentCollection; +} + +void KAction::unplugAll() +{ + while ( containerCount() != 0 ) + unplug( container( 0 ) ); +} + +void KAction::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +/* vim: et sw=2 ts=2 + */ + +//US #include "kaction.moc" diff --git a/microkde/kdeui/kaction.h b/microkde/kdeui/kaction.h new file mode 100644 index 0000000..13e2e1e --- a/dev/null +++ b/microkde/kdeui/kaction.h @@ -0,0 +1,624 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//$Id$ + +#ifndef __kaction_h__ +#define __kaction_h__ + + +//US #include <qkeysequence.h> +#include <qobject.h> +#include <qvaluelist.h> +#include <qguardedptr.h> +#include <kguiitem.h> +#include <kshortcut.h> +#include <kstdaction.h> +//US#include <kicontheme.h> + +//US added the following files +#include <kiconloader.h> + +class QMenuBar; +class QPopupMenu; +//USclass QComboBox; +//USclass QPoint; +class QIconSet; +class QString; +class KToolBar; + +class KAccel; +//USclass KAccelActions; +//USclass KConfig; +//USclass KConfigBase; +//USclass KURL; +//USclass KInstance; +//USclass KToolBar; +class KActionCollection; +//USclass KPopupMenu; +class KMainWindow; + +/** + * The KAction class (and derived and super classes) provides a way to + * easily encapsulate a "real" user-selected action or event in your + * program. + * + * For instance, a user may want to @p paste the contents of + * the clipboard or @p scroll @p down a document or @p quit the + * application. These are all @p actions -- events that the + * user causes to happen. The KAction class allows the developer to + * deal with these actions in an easy and intuitive manner. + * + * Specifically, the KAction class encapsulated the various attributes + * to an event/action. For instance, an action might have an icon + * that goes along with it (a clipboard for a "paste" action or + * scissors for a "cut" action). The action might have some text to + * describe the action. It will certainly have a method or function + * that actually @p executes the action! All these attributes + * are contained within the KAction object. + * + * The advantage of dealing with Actions is that you can manipulate + * the Action without regard to the GUI representation of it. For + * instance, in the "normal" way of dealing with actions like "cut", + * you would manually insert a item for Cut into a menu and a button + * into a toolbar. If you want to disable the cut action for a moment + * (maybe nothing is selected), you woud have to hunt down the pointer + * to the menu item and the toolbar button and disable both + * individually. Setting the menu item and toolbar item up uses very + * similar code - but has to be done twice! + * + * With the Action concept, you simply "plug" the Action into whatever + * GUI element you want. The KAction class will then take care of + * correctly defining the menu item (with icons, accelerators, text, + * etc) or toolbar button.. or whatever. From then on, if you + * manipulate the Action at all, the effect will propogate through all + * GUI representations of it. Back to the "cut" example: if you want + * to disable the Cut Action, you would simply do + * 'cutAction->setEnabled(false)' and the menuitem and button would + * instantly be disabled! + * + * This is the biggest advantage to the Action concept -- there is a + * one-to-one relationship between the "real" action and @p all + * GUI representations of it. + * + * KAction emits the activated() signal if the user activated the + * corresponding GUI element ( menu item, toolbar button, etc. ) + * + * If you are in the situation of wanting to map the activated() + * signal of multiple action objects to one slot, with a special + * argument bound to each action, then you might consider using + * @ref QSignalMapper . A tiny example: + * + * <PRE> + * QSignalMapper *desktopNumberMapper = new QSignalMapper( this ); + * connect( desktopNumberMapper, SIGNAL( mapped( int ) ), + * this, SLOT( moveWindowToDesktop( int ) ) ); + * + * for ( uint i = 0; i < numberOfDesktops; ++i ) { + * KAction *desktopAction = new KAction( i18n( "Move Window to Desktop %i" ).arg( i ), ... ); + * connect( desktopAction, SIGNAL( activated() ), desktopNumberMapper, SLOT( map() ) ); + * desktopNumberMapper->setMapping( desktopAction, i ); + * } + * </PRE> + * + * @sect General Usage: + * + * The steps to using actions are roughly as follows + * + * @li Decide which attributes you want to associate with a given + * action (icons, text, keyboard shortcut, etc) + * @li Create the action using KAction (or derived or super class). + * @li "Plug" the Action into whatever GUI element you want. Typically, + * this will be a menu or toolbar. + * + * @sect Detailed Example: + * + * Here is an example of enabling a "New [document]" action + * <PRE> + * KAction *newAct = new KAction(i18n("&New"), "filenew", + * KStdAccel::shortcut(KStdAccel::New), + * this, SLOT(fileNew()), + * actionCollection(), "new"); + * </PRE> + * This line creates our action. It says that wherever this action is + * displayed, it will use "&New" as the text, the standard icon, and + * the standard shortcut. It further says that whenever this action + * is invoked, it will use the fileNew() slot to execute it. + * + * <PRE> + * QPopupMenu *file = new QPopupMenu; + * newAct->plug(file); + * </PRE> + * That just inserted the action into the File menu. The point is, it's not + * important in which menu it is: all manipulation of the item is + * done through the newAct object. + * + * <PRE> + * newAct->plug(toolBar()); + * </PRE> + * And this inserted the Action into the main toolbar as a button. + * + * That's it! + * + * If you want to disable that action sometime later, you can do so + * with + * <PRE> + * newAct->setEnabled(false) + * </PRE> + * and both the menuitem in File and the toolbar button will instantly + * be disabled. + * + * Do not delete a KAction object without unplugging it from all its + * containers. The simplest way to do that is to use the unplugAll() + * as in the following example: + * <PRE> + * newAct->unplugAll(); + * delete newAct; + * </PRE> + * Normally you will not need to do this as KActionCollection manages + * everything for you. + * + * Note: if you are using a "standard" action like "new", "paste", + * "quit", or any other action described in the KDE UI Standards, + * please use the methods in the @ref KStdAction class rather than + * defining your own. + * + * @sect Usage Within the XML Framework: + * + * If you are using KAction within the context of the XML menu and + * toolbar building framework, then there are a few tiny changes. The + * first is that you must insert your new action into an action + * collection. The action collection (a @ref KActionCollection) is, + * logically enough, a central collection of all of the actions + * defined in your application. The XML UI framework code in KXMLGUI + * classes needs access to this collection in order to build up the + * GUI (it's how the builder code knows which actions are valid and + * which aren't). + * + * Also, if you use the XML builder framework, then you do not ever + * have to plug your actions into containers manually. The framework + * does that for you. + * + * @see KStdAction + * @short Class to encapsulate user-driven action or event + */ +class KAction : public QObject +{ + friend class KActionCollection; + Q_OBJECT + Q_PROPERTY( int containerCount READ containerCount ) + Q_PROPERTY( QString plainText READ plainText ) + Q_PROPERTY( QString text READ text WRITE setText ) + Q_PROPERTY( QString shortcut READ shortcutText WRITE setShortcutText ) + Q_PROPERTY( bool enabled READ isEnabled WRITE setEnabled ) + Q_PROPERTY( QString group READ group WRITE setGroup ) + Q_PROPERTY( QString whatsThis READ whatsThis WRITE setWhatsThis ) + Q_PROPERTY( QString toolTip READ toolTip WRITE setToolTip ) + Q_PROPERTY( QString icon READ icon WRITE setIcon ) +public: + /** + * Constructs an action with text, potential keyboard + * shortcut, and a SLOT to call when this action is invoked by + * the user. + * + * If you do not want or have a keyboard shortcut, + * set the @p cut param to 0. + * + * This is the most common KAction used when you do not have a + * corresponding icon (note that it won't appear in the current version + * of the "Edit ToolBar" dialog, because an action needs an icon to be + * plugged in a toolbar...). + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard shortcut. + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + /** + * Constructs an action with text, icon, potential keyboard + * shortcut, and a SLOT to call when this action is invoked by + * the user. + * + * If you do not want or have a keyboard shortcut, set the + * @p cut param to 0. + * + * This is the other common KAction used. Use it when you + * @p do have a corresponding icon. + * + * @param text The text that will be displayed. + * @param pix The icon to display. + * @param cut The corresponding keyboard shortcut. + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + + KAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + + /** + * Constructs an action with text, icon, potential keyboard + * shortcut, and a SLOT to call when this action is invoked by + * the user. The icon is loaded on demand later based on where it + * is plugged in. + * + * If you do not want or have a keyboard shortcut, set the + * @p cut param to 0. + * + * This is the other common KAction used. Use it when you + * @p do have a corresponding icon. + * + * @param text The text that will be displayed. + * @param pix The icon to display. + * @param cut The corresponding keyboard shortcut (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + + /** + * The same as the above constructor, but with a KGuiItem providing + * the text and icon. + * + * @param item The KGuiItem with the label and (optional) icon. + */ + KAction( const KGuiItem& item, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + /** + * @obsolete + */ + KAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + /** + * @obsolete + */ + KAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + /** + * @obsolete + */ + KAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Standard destructor + */ + virtual ~KAction(); + + /** + * "Plug" or insert this action into a given widget. + * + * This will + * typically be a menu or a toolbar. From this point on, you will + * never need to directly manipulate the item in the menu or + * toolbar. You do all enabling/disabling/manipulation directly + * with your KAction object. + * + * @param w The GUI element to display this action + */ + virtual int plug( QWidget *w, int index = -1 ); + + /** + * @deprecated. Shouldn't be used. No substitute available. + * + * "Plug" or insert this action into a given KAccel. + * + * @param accel The KAccel collection which holds this accel + * @param configurable If the shortcut is configurable via + * the KAccel configuration dialog (this is somehow deprecated since + * there is now a KAction key configuration dialog). + */ + virtual void plugAccel(KAccel *accel, bool configurable = true); + + /** + * "Unplug" or remove this action from a given widget. + * + * This will typically be a menu or a toolbar. This is rarely + * used in "normal" application. Typically, it would be used if + * your application has several views or modes, each with a + * completely different menu structure. If you simply want to + * disable an action for a given period, use @ref setEnabled() + * instead. + * + * @param w Remove the action from this GUI element. + */ + virtual void unplug( QWidget *w ); + + /** + * @deprecated. Complement method to plugAccel(). + * Disconnect this action from the KAccel. + */ + virtual void unplugAccel(); + + /** + * returns whether the action is plugged into any container widget or not. + * @since 3.1 + */ + virtual bool isPlugged() const; + + /** + * returns whether the action is plugged into the given container + */ + bool isPlugged( const QWidget *container ) const; + + /** + * returns whether the action is plugged into the given container with the given, container specific, id (often + * menu or toolbar id ) . + */ + virtual bool isPlugged( const QWidget *container, int id ) const; + + /** + * returns whether the action is plugged into the given container with the given, container specific, representative + * container widget item. + */ + virtual bool isPlugged( const QWidget *container, const QWidget *_representative ) const; + + QWidget* container( int index ) const; + int itemId( int index ) const; + QWidget* representative( int index ) const; + int containerCount() const; + /// @since 3.1 + uint kaccelCount() const; + + virtual bool hasIcon() const; +#ifndef KDE_NO_COMPAT + bool hasIconSet() const { return hasIcon(); } +#endif + virtual QString plainText() const; + + /** + * Get the text associated with this action. + */ + virtual QString text() const; + + /** + * Get the keyboard shortcut associated with this action. + */ + virtual const KShortcut& shortcut() const; + /** + * Get the default shortcut for this action. + */ + virtual const KShortcut& shortcutDefault() const; + + // These two methods are for Q_PROPERTY + QString shortcutText() const; + void setShortcutText( const QString& ); + + /** + * Returns true if this action is enabled. + */ + virtual bool isEnabled() const; + + /** + * Returns true if this action's shortcut is configurable. + */ + virtual bool isShortcutConfigurable() const; + + virtual QString group() const; + + /** + * Get the What's this text for the action. + */ + virtual QString whatsThis() const; + + /** + * Get the tooltip text for the action. + */ + virtual QString toolTip() const; + + /** + * Get the QIconSet from which the icons used to display this action will + * be chosen. + */ + virtual QIconSet iconSet( KIcon::Group group, int size=0 ) const; + +#ifndef KDE_NO_COMPAT + QIconSet iconSet() const + { + return iconSet( KIcon::Small ); + } +#endif + + virtual QString icon() const; + + KActionCollection *parentCollection() const; + + /** + * @internal + * Generate a toolbar button id. Made public for reimplementations. + */ + static int getToolButtonID(); + + + void unplugAll(); + +public slots: + /** + * Sets the text associated with this action. The text is used for menu + * and toolbar labels etc. + */ + virtual void setText(const QString &text); + + /** + * Sets the keyboard shortcut associated with this action. + */ + virtual bool setShortcut( const KShortcut& ); + + virtual void setGroup( const QString& ); + + /** + * Sets the What's this text for the action. This text will be displayed when + * a widget that has been created by plugging this action into a container + * is clicked on in What's this mode. + * + * The What's this text can include QML markup as well as raw text. + */ + virtual void setWhatsThis( const QString& text ); + + /** + * Sets the tooltip text for the action. + * This will be used as a tooltip for a toolbar button, as a + * statusbar help-text for a menu item, and it also appears + * in the toolbar editor, to describe the action. + */ + virtual void setToolTip( const QString& ); + + /** + * Sets the QIconSet from which the icons used to display this action will + * be chosen. + */ + virtual void setIconSet( const QIconSet &iconSet ); + + virtual void setIcon( const QString& icon ); + + /** + * Enables or disables this action. All uses of this action (eg. in menus + * or toolbars) will be updated to reflect the state of the action. + */ + virtual void setEnabled(bool enable); + + /** + * Indicate whether the user may configure the action's shortcut. + */ + virtual void setShortcutConfigurable( bool ); + + /** + * Emulate user's interaction programmatically, by activating the action. + * The implementation simply emits activated(). + */ + virtual void activate(); + +protected slots: + virtual void slotDestroyed(); + virtual void slotKeycodeChanged(); + virtual void slotActivated(); + +protected: + KToolBar* toolBar( int index ) const; + QPopupMenu* popupMenu( int index ) const; + void removeContainer( int index ); + int findContainer( const QWidget* widget ) const; + void plugMainWindowAccel( QWidget *w ); + + void addContainer( QWidget* parent, int id ); + void addContainer( QWidget* parent, QWidget* representative ); + + virtual void updateShortcut( int i ); + virtual void updateShortcut( QPopupMenu* menu, int id ); + virtual void updateGroup( int id ); + virtual void updateText(int i ); + virtual void updateEnabled(int i); + virtual void updateIconSet(int i); + virtual void updateIcon( int i); + virtual void updateToolTip( int id ); + virtual void updateWhatsThis( int i ); + + KActionCollection *m_parentCollection; + QString whatsThisWithIcon() const; + +signals: + void activated(); + void enabled( bool ); + +private: + void initPrivate( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot ); + KAccel* kaccelCurrent(); + bool initShortcut( const KShortcut& ); + void plugShortcut(); + bool updateKAccelShortcut( KAccel* kaccel ); + void insertKAccel( KAccel* ); + /** @internal To be used exclusively by KActionCollection::removeWidget(). */ + void removeKAccel( KAccel* ); + +#ifndef KDE_NO_COMPAT +public: + /** + * @deprecated. Use shortcut(). + * Get the keyboard accelerator associated with this action. + */ + int accel() const; + + QString statusText() const + { return toolTip(); } + + /** + * @deprecated. Use setShortcut(). + * Sets the keyboard accelerator associated with this action. + */ + void setAccel( int key ); + + /** + * @deprecated. Use setToolTip instead (they do the same thing now). + */ + void setStatusText( const QString &text ) + { setToolTip( text ); } + + /** + * @deprecated. for backwards compatibility. + */ + int menuId( int i ) { return itemId( i ); } +#endif // !KDE_NO_COMPAT + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionPrivate; + KActionPrivate *d; +}; + +#include <kactioncollection.h> +#include <kactionclasses.h> + +#endif diff --git a/microkde/kdeui/kactionclasses.cpp b/microkde/kdeui/kactionclasses.cpp new file mode 100644 index 0000000..82e6c8b --- a/dev/null +++ b/microkde/kdeui/kactionclasses.cpp @@ -0,0 +1,2058 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + (C) 2002 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kactionclasses.h" + +#include <assert.h> + +#include <qfontdatabase.h> +#include <qobjectlist.h> +//US#include <qwhatsthis.h> +#include <qtimer.h> + +//US#include <kaccel.h> +//US#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +//US#include <kfontcombo.h> +//US#include <kmainwindow.h> +//US#include <kmenubar.h> +//US#include <kpopupmenu.h> +#include <kcombobox.h> +#include <ktoolbar.h> +#include <ktoolbarbutton.h> +#include <kurl.h> + +//US added the following includefiles +#include <kconfigbase.h> +#include <qwidget.h> +#include <qpopupmenu.h> +#include <qmenubar.h> +#include <qmainwindow.h> +#include <qtoolbar.h> +#include <qcombobox.h> +#include <qmainwindow.h> + + +static QFontDatabase *fontDataBase = 0; + +static void cleanupFontDatabase() +{ + delete fontDataBase; + fontDataBase = 0; +} + +static void get_fonts( QStringList &lst ) +{ + if ( !fontDataBase ) { + fontDataBase = new QFontDatabase(); + qAddPostRoutine( cleanupFontDatabase ); + } + lst.clear(); + QStringList families = fontDataBase->families(); + for ( QStringList::Iterator it = families.begin(); it != families.end(); ++it ) + { + QString family = *it; + if ( family. contains('-') ) // remove foundry + family = family.right( family.length() - family.find('-' ) - 1); + if ( !lst.contains( family ) ) + lst.append( family ); + } + lst.sort(); +} + +static QValueList<int> get_standard_font_sizes() +{ + if ( !fontDataBase ) { + fontDataBase = new QFontDatabase(); + qAddPostRoutine( cleanupFontDatabase ); + } + return fontDataBase->standardSizes(); +} + +class KToggleAction::KToggleActionPrivate +{ +public: + KToggleActionPrivate() + { + m_checked = false; + } + + bool m_checked; + QString m_exclusiveGroup; +}; + +KToggleAction::KToggleAction( const QString& text, const KShortcut& cut, + QObject* parent, + const char* name ) + : KAction( text, cut, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KAction( text, cut, receiver, slot, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::KToggleAction( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + d = new KToggleActionPrivate; +} + +KToggleAction::~KToggleAction() +{ + delete d; +} + +int KToggleAction::plug( QWidget* widget, int index ) +{ + if ( !widget->inherits("QPopupMenu") && !widget->inherits("KToolBar") ) + { + kdWarning() << "Can not plug KToggleAction in " << widget->className() << endl; + return -1; + } + +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + + int _index = KAction::plug( widget, index ); + if ( _index == -1 ) + return _index; + + if ( widget->inherits("QPopupMenu") ) + { + int id = itemId( _index ); + + static_cast<QPopupMenu*>(widget)->setItemChecked( id, d->m_checked ); + } else if ( widget->inherits( "KToolBar" ) ) { + + KToolBar *bar = static_cast<KToolBar *>( widget ); + + bar->setToggle( itemId( _index ), true ); + bar->setButton( itemId( _index ), isChecked() ); + } + + return _index; +} + +void KToggleAction::setChecked( bool c ) +{ + if ( c == d->m_checked ) + return; + //kdDebug(129) << "KToggleAction::setChecked(" << c << ") " << this << " " << name() << endl; + + d->m_checked = c; + + int len = containerCount(); + + for( int i = 0; i < len; ++i ) + updateChecked( i ); + + if ( c && parent() && !exclusiveGroup().isEmpty() ) { + const QObjectList *list = parent()->children(); + if ( list ) { + QObjectListIt it( *list ); + for( ; it.current(); ++it ) { + if ( it.current()->inherits( "KToggleAction" ) && it.current() != this && + static_cast<KToggleAction*>(it.current())->exclusiveGroup() == exclusiveGroup() ) { + KToggleAction *a = static_cast<KToggleAction*>(it.current()); + if( a->isChecked() ) { + a->setChecked( false ); + emit a->toggled( false ); + } + } + } + } + } +} + +void KToggleAction::updateChecked( int id ) +{ + QWidget *w = container( id ); + + if ( w->inherits( "QPopupMenu" ) ) + static_cast<QPopupMenu*>(w)->setItemChecked( itemId( id ), d->m_checked ); + else if ( w->inherits( "QMenuBar" ) ) + static_cast<QMenuBar*>(w)->setItemChecked( itemId( id ), d->m_checked ); + else if ( w->inherits( "KToolBar" ) ) + { + QWidget* r = static_cast<KToolBar*>( w )->getButton( itemId( id ) ); + if ( r && r->inherits( "KToolBarButton" ) ) + static_cast<KToolBar*>( w )->setButton( itemId( id ), d->m_checked ); + } +} + +void KToggleAction::slotActivated() +{ + setChecked( !isChecked() ); + emit activated(); + emit toggled( isChecked() ); +} + +bool KToggleAction::isChecked() const +{ + return d->m_checked; +} + +void KToggleAction::setExclusiveGroup( const QString& name ) +{ + d->m_exclusiveGroup = name; +} + +QString KToggleAction::exclusiveGroup() const +{ + return d->m_exclusiveGroup; +} + + +KRadioAction::KRadioAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) +: KToggleAction( text, cut, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) +: KToggleAction( text, cut, receiver, slot, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, receiver, slot, parent, name ) +{ +} + +KRadioAction::KRadioAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) +: KToggleAction( text, pix, cut, receiver, slot, parent, name ) +{ +} + +KRadioAction::KRadioAction( QObject* parent, const char* name ) +: KToggleAction( parent, name ) +{ +} + +void KRadioAction::slotActivated() +{ + if ( isChecked() ) + { + const QObject *senderObj = sender(); + + if ( !senderObj || !senderObj->inherits( "KToolBarButton" ) ) + return; + + qDebug("KRadioAction::slotActivated has to be fixed"); + const_cast<KToolBarButton *>( static_cast<const KToolBarButton *>( senderObj ) )->on( true ); + + return; + } + + KToggleAction::slotActivated(); +} + +class KSelectAction::KSelectActionPrivate +{ +public: + KSelectActionPrivate() + { + m_edit = false; + m_menuAccelsEnabled = true; + m_menu = 0; + m_current = -1; + m_comboWidth = -1; + } + bool m_edit; + bool m_menuAccelsEnabled; + QPopupMenu *m_menu; + int m_current; + int m_comboWidth; + QStringList m_list; + + QString makeMenuText( const QString &_text ) + { + if ( m_menuAccelsEnabled ) + return _text; + QString text = _text; + uint i = 0; + while ( i < text.length() ) { + if ( text.at( i ) == '&' ) { + text.insert( i, '&' ); + i += 2; + } + else + ++i; + } + return text; + } +}; + +KSelectAction::KSelectAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, cut, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KAction( text, cut, receiver, slot, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, pix, cut, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::KSelectAction( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + d = new KSelectActionPrivate; +} + +KSelectAction::~KSelectAction() +{ + assert(d); + delete d->m_menu; + delete d; d = 0; +} + +void KSelectAction::setCurrentItem( int id ) +{ + if ( id >= (int)d->m_list.count() ) { + ASSERT(id < (int)d->m_list.count()); + return; + } + + if ( d->m_menu ) + { + if ( d->m_current >= 0 ) + d->m_menu->setItemChecked( d->m_current, false ); + if ( id >= 0 ) + { + //US qDebug("KSelectAction::setCurrentItem %i", id); + d->m_menu->setItemChecked( id, true ); + } + } + + d->m_current = id; + + int len = containerCount(); + + for( int i = 0; i < len; ++i ) + updateCurrentItem( i ); + + // emit KAction::activated(); + // emit activated( currentItem() ); + // emit activated( currentText() ); +} + +void KSelectAction::setComboWidth( int width ) +{ + if ( width < 0 ) + return; + + d->m_comboWidth=width; + + int len = containerCount(); + + for( int i = 0; i < len; ++i ) + updateComboWidth( i ); + +} +QPopupMenu* KSelectAction::popupMenu() const +{ + kdDebug(129) << "KSelectAction::popupMenu()" << endl; // remove -- ellis + if ( !d->m_menu ) + { +//US d->m_menu = new KPopupMenu(0L, "KSelectAction::popupMenu()"); + d->m_menu = new QPopupMenu(0L, "QSelectAction::popupMenu()"); + setupMenu(); + if ( d->m_current >= 0 ) + d->m_menu->setItemChecked( d->m_current, true ); + } + + return d->m_menu; +} + +void KSelectAction::setupMenu() const +{ + if ( !d->m_menu ) + return; + d->m_menu->clear(); + + QStringList::ConstIterator it = d->m_list.begin(); + for( uint id = 0; it != d->m_list.end(); ++it, ++id ) { + QString text = *it; + if ( !text.isEmpty() ) + d->m_menu->insertItem( d->makeMenuText( text ), this, SLOT( slotActivated( int ) ), 0, id ); + else + d->m_menu->insertSeparator(); + } +} + +void KSelectAction::changeItem( int index, const QString& text ) +{ + if ( index < 0 || index >= (int)d->m_list.count() ) + { + kdWarning() << "KSelectAction::changeItem Index out of scope" << endl; + return; + } + + d->m_list[ index ] = text; + + if ( d->m_menu ) + d->m_menu->changeItem( index, d->makeMenuText( text ) ); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + changeItem( i, index, text ); +} + +void KSelectAction::changeItem( int id, int index, const QString& text) +{ + if ( index < 0 ) + return; + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) + { + QWidget* r = (static_cast<KToolBar*>( w ))->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) + { + QComboBox *b = static_cast<QComboBox*>( r ); + b->changeItem(text, index ); + } + } + +} + +void KSelectAction::setItems( const QStringList &lst ) +{ + kdDebug(129) << "KAction::setItems()" << endl; // remove -- ellis + d->m_list = lst; + d->m_current = -1; + + setupMenu(); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateItems( i ); + + // Disable if empty and not editable + setEnabled ( lst.count() > 0 || d->m_edit ); +} + +QStringList KSelectAction::items() const +{ + return d->m_list; +} + +QString KSelectAction::currentText() const +{ + if ( currentItem() < 0 ) + return QString::null; + + return d->m_list[ currentItem() ]; +} + +int KSelectAction::currentItem() const +{ + return d->m_current; +} + +void KSelectAction::updateCurrentItem( int id ) +{ + if ( d->m_current < 0 ) + return; + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *b = static_cast<QComboBox*>( r ); + b->setCurrentItem( d->m_current ); + } + } +} + +int KSelectAction::comboWidth() const +{ + return d->m_comboWidth; +} + +void KSelectAction::updateComboWidth( int id ) +{ + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *cb = static_cast<QComboBox*>( r ); + cb->setMinimumWidth( d->m_comboWidth ); + cb->setMaximumWidth( d->m_comboWidth ); + } + } +} + +void KSelectAction::updateItems( int id ) +{ + kdDebug(129) << "KAction::updateItems( " << id << ", lst )" << endl; // remove -- ellis + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *cb = static_cast<QComboBox*>( r ); + cb->clear(); + QStringList lst = comboItems(); + QStringList::ConstIterator it = lst.begin(); + for( ; it != lst.end(); ++it ) + cb->insertItem( *it ); + // Ok, this currently doesn't work due to a bug in QComboBox + // (the sizehint is cached for ever and never recalculated) + // Bug reported (against Qt 2.3.1). + cb->setMinimumWidth( cb->sizeHint().width() ); + } + } + +} + +int KSelectAction::plug( QWidget *widget, int index ) +{ +//US if (kapp && !kapp->authorizeKAction(name())) +//US return -1; + + kdDebug(129) << "KAction::plug( " << widget << ", " << index << " )" << endl; // remove -- ellis + if ( widget->inherits("QPopupMenu") ) + { + // Create the PopupMenu and store it in m_menu + (void)popupMenu(); + + QPopupMenu* menu = static_cast<QPopupMenu*>( widget ); + int id; + + if ( hasIconSet() ) + id = menu->insertItem( iconSet(), text(), d->m_menu, -1, index ); + else + id = menu->insertItem( text(), d->m_menu, -1, index ); + + if ( !isEnabled() ) + menu->setItemEnabled( id, false ); + + QString wth = whatsThis(); + if ( !wth.isEmpty() ) + menu->setWhatsThis( id, wth ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + else if ( widget->inherits("KToolBar") ) + { + + KToolBar* bar = static_cast<KToolBar*>( widget ); + int id_ = KAction::getToolButtonID(); + bar->insertCombo( comboItems(), id_, isEditable(), + SIGNAL( activated( const QString & ) ), this, + SLOT( slotActivated( const QString & ) ), isEnabled(), + toolTip(), -1, index ); + + KComboBox *cb = bar->getCombo( id_ ); + if ( cb ) + { + cb->setMaximumHeight( 34 ); + if (!isEditable()) cb->setFocusPolicy(QWidget::NoFocus); + cb->setMinimumWidth( cb->sizeHint().width() ); + if ( d->m_comboWidth > 0 ) + { + cb->setMinimumWidth( d->m_comboWidth ); + cb->setMaximumWidth( d->m_comboWidth ); + } + cb->setInsertionPolicy( QComboBox::NoInsertion ); +//US QWhatsThis::add( cb, whatsThis() ); + } + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + updateCurrentItem( containerCount() - 1 ); + + return containerCount() - 1; + + } + kdWarning() << "Can not plug KAction in " << widget->className() << endl; + return -1; +} + +QStringList KSelectAction::comboItems() const +{ + //qDebug("KSelectAction::comboItems has to be fixed"); + if( d->m_menuAccelsEnabled ) + { + QStringList lst; + QStringList::ConstIterator it = d->m_list.begin(); + for( ; it != d->m_list.end(); ++it ) + { + QString item = *it; + int i = item.find( '&' ); + if ( i > -1 ) + item = item.remove( i, 1 ); + lst.append( item ); + } + return lst; + } + else + { + return d->m_list; + } +} + +void KSelectAction::clear() +{ + if ( d->m_menu ) + d->m_menu->clear(); + + int len = containerCount(); + for( int i = 0; i < len; ++i ) + updateClear( i ); +} + +void KSelectAction::updateClear( int id ) +{ + + QWidget* w = container( id ); + if ( w->inherits( "KToolBar" ) ) { + QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) ); + if ( r->inherits( "QComboBox" ) ) { + QComboBox *b = static_cast<QComboBox*>( r ); + b->clear(); + } + } +} + +void KSelectAction::slotActivated( int id ) +{ + if ( d->m_current == id ) + return; + + setCurrentItem( id ); + // Delay this. Especially useful when the slot connected to activated() will re-create + // the menu, e.g. in the recent files action. This prevents a crash. + + QTimer::singleShot( 0, this, SLOT( slotActivated() ) ); +} + +void KSelectAction::slotActivated( const QString &text ) +{ + if ( isEditable() ) + { + QStringList lst = items(); + if(lst.contains(text)==0) + { + lst.append( text ); + setItems( lst ); + } + } + + int i = items().findIndex( text ); + if ( i > -1 ) + setCurrentItem( i ); + else + setCurrentItem( comboItems().findIndex( text ) ); + // Delay this. Especially useful when the slot connected to activated() will re-create + // the menu, e.g. in the recent files action. This prevents a crash. + + QTimer::singleShot( 0, this, SLOT( slotActivated() ) ); +} + +void KSelectAction::slotActivated() +{ + KAction::slotActivated(); + kdDebug(129) << "KSelectAction::slotActivated currentItem=" << currentItem() << " currentText=" << currentText() << endl; + emit activated( currentItem() ); + emit activated( currentText() ); +} + +void KSelectAction::setEditable( bool edit ) +{ + d->m_edit = edit; +} + +bool KSelectAction::isEditable() const +{ + return d->m_edit; +} + +void KSelectAction::setRemoveAmpersandsInCombo( bool b ) +{ + setMenuAccelsEnabled( b ); +} + +bool KSelectAction::removeAmpersandsInCombo() const +{ + return menuAccelsEnabled( ); +} + +void KSelectAction::setMenuAccelsEnabled( bool b ) +{ + d->m_menuAccelsEnabled = b; +} + +bool KSelectAction::menuAccelsEnabled() const +{ + return d->m_menuAccelsEnabled; +} + +class KListAction::KListActionPrivate +{ +public: + KListActionPrivate() + { + m_current = 0; + } + int m_current; +}; + +KListAction::KListAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::KListAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + d = new KListActionPrivate; + if ( receiver ) + connect( this, SIGNAL( activated( int ) ), receiver, slot ); +} + +KListAction::KListAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::KListAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::KListAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; + if ( receiver ) + connect( this, SIGNAL( activated( int ) ), receiver, slot ); +} + +KListAction::KListAction( const QString& text, const QString& pix, + const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KListActionPrivate; + if ( receiver ) + connect( this, SIGNAL( activated( int ) ), receiver, slot ); +} + +KListAction::KListAction( QObject* parent, const char* name ) + : KSelectAction( parent, name ) +{ + d = new KListActionPrivate; +} + +KListAction::~KListAction() +{ + delete d; d = 0; +} + +void KListAction::setCurrentItem( int index ) +{ + KSelectAction::setCurrentItem( index ); + d->m_current = index; + + // emit KAction::activated(); + // emit activated( currentItem() ); + // emit activated( currentText() ); +} + +QString KListAction::currentText() const +{ + if ( currentItem() < 0 ) + return QString::null; + + return items()[ currentItem() ]; +} + +int KListAction::currentItem() const +{ + return d->m_current; +} + +class KRecentFilesAction::KRecentFilesActionPrivate +{ +public: + KRecentFilesActionPrivate() + { + m_maxItems = 0; + } + uint m_maxItems; +}; + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const KShortcut& cut, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const KShortcut& cut, + const QObject* receiver, + const char* slot, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); + + if ( receiver ) + connect( this, SIGNAL(urlSelected(const KURL&)), + receiver, slot ); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); + + if ( receiver ) + connect( this, SIGNAL(urlSelected(const KURL&)), + receiver, slot ); +} + +KRecentFilesAction::KRecentFilesAction( const QString& text, + const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, + QObject* parent, const char* name, + uint maxItems ) + : KListAction( text, pix, cut, parent, name) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); + + if ( receiver ) + connect( this, SIGNAL(urlSelected(const KURL&)), + receiver, slot ); +} + +KRecentFilesAction::KRecentFilesAction( QObject* parent, const char* name, + uint maxItems ) + : KListAction( parent, name ) +{ + d = new KRecentFilesActionPrivate; + d->m_maxItems = maxItems; + + init(); +} + +void KRecentFilesAction::init() +{ + connect( this, SIGNAL( activated( const QString& ) ), + this, SLOT( itemSelected( const QString& ) ) ); + + setMenuAccelsEnabled( false ); +} + +KRecentFilesAction::~KRecentFilesAction() +{ + delete d; d = 0; +} + +uint KRecentFilesAction::maxItems() const +{ + return d->m_maxItems; +} + +void KRecentFilesAction::setMaxItems( uint maxItems ) +{ + QStringList lst = items(); + uint oldCount = lst.count(); + + // set new maxItems + d->m_maxItems = maxItems; + + // remove all items that are too much + while( lst.count() > maxItems ) + { + // remove last item + lst.remove( lst.last() ); + } + + // set new list if changed + if( lst.count() != oldCount ) + setItems( lst ); +} + +void KRecentFilesAction::addURL( const KURL& url ) +{ + QString file = url.prettyURL(); + QStringList lst = items(); + + // remove file if already in list + lst.remove( file ); + + // remove las item if already maxitems in list + if( lst.count() == d->m_maxItems ) + { + // remove last item + lst.remove( lst.last() ); + } + + // add file to list + lst.prepend( file ); + setItems( lst ); +} + +void KRecentFilesAction::removeURL( const KURL& url ) +{ + QStringList lst = items(); + QString file = url.prettyURL(); + + // remove url + if( lst.count() > 0 ) + { + lst.remove( file ); + setItems( lst ); + } +} + +void KRecentFilesAction::clearURLList() +{ + clear(); +} + +void KRecentFilesAction::loadEntries( KConfig* config, QString groupname) +{ + QString key; + QString value; + QString oldGroup; + QStringList lst; + + oldGroup = config->group(); + + if (groupname.isEmpty()) + groupname = "RecentFiles"; + config->setGroup( groupname ); + + // read file list + for( unsigned int i = 1 ; i <= d->m_maxItems ; i++ ) + { + key = QString( "File%1" ).arg( i ); + value = config->readEntry( key, QString::null ); + + if (!value.isNull()) + lst.append( value ); + } + + // set file + setItems( lst ); + + config->setGroup( oldGroup ); +} + +void KRecentFilesAction::saveEntries( KConfig* config, QString groupname ) +{ + QString key; + QString value; + QStringList lst = items(); + + if (groupname.isEmpty()) + groupname = "RecentFiles"; + + config->deleteGroup( groupname); + + KConfigGroupSaver( config, groupname ); + + // write file list + for( unsigned int i = 1 ; i <= lst.count() ; i++ ) + { + key = QString( "File%1" ).arg( i ); + value = lst[ i - 1 ]; + config->writeEntry( key, value ); + } +} + +void KRecentFilesAction::itemSelected( const QString& text ) +{ + emit urlSelected( KURL( text ) ); +} + +class KFontAction::KFontActionPrivate +{ +public: + KFontActionPrivate() + { + } + QStringList m_fonts; +}; + +KFontAction::KFontAction( const QString& text, + const KShortcut& cut, QObject* parent, + const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, cut, receiver, slot, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::KFontAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + + +KFontAction::KFontAction( QObject* parent, const char* name ) + : KSelectAction( parent, name ) +{ + d = new KFontActionPrivate; + get_fonts( d->m_fonts ); + KSelectAction::setItems( d->m_fonts ); + setEditable( true ); +} + +KFontAction::~KFontAction() +{ + delete d; + d = 0; +} + +/* + * Maintenance note: Keep in sync with KFontCombo::setCurrentFont() + */ +void KFontAction::setFont( const QString &family ) +{ + QString lowerName = family.lower(); + int i = 0; + for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i ) + { + if ((*it).lower() == lowerName) + { + setCurrentItem(i); + return; + } + } + i = lowerName.find(" ["); + if (i>-1) + { + lowerName = lowerName.left(i); + i = 0; + for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i ) + { + if ((*it).lower() == lowerName) + { + setCurrentItem(i); + return; + } + } + } + + lowerName += " ["; + i = 0; + for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i ) + { + if ((*it).lower().startsWith(lowerName)) + { + setCurrentItem(i); + return; + } + } + kdDebug(129) << "Font not found " << family.lower() << endl; +} + +int KFontAction::plug( QWidget *w, int index ) +{ + qDebug("KFontAction::plug ha to be fixed"); +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; + if ( w->inherits("KToolBar") ) + { + KToolBar* bar = static_cast<KToolBar*>( w ); + int id_ = KAction::getToolButtonID(); + KFontCombo *cb = new KFontCombo( items(), bar ); + connect( cb, SIGNAL( activated( const QString & ) ), + SLOT( slotActivated( const QString & ) ) ); + cb->setEnabled( isEnabled() ); + bar->insertWidget( id_, comboWidth(), cb, index ); + cb->setMinimumWidth( cb->sizeHint().width() ); + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + updateCurrentItem( containerCount() - 1 ); + + return containerCount() - 1; + } + else return KSelectAction::plug( w, index ); +*/ + return 3; +} + +class KFontSizeAction::KFontSizeActionPrivate +{ +public: + KFontSizeActionPrivate() + { + } +}; + +KFontSizeAction::KFontSizeAction( const QString& text, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, cut, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, + const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name ) + : KSelectAction( text, cut, receiver, slot, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QString& pix, + const KShortcut& cut, + QObject* parent, const char* name ) + : KSelectAction( text, pix, cut, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QIconSet& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( const QString& text, const QString& pix, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KSelectAction( text, pix, cut, receiver, slot, parent, name ) +{ + init(); +} + +KFontSizeAction::KFontSizeAction( QObject* parent, const char* name ) + : KSelectAction( parent, name ) +{ + init(); +} + +KFontSizeAction::~KFontSizeAction() +{ + delete d; + d = 0; +} + +void KFontSizeAction::init() +{ + d = new KFontSizeActionPrivate; + + setEditable( true ); + QValueList<int> sizes = get_standard_font_sizes(); + QStringList lst; + for ( QValueList<int>::Iterator it = sizes.begin(); it != sizes.end(); ++it ) + lst.append( QString::number( *it ) ); + + setItems( lst ); +} + +void KFontSizeAction::setFontSize( int size ) +{ + if ( size == fontSize() ) { + setCurrentItem( items().findIndex( QString::number( size ) ) ); + return; + } + + if ( size < 1 ) { + kdWarning() << "KFontSizeAction: Size " << size << " is out of range" << endl; + return; + } + + int index = items().findIndex( QString::number( size ) ); + if ( index == -1 ) { + // Insert at the correct position in the list (to keep sorting) + QValueList<int> lst; + // Convert to list of ints + QStringList itemsList = items(); + for (QStringList::Iterator it = itemsList.begin() ; it != itemsList.end() ; ++it) + lst.append( (*it).toInt() ); + // New size + lst.append( size ); + // Sort the list +qDebug("KFontSizeAction::setFontSize heapsort not found."); +//US has to be fixed +//US qHeapSort( lst ); + // Convert back to string list + QStringList strLst; + for (QValueList<int>::Iterator it = lst.begin() ; it != lst.end() ; ++it) + strLst.append( QString::number(*it) ); + KSelectAction::setItems( strLst ); + // Find new current item + index = lst.findIndex( size ); + setCurrentItem( index ); + } + else + setCurrentItem( index ); + + + //emit KAction::activated(); + //emit activated( index ); + //emit activated( QString::number( size ) ); + //emit fontSizeChanged( size ); +} + +int KFontSizeAction::fontSize() const +{ + return currentText().toInt(); +} + +void KFontSizeAction::slotActivated( int index ) +{ + KSelectAction::slotActivated( index ); + + emit fontSizeChanged( items()[ index ].toInt() ); +} + +void KFontSizeAction::slotActivated( const QString& size ) +{ + setFontSize( size.toInt() ); // insert sorted first + KSelectAction::slotActivated( size ); + emit fontSizeChanged( size.toInt() ); +} + +class KActionMenu::KActionMenuPrivate +{ +public: + KActionMenuPrivate() + { +//US m_popup = new KPopupMenu(0L,"KActionMenu::KActionMenuPrivate"); + m_popup = new QPopupMenu(0L,"KActionMenu::KActionMenuPrivate"); + m_delayed = true; + m_stickyMenu = true; + } + ~KActionMenuPrivate() + { + delete m_popup; m_popup = 0; + } + +//US KPopupMenu *m_popup; + QPopupMenu *m_popup; + bool m_delayed; + bool m_stickyMenu; +}; + +KActionMenu::KActionMenu( QObject* parent, const char* name ) + : KAction( parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::KActionMenu( const QString& text, QObject* parent, + const char* name ) + : KAction( text, 0, parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::KActionMenu( const QString& text, const QIconSet& icon, + QObject* parent, const char* name ) + : KAction( text, icon, 0, parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::KActionMenu( const QString& text, const QString& icon, + QObject* parent, const char* name ) + : KAction( text, icon, 0, parent, name ) +{ + d = new KActionMenuPrivate; + setShortcutConfigurable( false ); +} + +KActionMenu::~KActionMenu() +{ + unplugAll(); + kdDebug(129) << "KActionMenu::~KActionMenu()" << endl; // ellis + delete d; d = 0; +} + +void KActionMenu::popup( const QPoint& global ) +{ + popupMenu()->popup( global ); +} + + +//US KPopupMenu* KActionMenu::popupMenu() const +QPopupMenu* KActionMenu::popupMenu() const +{ + return d->m_popup; +} + +void KActionMenu::insert( KAction* cmd, int index ) +{ + if ( cmd ) + cmd->plug( d->m_popup, index ); +} + +void KActionMenu::remove( KAction* cmd ) +{ + if ( cmd ) + cmd->unplug( d->m_popup ); +} + +bool KActionMenu::delayed() const { + return d->m_delayed; +} + +void KActionMenu::setDelayed(bool _delayed) { + d->m_delayed = _delayed; +} + +bool KActionMenu::stickyMenu() const { + return d->m_stickyMenu; +} + +void KActionMenu::setStickyMenu(bool sticky) { + d->m_stickyMenu = sticky; +} + +int KActionMenu::plug( QWidget* widget, int index ) +{ +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + kdDebug(129) << "KAction::plug( " << widget << ", " << index << " )" << endl; // remove -- ellis + if ( widget->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( widget ); + int id; + if ( hasIconSet() ) + id = menu->insertItem( iconSet(), text(), d->m_popup, -1, index ); + else + id = menu->insertItem( text(), d->m_popup, -1, index ); + + if ( !isEnabled() ) + menu->setItemEnabled( id, false ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( menu, this ); + + return containerCount() - 1; + } + else if ( widget->inherits( "KToolBar" ) ) + { + KToolBar *bar = static_cast<KToolBar *>( widget ); + + int id_ = KAction::getToolButtonID(); + + if ( icon().isEmpty() && !iconSet().isNull() ) + bar->insertButton( iconSet().pixmap(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index ); + else + { + /*US + KInstance *instance; + + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + bar->insertButton( icon(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index/*US, instance */); + } + + addContainer( bar, id_ ); +/*US + if (!whatsThis().isEmpty()) + QWhatsThis::add( bar->getButton(id_), whatsThis() ); +*/ + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if (delayed()) { + bar->setDelayedPopup( id_, popupMenu(), stickyMenu() ); + } else { + bar->getButton(id_)->setPopup(popupMenu(), stickyMenu() ); + } + + if ( m_parentCollection ) + m_parentCollection->connectHighlight( bar, this ); + + return containerCount() - 1; + } + else if ( widget->inherits( "QMenuBar" ) ) + { + QMenuBar *bar = static_cast<QMenuBar *>( widget ); + + int id; + + id = bar->insertItem( text(), popupMenu(), -1, index ); + + if ( !isEnabled() ) + bar->setItemEnabled( id, false ); + + addContainer( bar, id ); + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + + return -1; +} + +//////// + +KToolBarPopupAction::KToolBarPopupAction( const QString& text, + const QString& icon, + const KShortcut& cut, + QObject* parent, const char* name ) + : KAction( text, icon, cut, parent, name ) +{ + m_popup = 0; + m_delayed = true; + m_stickyMenu = true; +} + +KToolBarPopupAction::KToolBarPopupAction( const QString& text, + const QString& icon, + const KShortcut& cut, + const QObject* receiver, + const char* slot, QObject* parent, + const char* name ) + : KAction( text, icon, cut, receiver, slot, parent, name ) +{ + m_popup = 0; + m_delayed = true; + m_stickyMenu = true; +} + +KToolBarPopupAction::KToolBarPopupAction( const KGuiItem& item, + const KShortcut& cut, + const QObject* receiver, + const char* slot, KActionCollection* parent, + const char* name ) + : KAction( item, cut, receiver, slot, parent, name ) +{ + m_popup = 0; + m_delayed = true; + m_stickyMenu = true; +} + + +KToolBarPopupAction::~KToolBarPopupAction() +{ + if ( m_popup ) + delete m_popup; +} + +bool KToolBarPopupAction::delayed() const { + return m_delayed; +} + +void KToolBarPopupAction::setDelayed(bool delayed) { + m_delayed = delayed; +} + +bool KToolBarPopupAction::stickyMenu() const { + return m_stickyMenu; +} + +void KToolBarPopupAction::setStickyMenu(bool sticky) { + m_stickyMenu = sticky; +} + +int KToolBarPopupAction::plug( QWidget *widget, int index ) +{ +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + // This is very related to KActionMenu::plug. + // In fact this class could be an interesting base class for KActionMenu + if ( widget->inherits( "KToolBar" ) ) + { + KToolBar *bar = (KToolBar *)widget; + + int id_ = KAction::getToolButtonID(); +/*US + KInstance * instance; + if ( m_parentCollection ) + instance = m_parentCollection->instance(); + else + instance = KGlobal::instance(); +*/ + bar->insertButton( icon(), id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), isEnabled(), plainText(), + index/*US, instance*/ ); + + addContainer( bar, id_ ); + + connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + if (delayed()) { + bar->setDelayedPopup( id_, popupMenu(), stickyMenu() ); + } else { + bar->getButton(id_)->setPopup(popupMenu(), stickyMenu()); + } +/*US + if ( !whatsThis().isEmpty() ) + QWhatsThis::add( bar->getButton( id_ ), whatsThisWithIcon() ); +*/ + return containerCount() - 1; + } + + + return KAction::plug( widget, index ); +} + +//US KPopupMenu *KToolBarPopupAction::popupMenu() const +QPopupMenu *KToolBarPopupAction::popupMenu() const +{ + if ( !m_popup ) { + KToolBarPopupAction *that = const_cast<KToolBarPopupAction*>(this); +//US that->m_popup = new KPopupMenu; + that->m_popup = new QPopupMenu; + } + return m_popup; +} + +//////// + +KToggleToolBarAction::KToggleToolBarAction( const char* toolBarName, + const QString& text, KActionCollection* parent, const char* name ) + : KToggleAction( text, KShortcut(), parent, name ) + , m_toolBarName( toolBarName ) + , m_toolBar( 0L ) +{ +} + +KToggleToolBarAction::KToggleToolBarAction( KToolBar *toolBar, const QString &text, + KActionCollection *parent, const char *name ) + : KToggleAction( text, KShortcut(), parent, name ) + , m_toolBarName( 0 ) + , m_toolBar( toolBar ) +{ +} + +KToggleToolBarAction::~KToggleToolBarAction() +{ +} + +int KToggleToolBarAction::plug( QWidget* w, int index ) +{ + qDebug("KToggleToolBarAction::plug has to be fixed"); +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; + + if ( !m_toolBar ) { + // Note: topLevelWidget() stops too early, we can't use it. + QWidget * tl = w; + QWidget * n; + while ( !tl->isDialog() && ( n = tl->parentWidget() ) ) // lookup parent and store + tl = n; + +//US KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow + QMainWindow * mw = 0; + if ( tl->inherits("QMainWindow") ) + mw = (QMainWindow *)(tl); // try to see if it's a kmainwindow + + if ( mw ) + m_toolBar = mw->toolBar( m_toolBarName ); + } + + if( m_toolBar ) { + setChecked( m_toolBar->isVisible() ); + connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SLOT(setChecked(bool)) ); + // Also emit toggled when the toolbar's visibility changes (see comment in header) + connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SIGNAL(toggled(bool)) ); + } else { + setEnabled( false ); + } +*/ + return KToggleAction::plug( w, index ); +} + +void KToggleToolBarAction::setChecked( bool c ) +{ + if( m_toolBar && c != m_toolBar->isVisible() ) { + if( c ) { + m_toolBar->show(); + } else { + m_toolBar->hide(); + } + qDebug("KToggleToolBarAction::setChecked has to be fixed"); +/*US + QMainWindow* mw = m_toolBar->mainWindow(); + if ( mw && mw->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>( mw )->setSettingsDirty(); +*/ + } + KToggleAction::setChecked( c ); + +} + +//////// + +KWidgetAction::KWidgetAction( QWidget* widget, + const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ) + : KAction( text, cut, receiver, slot, parent, name ) + , m_widget( widget ) + , m_autoSized( false ) +{ +} + +KWidgetAction::~KWidgetAction() +{ +} + +void KWidgetAction::setAutoSized( bool autoSized ) +{ + if( m_autoSized == autoSized ) + return; + + m_autoSized = autoSized; + + if( !m_widget || !isPlugged() ) + return; + + KToolBar* toolBar = (KToolBar*)m_widget->parent(); + int i = findContainer( toolBar ); + if ( i == -1 ) + return; + int id = itemId( i ); + + toolBar->setItemAutoSized( id, m_autoSized ); + +} + +int KWidgetAction::plug( QWidget* w, int index ) +{ +/*US + if (kapp && !kapp->authorizeKAction(name())) + return -1; +*/ + if ( !w->inherits( "KToolBar" ) ) { + kdError() << "KWidgetAction::plug: KWidgetAction must be plugged into KToolBar." << endl; + return -1; + } + if ( !m_widget ) { + kdError() << "KWidgetAction::plug: Widget was deleted or null!" << endl; + return -1; + } + + KToolBar* toolBar = static_cast<KToolBar*>( w ); + + int id = KAction::getToolButtonID(); + + m_widget->reparent( toolBar, QPoint() ); + toolBar->insertWidget( id, 0, m_widget, index ); + toolBar->setItemAutoSized( id, m_autoSized ); + +//US QWhatsThis::add( m_widget, whatsThis() ); + addContainer( toolBar, id ); + + connect( toolBar, SIGNAL( toolbarDestroyed() ), this, SLOT( slotToolbarDestroyed() ) ); + connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; +} + +void KWidgetAction::unplug( QWidget *w ) +{ + if( !m_widget || !isPlugged() ) + return; + + KToolBar* toolBar = (KToolBar*)m_widget->parent(); + if ( toolBar == w ) + { + disconnect( toolBar, SIGNAL( toolbarDestroyed() ), this, SLOT( slotToolbarDestroyed() ) ); + m_widget->reparent( 0L, QPoint(), false ); // false = showit + } + KAction::unplug( w ); +} + +void KWidgetAction::slotToolbarDestroyed() +{ + //Q_ASSERT( m_widget ); // When exiting the app the widget could be destroyed before the toolbar. + + ASSERT( isPlugged() ); + if( !m_widget || !isPlugged() ) + return; + + // Don't let a toolbar being destroyed, delete my widget. + m_widget->reparent( 0L, QPoint(), false /*showIt*/ ); +} + +//////// + +KActionSeparator::KActionSeparator( QObject *parent, const char *name ) + : KAction( parent, name ) +{ +} + +KActionSeparator::~KActionSeparator() +{ +} + +int KActionSeparator::plug( QWidget *widget, int index ) +{ + if ( widget->inherits("QPopupMenu") ) + { + QPopupMenu* menu = static_cast<QPopupMenu*>( widget ); + + int id = menu->insertSeparator( index ); + + addContainer( menu, id ); + connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + else if ( widget->inherits( "QMenuBar" ) ) + { + QMenuBar *menuBar = static_cast<QMenuBar *>( widget ); + + int id = menuBar->insertSeparator( index ); + + addContainer( menuBar, id ); + + connect( menuBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + else if ( widget->inherits( "KToolBar" ) ) + { + KToolBar *toolBar = static_cast<KToolBar *>( widget ); + + int id = toolBar->insertSeparator( index ); +// toolBar->addSeparator(); + + addContainer( toolBar, id ); + + connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + return containerCount() - 1; + } + + return -1; +} + +void KToggleAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KRadioAction::virtual_hook( int id, void* data ) +{ KToggleAction::virtual_hook( id, data ); } + +void KSelectAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KListAction::virtual_hook( int id, void* data ) +{ KSelectAction::virtual_hook( id, data ); } + +void KRecentFilesAction::virtual_hook( int id, void* data ) +{ KListAction::virtual_hook( id, data ); } + +void KFontAction::virtual_hook( int id, void* data ) +{ KSelectAction::virtual_hook( id, data ); } + +void KFontSizeAction::virtual_hook( int id, void* data ) +{ KSelectAction::virtual_hook( id, data ); } + +void KActionMenu::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KToolBarPopupAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KToggleToolBarAction::virtual_hook( int id, void* data ) +{ KToggleAction::virtual_hook( id, data ); } + +void KWidgetAction::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +void KActionSeparator::virtual_hook( int id, void* data ) +{ KAction::virtual_hook( id, data ); } + +/* vim: et sw=2 ts=2 + */ + +/*US +#include "kactionclasses.moc" +*/ diff --git a/microkde/kdeui/kactionclasses.h b/microkde/kdeui/kactionclasses.h new file mode 100644 index 0000000..f6e7a0f --- a/dev/null +++ b/microkde/kdeui/kactionclasses.h @@ -0,0 +1,1223 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//$Id$ + +#ifndef __kactionclasses_h__ +#define __kactionclasses_h__ + +#include <kaction.h> + +//US#include <qkeysequence.h> +//US#include <qobject.h> +//US#include <qvaluelist.h> +//US#include <qguardedptr.h> +//US#include <kguiitem.h> +#include <kshortcut.h> +//US#include <kstdaction.h> +//US#include <kicontheme.h> + +class QMenuBar; +class QPopupMenu; +//USclass QComboBox; +//USclass QPoint; +//USclass QIconSet; +//USclass QString; +//USclass KToolBar; + +//USclass KAccel; +//USclass KAccelActions; +class KConfig; +//USclass KConfigBase; +class KURL; +//USclass KInstance; + + +//US class KToolBar needs to be replaced +class KToolBar; +class KActionCollection; + +//US class KPopupMenu needs to be replaced +//US class KPopupMenu; +//USclass KMainWindow; + +/** + * Checkbox like action. + * + * This action provides two states: checked or not. + * + * @short Checkbox like action. + */ +class KToggleAction : public KAction +{ + Q_OBJECT + Q_PROPERTY( bool checked READ isChecked WRITE setChecked ) + Q_PROPERTY( QString exclusiveGroup READ exclusiveGroup WRITE setExclusiveGroup ) +public: + + /** + * Constructs a toggle action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToggleAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~KToggleAction(); + + /** + * "Plug" or insert this action into a given widget. + * + * This will typically be a menu or a toolbar. From this point + * on, you will never need to directly manipulate the item in the + * menu or toolbar. You do all enabling/disabling/manipulation + * directly with your KToggleAction object. + * + * @param widget The GUI element to display this action. + * @param index The index of the item. + */ + virtual int plug( QWidget* widget, int index = -1 ); + + /** + * Returns the actual state of the action. + */ + bool isChecked() const; + + /** + * @return which "exclusive group" this action is part of. + * @see setExclusiveGroup + */ + QString exclusiveGroup() const; + + /** + * Defines which "exclusive group" this action is part of. + * In a given exclusive group, only one toggle action can be checked + * at a any moment. Checking an action unchecks the other actions + * of the group. + */ + virtual void setExclusiveGroup( const QString& name ); + +public slots: + /** + * Sets the state of the action. + */ + virtual void setChecked( bool ); + +protected slots: + virtual void slotActivated(); + +protected: + virtual void updateChecked( int id ); + +signals: + void toggled( bool ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KToggleActionPrivate; + KToggleActionPrivate *d; +}; + +/** + * An action that operates like a radio button. At any given time + * only a single action from the group will be active. + */ +class KRadioAction : public KToggleAction +{ + Q_OBJECT +public: + /** + * Constructs a radio action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KRadioAction( QObject* parent = 0, const char* name = 0 ); + +protected: + virtual void slotActivated(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KRadioActionPrivate; + KRadioActionPrivate *d; +}; + +/** + * Action for selecting one of several items. + * + * This action shows up a submenu with a list of items. + * One of them can be checked. If the user clicks on an item + * this item will automatically be checked, + * the formerly checked item becomes unchecked. + * There can be only one item checked at a time. + * + * @short Action for selecting one of several items + */ +class KSelectAction : public KAction +{ + Q_OBJECT + Q_PROPERTY( int currentItem READ currentItem WRITE setCurrentItem ) + Q_PROPERTY( QStringList items READ items WRITE setItems ) + Q_PROPERTY( bool editable READ isEditable WRITE setEditable ) + Q_PROPERTY( int comboWidth READ comboWidth WRITE setComboWidth ) + Q_PROPERTY( QString currentText READ currentText ) + Q_PROPERTY( bool menuAccelsEnabled READ menuAccelsEnabled WRITE setMenuAccelsEnabled ) +public: + + /** + * Constructs a select action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KSelectAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~KSelectAction(); + + /** + * "Plug" or insert this action into a given widget. + * + * This will typically be a menu or a toolbar. + * From this point on, you will never need to directly + * manipulate the item in the menu or toolbar. + * You do all enabling/disabling/manipulation directly with your KSelectAction object. + * + * @param widget The GUI element to display this action. + * @param index The index of the item. + */ + virtual int plug( QWidget* widget, int index = -1 ); + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * @return true if the combo editable. + */ + virtual bool isEditable() const; + + /** + * @return the items that can be selected with this action. + * Use setItems to set them. + */ + virtual QStringList items() const; + + virtual void changeItem( int index, const QString& text ); + + virtual QString currentText() const; + + virtual int currentItem() const; + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * This returns the maximum width set by setComboWidth + */ + virtual int comboWidth() const; + + QPopupMenu* popupMenu() const; + + /** + * Deprecated. See @ref setMenuAccelsEnabled . + * @since 3.1 + */ + void setRemoveAmpersandsInCombo( bool b ); + /// @since 3.1 + bool removeAmpersandsInCombo() const; + + /** + * Sets whether any occurence of the ampersand character ( & ) in items + * should be interpreted as keyboard accelerator for items displayed in a + * menu or not. + * @since 3.1 + */ + void setMenuAccelsEnabled( bool b ); + /// @since 3.1 + bool menuAccelsEnabled() const; + +public slots: + /** + * Sets the currently checked item. + * + * @param index Index of the item (remember the first item is zero). + */ + virtual void setCurrentItem( int index ); + + /** + * Sets the items to be displayed in this action + * You need to call this. + */ + virtual void setItems( const QStringList &lst ); + + /** + * Clears up all the items in this action + */ + virtual void clear(); + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * This makes the combo editable or read-only. + */ + virtual void setEditable( bool ); + + /** + * When this action is plugged into a toolbar, it creates a combobox. + * This gives a _maximum_ size to the combobox. + * The minimum size is automatically given by the contents (the items). + */ + virtual void setComboWidth( int width ); + +protected: + virtual void changeItem( int id, int index, const QString& text ); + + /** + * Depending on the menuAccelsEnabled property this method will return the + * actions items in a way for inclusion in a combobox with the ampersand + * character removed from all items or not. + * @since 3.1 + */ + QStringList comboItems() const; + +protected slots: + virtual void slotActivated( int id ); + virtual void slotActivated( const QString &text ); + virtual void slotActivated(); + +signals: + void activated( int index ); + void activated( const QString& text ); + +protected: + virtual void updateCurrentItem( int id ); + + virtual void updateComboWidth( int id ); + + virtual void updateItems( int id ); + + virtual void updateClear( int id ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + void setupMenu() const; + class KSelectActionPrivate; + KSelectActionPrivate *d; + +}; + +/// Remove this class in KDE-4.0. It doesn't add _anything_ to KSelectAction +/** + * @deprecated Use KSelectAction instead. + */ +class KListAction : public KSelectAction +{ + Q_OBJECT +public: + /** + * Constructs a list action with text and potential keyboard + * accelerator but nothing else. Use this only if you really + * know what you are doing. + * + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, + const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KListAction( QObject* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~KListAction(); + + + virtual QString currentText() const; + virtual int currentItem() const; + + +public slots: + /** + * Sets the currently checked item. + * + * @param index Index of the item (remember the first item is zero). + */ + virtual void setCurrentItem( int index ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KListActionPrivate; + KListActionPrivate *d; +}; + +/** + * This class is an action to handle a recent files submenu. + * The best way to create the action is to use KStdAction::openRecent. + * Then you simply need to call @ref loadEntries on startup, @ref saveEntries + * on shutdown, @ref addURL when your application loads/saves a file. + * + * @author Michael Koch + * @short Recent files action + */ +class KRecentFilesAction : public KListAction // TODO public KSelectAction +{ + Q_OBJECT + Q_PROPERTY( uint maxItems READ maxItems WRITE setMaxItems ) +public: + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const KShortcut& cut, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QString& pix, const KShortcut& cut, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The icons that go with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param text The text that will be displayed. + * @param pix The dynamically loaded icon that goes with this action. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's parent. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0, + uint maxItems = 10 ); + + /** + * @param parent This action's parent. + * @param name An internal name for this action. + * @param maxItems The maximum number of files to display + */ + KRecentFilesAction( QObject* parent = 0, const char* name = 0, + uint maxItems = 10 ); + + /** + * Destructor. + */ + virtual ~KRecentFilesAction(); + + /** + * Returns the maximum of items in the recent files list. + */ + uint maxItems() const; + +public slots: + /** + * Sets the maximum of items in the recent files list. + * The default for this value is 10 set in the constructor. + * + * If this value is lesser than the number of items currently + * in the recent files list the last items are deleted until + * the number of items are equal to the new maximum. + */ + void setMaxItems( uint maxItems ); + + /** + * Loads the recent files entries from a given KConfig object. + * You can provide the name of the group used to load the entries. + * If the groupname is empty, entries are load from a group called 'RecentFiles' + * + * This method does not effect the active group of KConfig. + */ + void loadEntries( KConfig* config, QString groupname=QString::null ); + + /** + * Saves the current recent files entries to a given KConfig object. + * You can provide the name of the group used to load the entries. + * If the groupname is empty, entries are saved to a group called 'RecentFiles' + * + * This method does not effect the active group of KConfig. + */ + void saveEntries( KConfig* config, QString groupname=QString::null ); + +public slots: + /** + * Add URL to recent files list. + * + * @param url The URL of the file + */ + void addURL( const KURL& url ); + + /** + * Remove an URL from the recent files list. + * + * @param url The URL of the file + */ + void removeURL( const KURL& url ); + + /** + * Removes all entries from the recent files list. + */ + void clearURLList(); + +signals: + + /** + * This signal gets emited when the user selects an URL. + * + * @param url The URL thats the user selected. + */ + void urlSelected( const KURL& url ); + +protected slots: + /** + * + */ + void itemSelected( const QString& string ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + void init(); + + class KRecentFilesActionPrivate; + KRecentFilesActionPrivate *d; +}; + +class KFontAction : public KSelectAction +{ + Q_OBJECT + Q_PROPERTY( QString font READ font WRITE setFont ) +public: + KFontAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, + const char* name = 0 ); + KFontAction( const QString& text, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + KFontAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + KFontAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, QObject* parent, + const char* name = 0 ); + + KFontAction( QObject* parent = 0, const char* name = 0 ); + ~KFontAction(); + + QString font() const { + return currentText(); + } + + int plug( QWidget*, int index = -1 ); + +public slots: + void setFont( const QString &family ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KFontActionPrivate; + KFontActionPrivate *d; +}; + +class KFontSizeAction : public KSelectAction +{ + Q_OBJECT + Q_PROPERTY( int fontSize READ fontSize WRITE setFontSize ) +public: + KFontSizeAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, + const char* name = 0 ); + KFontSizeAction( const QString& text, const KShortcut& cut, const QObject* receiver, + const char* slot, QObject* parent, const char* name = 0 ); + KFontSizeAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontSizeAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + KFontSizeAction( const QString& text, const QIconSet& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + KFontSizeAction( const QString& text, const QString& pix, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent, const char* name = 0 ); + KFontSizeAction( QObject* parent = 0, const char* name = 0 ); + + virtual ~KFontSizeAction(); + + virtual int fontSize() const; + +public slots: + virtual void setFontSize( int size ); + +protected slots: + virtual void slotActivated( int ); + virtual void slotActivated( const QString& ); + virtual void slotActivated() { KAction::slotActivated(); } + +signals: + void fontSizeChanged( int ); + +private: + void init(); + + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KFontSizeActionPrivate; + KFontSizeActionPrivate *d; +}; + + +/** + * A KActionMenu is an action that holds a sub-menu of other actions. + * insert() and remove() allow to insert and remove actions into this action-menu. + * Plugged in a popupmenu, it will create a submenu. + * Plugged in a toolbar, it will create a button with a popup menu. + * + * This is the action used by the XMLGUI since it holds other actions. + * If you want a submenu for selecting one tool among many (without icons), see KSelectAction. + * See also setDelayed about the main action. + */ +class KActionMenu : public KAction +{ + Q_OBJECT + Q_PROPERTY( bool delayed READ delayed WRITE setDelayed ) + Q_PROPERTY( bool stickyMenu READ stickyMenu WRITE setStickyMenu ) + +public: + KActionMenu( const QString& text, QObject* parent = 0, + const char* name = 0 ); + KActionMenu( const QString& text, const QIconSet& icon, + QObject* parent = 0, const char* name = 0 ); + KActionMenu( const QString& text, const QString& icon, + QObject* parent = 0, const char* name = 0 ); + KActionMenu( QObject* parent = 0, const char* name = 0 ); + virtual ~KActionMenu(); + + virtual void insert( KAction*, int index = -1 ); + virtual void remove( KAction* ); + +//US KPopupMenu* popupMenu() const; + QPopupMenu* popupMenu() const; + void popup( const QPoint& global ); + + /** + * Returns true if this action creates a delayed popup menu + * when plugged in a KToolbar. + */ + bool delayed() const; + /** + * If set to true, this action will create a delayed popup menu + * when plugged in a KToolbar. Otherwise it creates a normal popup. + * Default: delayed + * + * Remember that if the "main" action (the toolbar button itself) + * cannot be clicked, then you should call setDelayed(false). + * + * On the opposite, if the main action can be clicked, it can only happen + * in a toolbar: in a menu, the parent of a submenu can't be activated. + * To get a "normal" menu item when plugged a menu (and no submenu) + * use KToolBarPopupAction. + */ + void setDelayed(bool _delayed); + + /** + * Returns true if this action creates a sticky popup menu. + * See @ref setStickyMenu. + */ + bool stickyMenu() const; + /** + * If set to true, this action will create a sticky popup menu + * when plugged in a KToolbar. + * "Sticky", means it's visible until a selection is made or the mouse is + * clicked elsewhere. This feature allows you to make a selection without + * having to press and hold down the mouse while making a selection. + * Default: sticky. + */ + void setStickyMenu(bool sticky); + + virtual int plug( QWidget* widget, int index = -1 ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionMenuPrivate; + KActionMenuPrivate *d; +}; + +/** + * This action is a normal action everywhere, except in a toolbar + * where it also has a popupmenu (optionnally delayed). This action is designed + * for history actions (back/forward, undo/redo) and for any other action + * that has more detail in a toolbar than in a menu (e.g. tool chooser + * with "Other" leading to a dialog...). + */ +class KToolBarPopupAction : public KAction +{ + Q_OBJECT + Q_PROPERTY( bool delayed READ delayed WRITE setDelayed ) + Q_PROPERTY( bool stickyMenu READ stickyMenu WRITE setStickyMenu ) + +public: + //Not all constructors - because we need an icon, since this action only makes + // sense when being plugged at least in a toolbar. + /** + * Create a KToolBarPopupAction, with a text, an icon, an optionnal accelerator, + * parent and name. + * + * @param text The text that will be displayed. + * @param icon The icon to display. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToolBarPopupAction( const QString& text, const QString& icon, const KShortcut& cut = KShortcut(), + QObject* parent = 0, const char* name = 0 ); + + /** + * Create a KToolBarPopupAction, with a text, an icon, an accelerator, + * a slot connected to the action, parent and name. + * + * If you do not want or have a keyboard accelerator, set the + * @p cut param to 0. + * + * @param text The text that will be displayed. + * @param icon The icon to display. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's owner. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + KToolBarPopupAction( const QString& text, const QString& icon, const KShortcut& cut, + const QObject* receiver, const char* slot, + QObject* parent = 0, const char* name = 0 ); + + /** + * Create a KToolBarPopupAction, with a KGuiItem, an accelerator, + * a slot connected to the action, parent and name. The text and the + * icon are taken from the KGuiItem. + * + * If you do not want or have a keyboard accelerator, set the + * @p cut param to 0. + * + * @param item The text and icon that will be displayed. + * @param cut The corresponding keyboard accelerator (shortcut). + * @param receiver The SLOT's owner. + * @param slot The SLOT to invoke to execute this action. + * @param parent This action's parent. + * @param name An internal name for this action. + */ + + KToolBarPopupAction( const KGuiItem& item, const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + + virtual ~KToolBarPopupAction(); + + virtual int plug( QWidget *widget, int index = -1 ); + + /** + * The popup menu that is shown when clicking (some time) on the toolbar + * button. You may want to plug items into it on creation, or connect to + * aboutToShow for a more dynamic menu. + */ +//US KPopupMenu *popupMenu() const; + QPopupMenu *popupMenu() const; + + /** + * Returns true if this action creates a delayed popup menu + * when plugged in a KToolbar. + */ + bool delayed() const; + /** + * If set to true, this action will create a delayed popup menu + * when plugged in a KToolbar. Otherwise it creates a normal popup. + * Default: delayed. + */ + void setDelayed(bool delayed); + /** + * Returns true if this action creates a sticky popup menu. + * See @ref setStickyMenu. + */ + bool stickyMenu() const; + /** + * If set to true, this action will create a sticky popup menu + * when plugged in a KToolbar. + * "Sticky", means it's visible until a selection is made or the mouse is + * clicked elsewhere. This feature allows you to make a selection without + * having to press and hold down the mouse while making a selection. + * Only available if delayed() is true. + * Default: sticky. + */ + void setStickyMenu(bool sticky); + +private: +//US KPopupMenu *m_popup; + QPopupMenu *m_popup; + bool m_delayed:1; + bool m_stickyMenu:1; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KToolBarPopupActionPrivate; + KToolBarPopupActionPrivate *d; +}; + +/** + * An action that takes care of everything associated with + * showing or hiding a toolbar by a menu action. It will + * show or hide the toolbar with the given name when + * activated, and check or uncheck itself if the toolbar + * is manually shown or hidden. + * + * If you need to perfom some additional action when the + * toolbar is shown or hidden, connect to the toggled(bool) + * signal. It will be emitted after the toolbar's + * visibility has changed, whenever it changes. + * @since 3.1 + */ +class KToggleToolBarAction : public KToggleAction +{ + Q_OBJECT +public: + /** + * Create a KToggleToolbarAction that manages the toolbar + * named toolBarName. This can be either the name of a + * toolbar in an xml ui file, or a toolbar programmatically + * created with that name. + */ + KToggleToolBarAction( const char* toolBarName, const QString& text, + KActionCollection* parent, const char* name ); + KToggleToolBarAction( KToolBar *toolBar, const QString &text, + KActionCollection *parent, const char *name ); + virtual ~KToggleToolBarAction(); + + virtual int plug( QWidget*, int index = -1 ); + + KToolBar *toolBar() { + return m_toolBar; + } + +public slots: + virtual void setChecked( bool ); + +private: + QCString m_toolBarName; + QGuardedPtr<KToolBar> m_toolBar; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KToggleToolBarActionPrivate; + KToggleToolBarActionPrivate *d; +}; + +/** + * An action that automatically embeds a widget into a + * toolbar. + */ +class KWidgetAction : public KAction +{ + Q_OBJECT +public: + /** + * Create an action that will embed widget into a toolbar + * when plugged. This action may only be plugged into + * a toolbar. + */ + KWidgetAction( QWidget* widget, const QString& text, + const KShortcut& cut, + const QObject* receiver, const char* slot, + KActionCollection* parent, const char* name ); + virtual ~KWidgetAction(); + + /** + * Returns the widget associated with this action. + */ + QWidget* widget() { return m_widget; } + + void setAutoSized( bool ); + + /** + * Plug the action. The widget passed to the constructor + * will be reparented to w, which must inherit KToolBar. + */ + virtual int plug( QWidget* w, int index = -1 ); + /** + * Unplug the action. Ensures that the action is not + * destroyed. It will be hidden and reparented to 0L instead. + */ + virtual void unplug( QWidget *w ); +protected slots: + void slotToolbarDestroyed(); +private: + QGuardedPtr<QWidget> m_widget; + bool m_autoSized; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KWidgetActionPrivate; + KWidgetActionPrivate *d; +}; + +class KActionSeparator : public KAction +{ + Q_OBJECT +public: + KActionSeparator( QObject* parent = 0, const char* name = 0 ); + virtual ~KActionSeparator(); + + virtual int plug( QWidget*, int index = -1 ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionSeparatorPrivate; + KActionSeparatorPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/kactioncollection.cpp b/microkde/kdeui/kactioncollection.cpp new file mode 100644 index 0000000..b819e76 --- a/dev/null +++ b/microkde/kdeui/kactioncollection.cpp @@ -0,0 +1,839 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + (C) 2002 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kactioncollection.h" +//US#include "kactionshortcutlist.h" + +#include <qptrdict.h> +//US#include <qvariant.h> + +//US#include <kaccel.h> +//US#include <kaccelbase.h> +//US#include <kapplication.h> +#include <kdebug.h> +//US#include <kxmlguifactory.h> + +//US I included the following files +#include <qasciidict.h> +#include <qptrlist.h> +#include "kaction.h" +#include <kglobal.h> +#include <qobject.h> +#include <qwidget.h> + +class KActionCollection::KActionCollectionPrivate +{ +public: + KActionCollectionPrivate() + { +//US m_instance = 0; + //m_bOneKAccelOnly = false; + //m_iWidgetCurrent = 0; + m_bAutoConnectShortcuts = true; + m_widget = 0; + m_kaccel = m_builderKAccel = 0; + m_dctHighlightContainers.setAutoDelete( true ); + m_highlight = false; + m_currentHighlightAction = 0; + m_statusCleared = true; + } + +//US KInstance *m_instance; +//US QString m_sXMLFile; + bool m_bAutoConnectShortcuts; + //bool m_bOneKAccelOnly; + //int m_iWidgetCurrent; + //QValueList<QWidget*> m_widgetList; + //QValueList<KAccel*> m_kaccelList; + QValueList<KActionCollection*> m_docList; + QWidget *m_widget; + KAccel *m_kaccel; + KAccel *m_builderKAccel; + + QAsciiDict<KAction> m_actionDict; + QPtrDict< QPtrList<KAction> > m_dctHighlightContainers; + bool m_highlight; + KAction *m_currentHighlightAction; + bool m_statusCleared; +}; + +KActionCollection::KActionCollection( QWidget *parent, const char *name /*US, + KInstance *instance */) + : QObject( (QObject*)parent, name ) +{ + kdDebug(129) << "KActionCollection::KActionCollection( " << parent << ", " << name << " ): this = " << this << endl; // ellis + d = new KActionCollectionPrivate; + if( parent ) + setWidget( parent ); + //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0); +//US setInstance( instance ); +} + + +KActionCollection::KActionCollection( QWidget *watch, QObject* parent, const char *name /*US, + KInstance *instance */) + : QObject( parent, name ) +{ + kdDebug(129) << "KActionCollection::KActionCollection( " << watch << ", " << parent << ", " << name << " ): this = " << this << endl; //ellis + d = new KActionCollectionPrivate; + if( watch ) + setWidget( watch ); + //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0); +//US setInstance( instance ); +} + +// KDE 4: remove +KActionCollection::KActionCollection( QObject *parent, const char *name /*US, + KInstance *instance */) + : QObject( parent, name ) +{ + kdWarning(129) << "KActionCollection::KActionCollection( QObject *parent, const char *name, KInstance *instance )" << endl; //ellis +//US kdBacktrace not available +//US kdDebug(129) << kdBacktrace() << endl; + d = new KActionCollectionPrivate; +//US QWidget* w = dynamic_cast<QWidget*>( parent ); + QWidget* w = (QWidget*)( parent ); + if( w ) + setWidget( w ); + //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0); +//US setInstance( instance ); +} + +KActionCollection::KActionCollection( const KActionCollection © ) + : QObject() +{ + kdWarning(129) << "KActionCollection::KActionCollection( const KActionCollection & ): function is severely deprecated." << endl; + d = new KActionCollectionPrivate; + *this = copy; +} +// KDE 4: remove end + +KActionCollection::~KActionCollection() +{ + kdDebug(129) << "KActionCollection::~KActionCollection(): this = " << this << endl; + for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) { + KAction* pAction = it.current(); + if ( pAction->m_parentCollection == this ) + pAction->m_parentCollection = 0L; + } + +//US delete d->m_kaccel; +//US delete d->m_builderKAccel; + delete d; d = 0; +} + +void KActionCollection::setWidget( QWidget* w ) +{ + //if ( d->m_actionDict.count() > 0 ) { + // kdError(129) << "KActionCollection::setWidget(): must be called before any actions are added to collection!" << endl; + // kdDebug(129) << kdBacktrace() << endl; + //} + //else + if ( !d->m_widget ) { + d->m_widget = w; + qDebug("KActionCollection::setWidget: warning: KAccel is never used in microkde"); +//US d->m_kaccel = new KAccel( w, this, "KActionCollection-KAccel" ); + } + else if ( d->m_widget != w ) + kdWarning(129) << "KActionCollection::setWidget(): tried to change widget from " << d->m_widget << " to " << w << endl; +} + +void KActionCollection::setAutoConnectShortcuts( bool b ) +{ + d->m_bAutoConnectShortcuts = b; +} + +bool KActionCollection::isAutoConnectShortcuts() +{ + return d->m_bAutoConnectShortcuts; +} + +bool KActionCollection::addDocCollection( KActionCollection* pDoc ) +{ + d->m_docList.append( pDoc ); + return true; +} + +void KActionCollection::beginXMLPlug( QWidget *widget ) +{ + qDebug("KActionCollection::beginXMLPlug has to be fixed"); +/*US + kdDebug(129) << "KActionCollection::beginXMLPlug( buildWidget = " << widget << " ): this = " << this << " d->m_builderKAccel = " << d->m_builderKAccel << endl; + + if( widget && !d->m_builderKAccel ) { + d->m_builderKAccel = new KAccel( widget, this, "KActionCollection-BuilderKAccel" ); + } +*/ +} + +void KActionCollection::endXMLPlug() +{ + kdDebug(129) << "KActionCollection::endXMLPlug(): this = " << this << endl; + //s_kaccelXML = 0; +} + +void KActionCollection::prepareXMLUnplug() +{ + qDebug("KActionCollection::prepareXMLUnplug has to be fixed"); +/*US + kdDebug(129) << "KActionCollection::prepareXMLUnplug(): this = " << this << endl; + unplugShortcuts( d->m_kaccel ); + + if( d->m_builderKAccel ) { + unplugShortcuts( d->m_builderKAccel ); + delete d->m_builderKAccel; + d->m_builderKAccel = 0; + } +*/ +} + +void KActionCollection::unplugShortcuts( KAccel* kaccel ) +{ + qDebug("KActionCollection::unplugShortcuts has to be fixed"); +/*US + for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) { + KAction* pAction = it.current(); + pAction->removeKAccel( kaccel ); + } + + for( uint i = 0; i < d->m_docList.count(); i++ ) + d->m_docList[i]->unplugShortcuts( kaccel ); +*/ + +} + +/*void KActionCollection::addWidget( QWidget* w ) +{ + if( !d->m_bOneKAccelOnly ) { + kdDebug(129) << "KActionCollection::addWidget( " << w << " ): this = " << this << endl; + for( uint i = 0; i < d->m_widgetList.count(); i++ ) { + if( d->m_widgetList[i] == w ) { + d->m_iWidgetCurrent = i; + return; + } + } + d->m_iWidgetCurrent = d->m_widgetList.count(); + d->m_widgetList.append( w ); + d->m_kaccelList.append( new KAccel( w, this, "KActionCollection-KAccel" ) ); + } +} + +void KActionCollection::removeWidget( QWidget* w ) +{ + if( !d->m_bOneKAccelOnly ) { + kdDebug(129) << "KActionCollection::removeWidget( " << w << " ): this = " << this << endl; + for( uint i = 0; i < d->m_widgetList.count(); i++ ) { + if( d->m_widgetList[i] == w ) { + // Remove KAccel object from children. + KAccel* pKAccel = d->m_kaccelList[i]; + for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) { + KAction* pAction = it.current(); + if ( pAction->m_parentCollection == this ) { + pAction->removeKAccel( pKAccel ); + } + } + delete pKAccel; + + d->m_widgetList.remove( d->m_widgetList.at( i ) ); + d->m_kaccelList.remove( d->m_kaccelList.at( i ) ); + + if( d->m_iWidgetCurrent == (int)i ) + d->m_iWidgetCurrent = -1; + else if( d->m_iWidgetCurrent > (int)i ) + d->m_iWidgetCurrent--; + return; + } + } + kdWarning(129) << "KActionCollection::removeWidget( " << w << " ): widget not in list." << endl; + } +} + +bool KActionCollection::ownsKAccel() const +{ + return d->m_bOneKAccelOnly; +} + +uint KActionCollection::widgetCount() const +{ + return d->m_widgetList.count(); +} + +const KAccel* KActionCollection::widgetKAccel( uint i ) const +{ + return d->m_kaccelList[i]; +}*/ + +//US we are using no accelerators so far. So just setup an empty implementation. +KAccel* KActionCollection::kaccel() +{ + //if( d->m_kaccelList.count() > 0 ) + // return d->m_kaccelList[d->m_iWidgetCurrent]; + //else + // return 0; +//US return d->m_kaccel; + return 0; +} + +//US we are using no accelerators so far. So just setup an empty implementation. +const KAccel* KActionCollection::kaccel() const +{ + //if( d->m_kaccelList.count() > 0 ) + // return d->m_kaccelList[d->m_iWidgetCurrent]; + //else + // return 0; + //USreturn d->m_kaccel; + return 0; +} + +/*void KActionCollection::findMainWindow( QWidget *w ) +{ + // Note: topLevelWidget() stops too early, we can't use it. + QWidget * tl = w; + while ( tl->parentWidget() ) // lookup parent and store + tl = tl->parentWidget(); + + KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow + if (mw) + d->m_mainwindow = mw; + else + kdDebug(129) << "KAction::plugMainWindowAccel: Toplevel widget isn't a KMainWindow, can't plug accel. " << tl << endl; +}*/ + +void KActionCollection::_insert( KAction* action ) +{ + char unnamed_name[100]; + const char *name = action->name(); + if( qstrcmp( name, "unnamed" ) == 0 ) + { + sprintf(unnamed_name, "unnamed-%p", (void *)action); + name = unnamed_name; + } + KAction *a = d->m_actionDict[ name ]; + if ( a == action ) + return; + + d->m_actionDict.insert( name, action ); + + emit inserted( action ); +} + +void KActionCollection::_remove( KAction* action ) +{ + delete _take( action ); +} + +KAction* KActionCollection::_take( KAction* action ) +{ + char unnamed_name[100]; + const char *name = action->name(); + if( qstrcmp( name, "unnamed" ) == 0 ) + { + sprintf(unnamed_name, "unnamed-%p", (void *) action); + name = unnamed_name; + } + + KAction *a = d->m_actionDict.take( name ); + if ( !a || a != action ) + return 0; + + emit removed( action ); + return a; +} + +void KActionCollection::_clear() +{ + QAsciiDictIterator<KAction> it( d->m_actionDict ); + while ( it.current() ) + _remove( it.current() ); +} + +void KActionCollection::insert( KAction* action ) { _insert( action ); } +void KActionCollection::remove( KAction* action ) { _remove( action ); } +KAction* KActionCollection::take( KAction* action ) { return _take( action ); } +void KActionCollection::clear() { _clear(); } +KAccel* KActionCollection::accel() { return kaccel(); } +const KAccel* KActionCollection::accel() const { return kaccel(); } +KAccel* KActionCollection::builderKAccel() const { return d->m_builderKAccel; } + +KAction* KActionCollection::action( const char* name, const char* classname ) const +{ + KAction* pAction = 0; + + if ( !classname && name ) + pAction = d->m_actionDict[ name ]; + + else { + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + { + if ( ( !name || strcmp( it.current()->name(), name ) == 0 ) && + ( !classname || strcmp( it.current()->className(), classname ) == 0 ) ) { + pAction = it.current(); + break; + } + } + } + + if( !pAction ) { + for( uint i = 0; i < d->m_docList.count() && !pAction; i++ ) + pAction = d->m_docList[i]->action( name, classname ); + } + + return pAction; +} + +KAction* KActionCollection::action( int index ) const +{ + QAsciiDictIterator<KAction> it( d->m_actionDict ); + it += index; + return it.current(); +// return d->m_actions.at( index ); +} +/*US +bool KActionCollection::readShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig ) +{ + return KActionShortcutList(this).readSettings( sConfigGroup, pConfig ); +} + +bool KActionCollection::writeShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig ) const +{ + return KActionShortcutList((KActionCollection*)this).writeSettings( sConfigGroup, pConfig ); +} +*/ +uint KActionCollection::count() const +{ + return d->m_actionDict.count(); +} + +QStringList KActionCollection::groups() const +{ + QStringList lst; + + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + if ( !it.current()->group().isEmpty() && !lst.contains( it.current()->group() ) ) + lst.append( it.current()->group() ); + + return lst; +} + +KActionPtrList KActionCollection::actions( const QString& group ) const +{ + KActionPtrList lst; + + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + if ( it.current()->group() == group ) + lst.append( it.current() ); + else if ( it.current()->group().isEmpty() && group.isEmpty() ) + lst.append( it.current() ); + + return lst; +} + +KActionPtrList KActionCollection::actions() const +{ + KActionPtrList lst; + + QAsciiDictIterator<KAction> it( d->m_actionDict ); + for( ; it.current(); ++it ) + lst.append( it.current() ); + + return lst; +} + +/*US we have no instance object. Use KGlobal instead +void KActionCollection::setInstance( KInstance *instance ) +{ + if ( instance ) + d->m_instance = instance; +qDebug("KActionCollection::setInstance has to be fixed"); + else + d->m_instance = KGlobal::instance(); +} + +KInstance *KActionCollection::instance() const +{ + return d->m_instance; +} +*/ + +/*US we have no XML facility in microkde +void KActionCollection::setXMLFile( const QString& sXMLFile ) +{ + d->m_sXMLFile = sXMLFile; +} + +const QString& KActionCollection::xmlFile() const +{ + return d->m_sXMLFile; +} +*/ + +void KActionCollection::setHighlightingEnabled( bool enable ) +{ + d->m_highlight = enable; +} + +bool KActionCollection::highlightingEnabled() const +{ + return d->m_highlight; +} + +void KActionCollection::connectHighlight( QWidget *container, KAction *action ) +{ + if ( !d->m_highlight ) + return; + + QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ]; + + if ( !actionList ) + { + actionList = new QPtrList<KAction>; + + if ( container->inherits( "QPopupMenu" ) ) + { + connect( container, SIGNAL( highlighted( int ) ), + this, SLOT( slotMenuItemHighlighted( int ) ) ); + connect( container, SIGNAL( aboutToHide() ), + this, SLOT( slotMenuAboutToHide() ) ); + } +//US else if ( container->inherits( "KToolBar" ) ) + else if ( container->inherits( "QToolBar" ) ) + { + connect( container, SIGNAL( highlighted( int, bool ) ), + this, SLOT( slotToolBarButtonHighlighted( int, bool ) ) ); + } + + connect( container, SIGNAL( destroyed() ), + this, SLOT( slotDestroyed() ) ); + + d->m_dctHighlightContainers.insert( container, actionList ); + } + + actionList->append( action ); +} + +void KActionCollection::disconnectHighlight( QWidget *container, KAction *action ) +{ + if ( !d->m_highlight ) + return; + + QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ]; + + if ( !actionList ) + return; + + actionList->removeRef( action ); + + if ( actionList->count() == 0 ) + d->m_dctHighlightContainers.remove( container ); +} + +void KActionCollection::slotMenuItemHighlighted( int id ) +{ + if ( !d->m_highlight ) + return; + + if ( d->m_currentHighlightAction ) + emit actionHighlighted( d->m_currentHighlightAction, false ); + + QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) ); + + d->m_currentHighlightAction = findAction( container, id ); + + if ( !d->m_currentHighlightAction ) + { + if ( !d->m_statusCleared ) + emit clearStatusText(); + d->m_statusCleared = true; + return; + } + + d->m_statusCleared = false; + emit actionHighlighted( d->m_currentHighlightAction ); + emit actionHighlighted( d->m_currentHighlightAction, true ); + emit actionStatusText( d->m_currentHighlightAction->toolTip() ); +} + +void KActionCollection::slotMenuAboutToHide() +{ + if ( d->m_currentHighlightAction ) + emit actionHighlighted( d->m_currentHighlightAction, false ); + d->m_currentHighlightAction = 0; + + if ( !d->m_statusCleared ) + emit clearStatusText(); + d->m_statusCleared = true; +} + +void KActionCollection::slotToolBarButtonHighlighted( int id, bool highlight ) +{ + if ( !d->m_highlight ) + return; + + QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) ); + + KAction *action = findAction( container, id ); + + if ( !action ) + { + d->m_currentHighlightAction = 0; + // use tooltip groups for toolbar status text stuff instead (Simon) +// emit clearStatusText(); + return; + } + + emit actionHighlighted( action, highlight ); + + if ( highlight ) + d->m_currentHighlightAction = action; + else + { + d->m_currentHighlightAction = 0; +// emit clearStatusText(); + } +} + +void KActionCollection::slotDestroyed() +{ + d->m_dctHighlightContainers.remove( reinterpret_cast<void *>( const_cast<QObject *>(sender()) ) ); +} + +KAction *KActionCollection::findAction( QWidget *container, int id ) +{ + QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ reinterpret_cast<void *>( container ) ]; + + if ( !actionList ) + return 0; + + QPtrListIterator<KAction> it( *actionList ); + for (; it.current(); ++it ) + if ( it.current()->isPlugged( container, id ) ) + return it.current(); + + return 0; +} + +// KDE 4: remove +KActionCollection KActionCollection::operator+(const KActionCollection &c ) const +{ + kdWarning(129) << "KActionCollection::operator+(): function is severely deprecated." << endl; + KActionCollection ret( *this ); + + QValueList<KAction *> actions = c.actions(); + QValueList<KAction *>::ConstIterator it = actions.begin(); + QValueList<KAction *>::ConstIterator end = actions.end(); + for (; it != end; ++it ) + ret.insert( *it ); + + return ret; +} + +KActionCollection &KActionCollection::operator=( const KActionCollection © ) +{ + kdWarning(129) << "KActionCollection::operator=(): function is severely deprecated." << endl; + //d->m_bOneKAccelOnly = copy.d->m_bOneKAccelOnly; + //d->m_iWidgetCurrent = copy.d->m_iWidgetCurrent; + //d->m_widgetList = copy.d->m_widgetList; + //d->m_kaccelList = copy.d->m_kaccelList; + d->m_widget = copy.d->m_widget; + d->m_kaccel = copy.d->m_kaccel; + d->m_actionDict = copy.d->m_actionDict; +//US setInstance( copy.instance() ); + return *this; +} + +KActionCollection &KActionCollection::operator+=( const KActionCollection &c ) +{ + kdWarning(129) << "KActionCollection::operator+=(): function is severely deprecated." << endl; + QAsciiDictIterator<KAction> it(c.d->m_actionDict); + for ( ; it.current(); ++it ) + insert( it.current() ); + + return *this; +} +// KDE 4: remove end + +//--------------------------------------------------------------------- +// KActionShortcutList +//--------------------------------------------------------------------- +/*US +KActionShortcutList::KActionShortcutList( KActionCollection* pColl ) +: m_actions( *pColl ) + { } +KActionShortcutList::~KActionShortcutList() + { } +uint KActionShortcutList::count() const + { return m_actions.count(); } +QString KActionShortcutList::name( uint i ) const + { return m_actions.action(i)->name(); } +QString KActionShortcutList::label( uint i ) const + { return m_actions.action(i)->text(); } +QString KActionShortcutList::whatsThis( uint i ) const + { return m_actions.action(i)->whatsThis(); } +const KShortcut& KActionShortcutList::shortcut( uint i ) const + { return m_actions.action(i)->shortcut(); } +const KShortcut& KActionShortcutList::shortcutDefault( uint i ) const + { return m_actions.action(i)->shortcutDefault(); } +bool KActionShortcutList::isConfigurable( uint i ) const + { return m_actions.action(i)->isShortcutConfigurable(); } +bool KActionShortcutList::setShortcut( uint i, const KShortcut& cut ) + { return m_actions.action(i)->setShortcut( cut ); } +const KInstance* KActionShortcutList::instance() const + { return m_actions.instance(); } +QVariant KActionShortcutList::getOther( Other, uint ) const + { return QVariant(); } +bool KActionShortcutList::setOther( Other, uint, QVariant ) + { return false; } + +bool KActionShortcutList::save() const +{ + kdDebug(129) << "KActionShortcutList::save(): xmlFile = " << m_actions.xmlFile() << endl; + + if( m_actions.xmlFile().isEmpty() ) + return writeSettings(); + + QString tagActionProp = QString::fromLatin1("ActionProperties"); + QString tagAction = QString::fromLatin1("Action"); + QString attrName = QString::fromLatin1("name"); + QString attrShortcut = QString::fromLatin1("shortcut"); + QString attrAccel = QString::fromLatin1("accel"); // Depricated attribute + + // Read XML file + QString sXml( KXMLGUIFactory::readConfigFile( m_actions.xmlFile(), false, instance() ) ); + QDomDocument doc; + doc.setContent( sXml ); + + // Process XML data + + // first, lets see if we have existing properties + QDomElement elem; + QDomElement it = doc.documentElement(); + // KXMLGUIFactory::removeDOMComments( it ); <-- What was this for? --ellis + it = it.firstChild().toElement(); + for( ; !it.isNull(); it = it.nextSibling().toElement() ) { + if( it.tagName() == tagActionProp ) { + elem = it; + break; + } + } + + // if there was none, create one + if( elem.isNull() ) { + elem = doc.createElement( tagActionProp ); + doc.documentElement().appendChild( elem ); + } + + // now, iterate through our actions + uint nSize = count(); + for( uint i = 0; i < nSize; i++ ) { + const QString& sName = name(i); + + bool bSameAsDefault = (shortcut(i) == shortcutDefault(i)); + //kdDebug(129) << "name = " << sName << " shortcut = " << shortcut(i).toStringInternal() << " def = " << shortcutDefault(i).toStringInternal() << endl; + + // now see if this element already exists + QDomElement act_elem; + for( it = elem.firstChild().toElement(); !it.isNull(); it = it.nextSibling().toElement() ) { + if( it.attribute( attrName ) == sName ) { + act_elem = it; + break; + } + } + + // nope, create a new one + if( act_elem.isNull() ) { + if( bSameAsDefault ) + continue; + //kdDebug(129) << "\tnode doesn't exist." << endl; + act_elem = doc.createElement( tagAction ); + act_elem.setAttribute( attrName, sName ); + } + + act_elem.removeAttribute( attrAccel ); + if( bSameAsDefault ) { + act_elem.removeAttribute( attrShortcut ); + //kdDebug(129) << "act_elem.attributes().count() = " << act_elem.attributes().count() << endl; + if( act_elem.attributes().count() == 1 ) + elem.removeChild( act_elem ); + } else { + act_elem.setAttribute( attrShortcut, shortcut(i).toStringInternal() ); + elem.appendChild( act_elem ); + } + } + + // Write back to XML file + return KXMLGUIFactory::saveConfigFile( doc, m_actions.xmlFile(), instance() ); +} + +//--------------------------------------------------------------------- +// KActionPtrShortcutList +//--------------------------------------------------------------------- + +KActionPtrShortcutList::KActionPtrShortcutList( KActionPtrList& list ) +: m_actions( list ) + { } +KActionPtrShortcutList::~KActionPtrShortcutList() + { } +uint KActionPtrShortcutList::count() const + { return m_actions.count(); } +QString KActionPtrShortcutList::name( uint i ) const + { return m_actions[i]->name(); } +QString KActionPtrShortcutList::label( uint i ) const + { return m_actions[i]->text(); } +QString KActionPtrShortcutList::whatsThis( uint i ) const + { return m_actions[i]->whatsThis(); } +const KShortcut& KActionPtrShortcutList::shortcut( uint i ) const + { return m_actions[i]->shortcut(); } +const KShortcut& KActionPtrShortcutList::shortcutDefault( uint i ) const + { return m_actions[i]->shortcutDefault(); } +bool KActionPtrShortcutList::isConfigurable( uint i ) const + { return m_actions[i]->isShortcutConfigurable(); } +bool KActionPtrShortcutList::setShortcut( uint i, const KShortcut& cut ) + { return m_actions[i]->setShortcut( cut ); } +QVariant KActionPtrShortcutList::getOther( Other, uint ) const + { return QVariant(); } +bool KActionPtrShortcutList::setOther( Other, uint, QVariant ) + { return false; } +bool KActionPtrShortcutList::save() const + { return false; } + +void KActionShortcutList::virtual_hook( int id, void* data ) +{ KShortcutList::virtual_hook( id, data ); } + +void KActionPtrShortcutList::virtual_hook( int id, void* data ) +{ KShortcutList::virtual_hook( id, data ); } +*/ + +void KActionCollection::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +/* vim: et sw=2 ts=2 + */ + +/*US +#include "kactioncollection.moc" +*/ diff --git a/microkde/kdeui/kactioncollection.h b/microkde/kdeui/kactioncollection.h new file mode 100644 index 0000000..b9466d0 --- a/dev/null +++ b/microkde/kdeui/kactioncollection.h @@ -0,0 +1,329 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> + (C) 1999 Simon Hausmann <hausmann@kde.org> + (C) 2000 Nicolas Hadacek <haadcek@kde.org> + (C) 2000 Kurt Granroth <granroth@kde.org> + (C) 2000 Michael Koch <koch@kde.org> + (C) 2001 Holger Freyther <freyther@kde.org> + (C) 2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +//$Id$ + +#ifndef __kactioncollection_h__ +#define __kactioncollection_h__ + +#include <kaction.h> + +//US #include <qkeysequence.h> +#include <qobject.h> +//US#include <qvaluelist.h> +//US#include <qguardedptr.h> +//US #include <kguiitem.h> +//US#include <kshortcut.h> +//US#include <kstdaction.h> +//US#include <kicontheme.h> + +//USclass QMenuBar; +//USclass QPopupMenu; +//USclass QComboBox; +//USclass QPoint; +//USclass QIconSet; +//USclass QString; +//USclass KToolBar; + +//USclass KAccel; +//USclass KAccelActions; +//USclass KConfig; +//USclass KConfigBase; +//USclass KURL; +//USclass KInstance; +//USclass KToolBar; +//USclass KActionCollection; +//USclass KPopupMenu; +//USclass KMainWindow; + +//US added inclidefiles +class QWidget; + + +typedef QValueList<KAction *> KActionPtrList; + +/** + * A managed set of KAction objects. + */ +class KActionCollection : public QObject +{ + friend class KAction; + friend class KXMLGUIClient; + + Q_OBJECT +public: + KActionCollection( QWidget *parent, const char *name = 0/*US , KInstance *instance = 0 */); + /** + * Use this constructor if you want the collection's actions to restrict + * their accelerator keys to @p watch rather than the @p parent. If + * you don't require shortcuts, you can pass a null to the @p watch parameter. + */ + KActionCollection( QWidget *watch, QObject* parent, const char *name = 0/*US, KInstance *instance = 0 */); + KActionCollection( const KActionCollection © ); + virtual ~KActionCollection(); + + /** + * This sets the widget to which the keyboard shortcuts should be attached. + * You only need to call this if a null pointer was passed in the constructor. + */ + virtual void setWidget( QWidget *widget ); + + /** + * This indicates whether new actions which are created in this collection + * should have their keyboard shortcuts automatically connected on + * construction. Set to 'false' if you will be loading XML-based settings. + * This is automatically done by KParts. The default is 'true'. + * @see isAutoConnectShortcuts() + */ + void setAutoConnectShortcuts( bool ); + + /** + * This indicates whether new actions which are created in this collection + * have their keyboard shortcuts automatically connected on + * construction. + * @see setAutoConnectShortcuts() + */ + bool isAutoConnectShortcuts(); + + /** + * This sets the default shortcut scope for new actions created in this + * collection. The default is ScopeUnspecified. Ideally the default + * would have been ScopeWidget, but that would cause some backwards + * compatibility problems. + */ + //void setDefaultScope( KAction::Scope ); + + /** + * Doc/View model. This lets you add the action collection of a document + * to a view's action collection. + */ + bool addDocCollection( KActionCollection* pDoc ); + + /** Returns the number of widgets which this collection is associated with. */ + //uint widgetCount() const; + + /** + * Returns true if the collection has its own KAccel object. This will be + * the case if it was constructed with a valid widget ptr or if setWidget() + * was called. + */ + //bool ownsKAccel() const; + + /** @deprecated Deprecated because of ambiguous name. Use kaccel() */ + virtual KAccel* accel(); + /** @deprecated Deprecated because of ambiguous name. Use kaccel() */ + virtual const KAccel* accel() const; + + /** Returns the KAccel object of the most recently set widget. */ + KAccel* kaccel(); + /** Returns the KAccel object of the most recently set widget. Const version for convenience. */ + const KAccel* kaccel() const; + + /** @internal, for KAction::kaccelCurrent() */ + KAccel* builderKAccel() const; + /** Returns the KAccel object associated with widget #. */ + //KAccel* widgetKAccel( uint i ); + //const KAccel* widgetKAccel( uint i ) const; + + /** Returns the number of actions in the collection */ + virtual uint count() const; + bool isEmpty() const { return count() == 0; } + /** + * Return the KAction* at position "index" in the action collection. + * @see count() + */ + virtual KAction* action( int index ) const; + /** + * Find an action (optionally, of a given subclass of KAction) in the action collection. + * @param name Name of the KAction. + * @param classname Name of the KAction subclass. + * @return A pointer to the first KAction in the collection which matches the parameters or + * null if nothing matches. + */ + virtual KAction* action( const char* name, const char* classname = 0 ) const; + + /** Returns a list of all the groups of all the KActions in this action collection. + * @see KAction::group() + * @see KAction::setGroup() + */ + virtual QStringList groups() const; + /** + * Returns the list of actions in a particular managed by this action collection. + * @param group The name of the group. + */ + virtual KActionPtrList actions( const QString& group ) const; + /** Returns the list of actions managed by this action collection. */ + virtual KActionPtrList actions() const; + + /** + * Used for reading shortcut configuration from a non-XML rc file. + */ +//US bool readShortcutSettings( const QString& sConfigGroup = QString::null, KConfigBase* pConfig = 0 ); + /** + * Used for writing shortcut configuration to a non-XML rc file. + */ +//US bool writeShortcutSettings( const QString& sConfigGroup = QString::null, KConfigBase* pConfig = 0 ) const; + +//US void setInstance( KInstance *instance ); + /** The instance with which this class is associated. */ +//US KInstance *instance() const; + + /** + * Use this to tell the KActionCollection what rc file its configuration + * is stored in. + */ + void setXMLFile( const QString& ); + /** The rc file in which the current configuration is stored. */ + const QString& xmlFile() const; + + /** + * Enable highlighting notification for specific KActions. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see actionHighlighted() + * @see highlightingEnabled() + */ + void setHighlightingEnabled( bool enable ); + /** + * Return whether highlighting notifications are enabled. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see actionHighlighted() + */ + bool highlightingEnabled() const; + + /** + * Call this function if you want to receive a signal whenever a KAction is highlighted in a menu or a toolbar. + * @param container A container in which the KAction is plugged (must inherit QPopupMenu or KToolBar) + * @param action The action you are interested in + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + * @see actionHighlighted() + */ + void connectHighlight( QWidget *container, KAction *action ); + /** + * Disconnect highlight notifications for a particular pair of contianer and action. + * @param container A container in which the KAction is plugged (must inherit QPopupMenu or KToolBar) + * @param action The action you are interested in + * @see connectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + * @see actionHighlighted() + */ + void disconnectHighlight( QWidget *container, KAction *action ); + +signals: + void inserted( KAction* ); + void removed( KAction* ); + + /** Emitted when "action" is highlighted. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + */ + void actionHighlighted( KAction *action ); + /** Emitted when "action" is highlighed or loses highlighting. + * @see connectHighlight() + * @see disconnectHighlight() + * @see actionHighlighted() + * @see setHighlightingEnabled() + * @see highlightingEnabled() + */ + void actionHighlighted( KAction *action, bool highlight ); + + void actionStatusText( const QString &text ); + void clearStatusText(); + +private: + /** + * @internal Only to be called by KXMLGUIFactory::addClient(). + * When actions are being connected, KAction needs to know what + * widget it should connect widget-scope actions to, and what + * main window it should connect + */ + void beginXMLPlug( QWidget *widget ); + void endXMLPlug(); + /** @internal. Only to be called by KXMLGUIFactory::removeClient() */ + void prepareXMLUnplug(); + void unplugShortcuts( KAccel* kaccel ); + + void _clear(); + void _insert( KAction* ); + void _remove( KAction* ); + KAction* _take( KAction* ); + +private slots: + void slotMenuItemHighlighted( int id ); + void slotToolBarButtonHighlighted( int id, bool highlight ); + void slotMenuAboutToHide(); + void slotDestroyed(); + +private: + KAction *findAction( QWidget *container, int id ); + +#ifndef KDE_NO_COMPAT +public: + KActionCollection( QObject *parent, const char *name = 0 /*US, KInstance *instance = 0 */); + + void insert( KAction* ); + + /** + * @deprecated Removes an action from the collection and deletes it. + * @param action The KAction to remove. + */ + void remove( KAction* action ); + + /** + * @deprecated Removes an action from the collection. + * @return NULL if not found else returns action. + * @param action the KAction to remove. + */ + KAction* take( KAction* action ); + + KActionCollection operator+ ( const KActionCollection& ) const; + KActionCollection& operator= ( const KActionCollection& ); + KActionCollection& operator+= ( const KActionCollection& ); + +public slots: + /** + * Clears the entire actionCollection, deleting all actions. + * @see #remove + */ + void clear(); +#endif // !KDE_NO_COMPAT +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KActionCollectionPrivate; + KActionCollectionPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/kbuttonbox.cpp b/microkde/kdeui/kbuttonbox.cpp new file mode 100644 index 0000000..16206e8 --- a/dev/null +++ b/microkde/kdeui/kbuttonbox.cpp @@ -0,0 +1,300 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Mario Weilguni (mweilguni@sime.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * KButtonBox class + * + * A container widget for buttons. Uses Qt layout control to place the + * buttons, can handle both vertical and horizontal button placement. +* + * HISTORY + * + * 03/08/2000 Mario Weilguni <mweilguni@kde.org> + * Removed all those long outdated Motif stuff + * Improved and clarified some if conditions (easier to understand) + * + * 11/13/98 Reginald Stadlbauer <reggie@kde.org> + * Now in Qt 1.4x motif default buttons have no extra width/height anymore. + * So the KButtonBox doesn't add this width/height to default buttons anymore + * which makes the buttons look better. + * + * 01/17/98 Mario Weilguni <mweilguni@sime.com> + * Fixed a bug in sizeHint() + * Improved the handling of Motif default buttons + * + * 01/09/98 Mario Weilguni <mweilguni@sime.com> + * The last button was to far right away from the right/bottom border. + * Fixed this. Removed old code. Buttons get now a minimum width. + * Programmer may now override minimum width and height of a button. + * + */ + +//US #include "kbuttonbox.moc" + +#include <kbuttonbox.h> +#include <qpushbutton.h> +#include <qptrlist.h> +#include <assert.h> + +#define minButtonWidth 50 + +class KButtonBox::Item { +public: + QPushButton *button; + bool noexpand; + unsigned short stretch; + unsigned short actual_size; +}; + +template class QPtrList<KButtonBox::Item>; + +class KButtonBoxPrivate { +public: + unsigned short border; + unsigned short autoborder; + unsigned short orientation; + bool activated; + QPtrList<KButtonBox::Item> buttons; +}; + +KButtonBox::KButtonBox(QWidget *parent, Orientation _orientation, + int border, int autoborder) + : QWidget(parent) +{ + data = new KButtonBoxPrivate; + assert(data != 0); + + data->orientation = _orientation; + data->border = border; + data->autoborder = autoborder < 0 ? border : autoborder; + data->buttons.setAutoDelete(TRUE); +} + +KButtonBox::~KButtonBox() { + delete data; +} + +QPushButton *KButtonBox::addButton(const QString& text, bool noexpand) { + Item *item = new Item; + + item->button = new QPushButton(text, this); + item->noexpand = noexpand; + data->buttons.append(item); + item->button->adjustSize(); + + return item->button; +} + + QPushButton * +KButtonBox::addButton( + const QString & text, + QObject * receiver, + const char * slot, + bool noexpand +) +{ + QPushButton * pb = addButton(text, noexpand); + + if ((0 != receiver) && (0 != slot)) + QObject::connect(pb, SIGNAL(clicked()), receiver, slot); + + return pb; +} + + +void KButtonBox::addStretch(int scale) { + if(scale > 0) { + Item *item = new Item; + item->button = 0; + item->noexpand = FALSE; + item->stretch = scale; + data->buttons.append(item); + } +} + +void KButtonBox::layout() { + // resize all buttons + QSize bs = bestButtonSize(); + + for(unsigned int i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + QPushButton *b = item->button; + if(b != 0) { + if(item->noexpand) + b->setFixedSize(buttonSizeHint(b)); + else + b->setFixedSize(bs); + } + } + + setMinimumSize(sizeHint()); +} + +void KButtonBox::placeButtons() { + unsigned int i; + + if(data->orientation == Horizontal) { + // calculate free size and stretches + int fs = width() - 2 * data->border; + int stretch = 0; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) { + fs -= item->button->width(); + + // Last button? + if(i != data->buttons.count() - 1) + fs -= data->autoborder; + } else + stretch +=item->stretch; + } + + // distribute buttons + int x_pos = data->border; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) { + QPushButton *b = item->button; + b->move(x_pos, (height() - b->height()) / 2); + + x_pos += b->width() + data->autoborder; + } else + x_pos += (int)((((double)fs) * item->stretch) / stretch); + } + } else { // VERTICAL + // calcualte free size and stretches + int fs = height() - 2 * data->border; + int stretch = 0; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) + fs -= item->button->height() + data->autoborder; + else + stretch +=item->stretch; + } + + // distribute buttons + int y_pos = data->border; + for(i = 0; i < data->buttons.count(); i++) { + Item *item = data->buttons.at(i); + if(item->button != 0) { + QPushButton *b = item->button; + b->move((width() - b->width()) / 2, y_pos); + + y_pos += b->height() + data->autoborder; + } else + y_pos += (int)((((double)fs) * item->stretch) / stretch); + } + } +} + +void KButtonBox::resizeEvent(QResizeEvent *) { + placeButtons(); +} + +QSize KButtonBox::bestButtonSize() const { + QSize s(0, 0); + unsigned int i; + + // calculate optimal size + for(i = 0; i < data->buttons.count(); i++) { + KButtonBox *that = (KButtonBox*)this; // to remove the const ;( + Item *item = that->data->buttons.at(i); + QPushButton *b = item->button; + + if(b != 0 && !item->noexpand) { + QSize bs = buttonSizeHint(b); + + if(bs.width() > s.width()) + s.setWidth(bs.width()); + if(bs.height() > s.height()) + s.setHeight(bs.height()); + } + } + + return s; +} + +QSize KButtonBox::sizeHint() const { + unsigned int i, dw; + + if(data->buttons.count() == 0) + return QSize(0, 0); + else { + dw = 2 * data->border; + + QSize bs = bestButtonSize(); + for(i = 0; i < data->buttons.count(); i++) { + KButtonBox *that = (KButtonBox*)this; + Item *item = that->data->buttons.at(i); + QPushButton *b = item->button; + if(b != 0) { + QSize s; + if(item->noexpand) + s = that->buttonSizeHint(b); + else + s = bs; + + if(data->orientation == Horizontal) + dw += s.width(); + else + dw += s.height(); + + if( i != data->buttons.count() - 1 ) + dw += data->autoborder; + } + } + + if(data->orientation == Horizontal) + return QSize(dw, bs.height() + 2 * data->border); + else + return QSize(bs.width() + 2 * data->border, dw); + } +} + +QSizePolicy KButtonBox::sizePolicy() const +{ + return data->orientation == Horizontal? + QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) : + QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ); +} + +/* + * Returns the best size for a button. If a button is less than + * minButtonWidth pixels wide, return minButtonWidth pixels + * as minimum width + */ +QSize KButtonBox::buttonSizeHint(QPushButton *b) const { + QSize s = b->sizeHint(); + QSize ms = b->minimumSize(); + if(s.width() < minButtonWidth) + s.setWidth(minButtonWidth); + + // allows the programmer to override the settings + if(ms.width() > s.width()) + s.setWidth(ms.width()); + if(ms.height() > s.height()) + s.setHeight(ms.height()); + + return s; +} + +void KButtonBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + diff --git a/microkde/kdeui/kbuttonbox.h b/microkde/kdeui/kbuttonbox.h new file mode 100644 index 0000000..1104366 --- a/dev/null +++ b/microkde/kdeui/kbuttonbox.h @@ -0,0 +1,139 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Mario Weilguni (mweilguni@sime.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __KBUTTONBOX__H__ +#define __KBUTTONBOX__H__ + +#include <qwidget.h> +class QPushButton; + +class KButtonBoxPrivate; +/** + * Container widget for buttons. + * + * This class uses Qt layout control to place the buttons; can handle + * both vertical and horizontal button placement. The default border + * is now @p 0 (making it easier to deal with layouts). The space + * between buttons is now more Motif compliant. + * + * @author Mario Weilguni <mweilguni@sime.com> + * @version $Id$ + **/ + +class KButtonBox : public QWidget +{ + Q_OBJECT + +public: + /** + * Create an empty container for buttons. + * + * If @p _orientation is @p Vertical, the buttons inserted with + * @ref addButton() are laid out from top to bottom, otherwise they + * are laid out from left to right. + */ + KButtonBox(QWidget *parent, Orientation _orientation = Horizontal, + int border = 0, int _autoborder = 6); + + /** + * Free private data field + */ + ~KButtonBox(); + + /** + * @return The minimum size needed to fit all buttons. + * + * This size is + * calculated by the width/height of all buttons plus border/autoborder. + */ + virtual QSize sizeHint() const; + /** + * @reimplemented + */ + virtual QSizePolicy sizePolicy() const; + /** + * @reimplemented + */ + virtual void resizeEvent(QResizeEvent *); + + /** + * Add a new @ref QPushButton. + * + * @param noexpand If @p noexpand is @p false, the width + * of the button is adjusted to fit the other buttons (the maximum + * of all buttons is taken). If @p noexpand is @p true, the width of this + * button will be set to the minimum width needed for the given text). + * + * @return A pointer to the new button. + */ + QPushButton *addButton(const QString& text, bool noexpand = FALSE); + + /** + * Add a new @ref QPushButton. + * + * @param receiver An object to connect to. + * @param slot A Qt slot to connect the 'clicked()' signal to. + * @param noexpand If @p noexpand is @p false, the width + * of the button is adjusted to fit the other buttons (the maximum + * of all buttons is taken). If @p noexpand @p true, the width of this + * button will be set to the minimum width needed for the given text). + * + * @return A pointer to the new button. + */ + QPushButton *addButton(const QString& text, QObject * receiver, const char * slot, bool noexpand = FALSE); + + /** + * Add a stretch to the buttonbox. + * + * Can be used to separate buttons. That is, if you add the + * buttons OK and Cancel, add a stretch, and then add the button Help, + * the buttons OK and Cancel will be left-aligned (or top-aligned + * for vertical) whereas Help will be right-aligned (or + * bottom-aligned for vertical). + * + * @see QBoxLayout + */ + void addStretch(int scale = 1); + + /** + * This function must be called @em once after all buttons have been + * inserted. + * + * It will start layout control. + */ + void layout(); + +public: // as PrivateData needs Item, it has to be exported + class Item; +protected: + /** + * @return the best size for a button. Checks all buttons and takes + * the maximum width/height. + */ + QSize bestButtonSize() const; + void placeButtons(); + QSize buttonSizeHint(QPushButton *) const; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KButtonBoxPrivate *data; +}; + +#endif diff --git a/microkde/kdeui/kcmodule.cpp b/microkde/kdeui/kcmodule.cpp new file mode 100644 index 0000000..915cd0f --- a/dev/null +++ b/microkde/kdeui/kcmodule.cpp @@ -0,0 +1,106 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2001 Michael Goffioul <goffioul@imec.be> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#include "kcmodule.h" +//US#include <kinstance.h> +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +class KCModulePrivate +{ +public: +//US KInstance *_instance; + QString _rootOnlyMsg; + bool _useRootOnlyMsg; + bool _hasOwnInstance; +}; + +KCModule::KCModule(QWidget *parent, const char *name, const QStringList &) + : QWidget(parent, name), _btn(Help|Default|Apply) +{ + kdDebug() << "KCModule " << name << endl; + d = new KCModulePrivate; + d->_useRootOnlyMsg = true; +/*US + d->_instance = new KInstance(name); + if (name && strlen(name)) { + d->_instance = new KInstance(name); + KGlobal::locale()->insertCatalogue(name); + } else + d->_instance = new KInstance("kcmunnamed"); +*/ + d->_hasOwnInstance = true; +//US KGlobal::setActiveInstance(this->instance()); +} + +/*US +KCModule::KCModule(KInstance *instance, QWidget *parent, const QStringList & ) + : QWidget(parent, instance ? instance->instanceName().data() : 0), _btn(Help|Default|Apply) +{ + kdDebug() << "KCModule instance " << (instance ? instance->instanceName().data() : "none") << endl; + d = new KCModulePrivate; + d->_useRootOnlyMsg = true; + d->_instance = instance; + KGlobal::locale()->insertCatalogue(instance->instanceName()); + d->_hasOwnInstance = false; + KGlobal::setActiveInstance(this->instance()); +} +*/ +KCModule::~KCModule() +{ +/*US + if (d->_hasOwnInstance) + delete d->_instance; +*/ + delete d; +} + +void KCModule::setRootOnlyMsg(const QString& msg) +{ + d->_rootOnlyMsg = msg; +} + +QString KCModule::rootOnlyMsg() const +{ + return d->_rootOnlyMsg; +} + +void KCModule::setUseRootOnlyMsg(bool on) +{ + d->_useRootOnlyMsg = on; +} + +bool KCModule::useRootOnlyMsg() const +{ + return d->_useRootOnlyMsg; +} +/*US +KInstance *KCModule::instance() const +{ + return d->_instance; +} +*/ +void KCModule::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "kcmodule.moc" diff --git a/microkde/kdeui/kcmodule.h b/microkde/kdeui/kcmodule.h new file mode 100644 index 0000000..90a87c9 --- a/dev/null +++ b/microkde/kdeui/kcmodule.h @@ -0,0 +1,266 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +#ifndef __KCMODULE_H__ +#define __KCMODULE_H__ + +#include <qwidget.h> +#include <qstringlist.h> +//USclass KAboutData; +class KCModulePrivate; +//US class KInstance; + +/** + * The base class for control center modules. + * + * Starting from KDE 2.0, control center modules are realized as shared + * libraries that are loaded into the control center at runtime. + * + * The module in principle is a simple widget displaying the + * item to be changed. The module has a very small interface. + * + * All the necessary glue logic and the GUI bells and whistles + * are provided by the control center and must not concern + * the module author. + * + * To write a config module, you have to create a library + * that contains at one factory function like this: + * + * <pre> + * #include <kgenericfactory.h> + * + * typedef KGenericFactory<YourKCModule, QWidget> YourKCModuleFactory; + * K_EXPORT_COMPONENT_FACTORY( yourLibName, YourKCModuleFactory("name_of_the_po_file") ); + * </pre> + * + * The parameter "name_of_the_po_file" has to correspond with the messages target + * that you created in your Makefile.am. + * + * See kdebase/kcontrol/HOWTO for more detailed documentation. + * + * @author Matthias Hoelzer-Kluepfel <hoelzer@kde.org> + */ + +class KCModule : public QWidget +{ + Q_OBJECT + +public: + + /** + * An enumeration type for the buttons used by this module. + * You should only use Help, Default and Apply. The rest is obsolete. + * + * @see KCModule::buttons @see KCModule::setButtons + */ + enum Button {Help=1, Default=2, Apply=16, + Reset=4, /* obsolete, do not use! */ + Cancel=8, /* obsolete, do not use! */ + Ok=32, /* obsolete, do not use! */ + SysDefault=64 /* obsolete, do not use! */ }; + + /* + * Base class for all KControlModules. + * Make sure you have a QStringList argument in your + * implementation. + */ + KCModule(QWidget *parent=0, const char *name=0, const QStringList &args=QStringList() ); + +//US KCModule(KInstance *instance, QWidget *parent=0, const QStringList &args=QStringList() ); + + /* + * Destroys the module. + */ + ~KCModule(); + + /** + * Load the configuration data into the module. + * + * The load method sets the user interface elements of the + * module to reflect the current settings stored in the + * configuration files. + * + * This method is invoked whenever the module should read its configuration + * (most of the times from a config file) and update the user interface. + * This happens when the user clicks the "Reset" button in the control + * center, to undo all of his changes and restore the currently valid + * settings. NOTE that this is not called after the modules is loaded, + * so you probably want to call this method in the constructor. + */ + virtual void load() {}; + + /** + * Save the configuration data. + * + * The save method stores the config information as shown + * in the user interface in the config files. + * + * If necessary, this method also updates the running system, + * e.g. by restarting applications. + * + * save is called when the user clicks "Apply" or "Ok". + */ + virtual void save() {}; + + /** + * Sets the configuration to sensible default values. + * + * This method is called when the user clicks the "Default" + * button. It should set the display to useful values. + */ + virtual void defaults() {}; + + /** + * Set the configuration to system default values. + * + * This method is called when the user clicks the "System-Default" + * button. It should set the display to the system default values. + * + * NOTE: The default behaviour is to call defaults(). + */ + virtual void sysdefaults() { defaults(); }; + + /** + * Return a quick-help text. + * + * This method is called when the module is docked. + * The quick-help text should contain a short description of the module and + * links to the module's help files. You can use QML formating tags in the text. + * + * NOTE: Please make sure the quick help text gets translated (use i18n()). + */ + virtual QString quickHelp() const { return QString::null; }; + + /** + * Returns a the KAboutData for this module + * This is generally only called for the KBugReport. + * Override and have it return a pointer to a constant + */ +//US virtual const KAboutData *aboutData() const { return 0; } + + /** + * Indicate which buttons will be used. + * + * The return value is a value or'ed together from + * the Button enumeration type. + * + * @see KCModule::setButtons + */ + int buttons() const { return _btn; }; + + /** + * Get the RootOnly message for this module. + * + * When the module must be run as root, or acts differently + * for root and a normal user, it is sometimes useful to + * customize the message that appears at the top of the module + * when used as a normal user. This function returns this + * customized message. If none has been set, a default message + * will be used. + * + * @see KCModule::setRootOnlyMsg + */ + QString rootOnlyMsg() const; + + /** + * Tell if KControl should show a RootOnly message when run as + * a normal user. + * + * In some cases, the module don't want a RootOnly message to + * appear (for example if it has already one). This function + * tells KControl if a RootOnly message should be shown + * + * @see KCModule::setUseRootOnlyMsg + */ + bool useRootOnlyMsg() const; + + +//US KInstance *instance() const; + +signals: + + /** + * Indicate that the state of the modules contents has changed. + * + * This signal is emitted whenever the state of the configuration + * shown in the module changes. It allows the control center to + * keep track of unsaved changes. + * + */ + void changed(bool state); + + /** + * Indicate that the module's quickhelp has changed. + * + * Emit this signal whenever the module's quickhelp changes. + * Modules implemented as tabbed dialogs might want to implement + * per-tab quickhelp for example. + * + */ + void quickHelpChanged(); + +protected: + + /** + * Sets the buttons to display. + * + * Help: shows a "Help" button. + * Default: shows a "Use Defaults" button + * Apply: in kcontrol this will show an "Apply" and "Reset" button + * in kcmshell this will show an "Ok", "Apply" and "Cancel" button + * + * If Apply is not specified, kcmshell will show a "Close" button. + * + * @see KCModule::buttons + */ + void setButtons(int btn) { _btn = btn; }; + + /** + * Sets the RootOnly message. + * + * This message will be shown at the top of the module of the + * corresponding desktop file contains the line X-KDE-RootOnly=true. + * If no message is set, a default one will be used. + * + * @see KCModule::rootOnlyMessage + */ + void setRootOnlyMsg(const QString& msg); + + /** + * Change wether or not the RootOnly message should be shown. + * + * Following the value of @p on, the RootOnly message will be + * shown or not. + * + * @see KCModule::useRootOnlyMsg + */ + void setUseRootOnlyMsg(bool on); + +private: + + int _btn; +protected: + virtual void virtual_hook( int id, void* data ); +private: + KCModulePrivate *d; +}; + +#endif diff --git a/microkde/kdeui/kguiitem.cpp b/microkde/kdeui/kguiitem.cpp new file mode 100644 index 0000000..828c5e6 --- a/dev/null +++ b/microkde/kdeui/kguiitem.cpp @@ -0,0 +1,205 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001 Holger Freyther (freyher@yahoo.com) + based on ideas from Martijn and Simon + many thanks to Simon + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qregexp.h> +#include <qstring.h> +#include <qiconset.h> +#include <qpixmap.h> + +#include <assert.h> +//US #include <kiconloader.h> +#include <kdebug.h> + +#include "kguiitem.h" + +class KGuiItem::KGuiItemPrivate +{ +public: + KGuiItemPrivate() + { + m_enabled = true; + m_hasIcon = false; + } + + KGuiItemPrivate( const KGuiItemPrivate &rhs ) + { + (*this ) = rhs; + } + + KGuiItemPrivate &operator=( const KGuiItemPrivate &rhs ) + { + m_text = rhs.m_text; + m_iconSet = rhs.m_iconSet; + m_iconName = rhs.m_iconName; + m_toolTip = rhs.m_toolTip; + m_whatsThis = rhs.m_whatsThis; + m_statusText = rhs.m_statusText; + m_enabled = rhs.m_enabled; + m_hasIcon = rhs.m_hasIcon; + + return *this; + } + + QString m_text; + QString m_toolTip; + QString m_whatsThis; + QString m_statusText; + QString m_iconName; + QIconSet m_iconSet; + bool m_hasIcon : 1; + bool m_enabled : 1; +}; + + +KGuiItem::KGuiItem() { + d = new KGuiItemPrivate; +} + +KGuiItem::KGuiItem( const QString &text, const QString &iconName, + const QString &toolTip, const QString &whatsThis ) +{ + d = new KGuiItemPrivate; + d->m_text = text; + d->m_toolTip = toolTip; + d->m_whatsThis = whatsThis; + setIconName( iconName ); +} + +KGuiItem::KGuiItem( const QString &text, const QIconSet &iconSet, + const QString &toolTip, const QString &whatsThis ) +{ + d = new KGuiItemPrivate; + d->m_text = text; + d->m_toolTip = toolTip; + d->m_whatsThis = whatsThis; + setIconSet( iconSet ); +} + +KGuiItem::KGuiItem( const KGuiItem &rhs ) + : d( 0 ) +{ + (*this) = rhs; +} + +KGuiItem &KGuiItem::operator=( const KGuiItem &rhs ) { + if ( d == rhs.d ) + return *this; + + assert( rhs.d ); + + delete d; + d = new KGuiItemPrivate( *rhs.d ); + + return *this; +} + +KGuiItem::~KGuiItem() { + delete d; +} + +QString KGuiItem::text() const { + return d->m_text; +} +QString KGuiItem::plainText() const { + QString stripped( d->m_text ); + stripped.replace( QRegExp( "&(?!&)" ), QString::null ); + + return stripped; +} + +QIconSet KGuiItem::iconSet( KIcon::Group group, int size /*US, KInstance* instance */ ) const +{ + if( d->m_hasIcon ) + { + if( !d->m_iconName.isEmpty()) + { +// some caching here would(?) come handy +//US return instance->iconLoader()->loadIconSet( d->m_iconName, group, size ); + return KGlobal::iconLoader()->loadIconSet( d->m_iconName); +// here is a little problem that with delayed icon loading +// we can't check if the icon really exists ... so what ... +// if( set.isNull() ) +// { +// d->m_hasIcon = false; +// return QIconSet(); +// } +// return set; + } + else + { + return d->m_iconSet; + } + } + else + return QIconSet(); +} + +QString KGuiItem::iconName() const +{ + return d->m_iconName; +} + +QString KGuiItem::toolTip() const { + return d->m_toolTip; +} +QString KGuiItem::whatsThis() const { + return d->m_whatsThis; +} + +bool KGuiItem::isEnabled() const +{ + return d->m_enabled; +} + +bool KGuiItem::hasIcon() const +{ + return d->m_hasIcon; +} + +void KGuiItem::setText( const QString &text ) { + d->m_text=text; +} + +void KGuiItem::setIconSet( const QIconSet &iconset ) +{ + d->m_iconSet = iconset; + d->m_iconName = QString::null; + d->m_hasIcon = !iconset.isNull(); +} + +void KGuiItem::setIconName( const QString &iconName ) +{ + d->m_iconName = iconName; + d->m_iconSet = QIconSet(); + d->m_hasIcon = !iconName.isEmpty(); +} + +void KGuiItem::setToolTip( const QString &toolTip) { + d->m_toolTip = toolTip; +} +void KGuiItem::setWhatsThis( const QString &whatsThis ) { + d->m_whatsThis = whatsThis; +} +void KGuiItem::setEnabled( bool enabled ){ + d->m_enabled = enabled; +} + +/* vim: et sw=4 + */ diff --git a/microkde/kdeui/kguiitem.h b/microkde/kdeui/kguiitem.h new file mode 100644 index 0000000..0079bb4 --- a/dev/null +++ b/microkde/kdeui/kguiitem.h @@ -0,0 +1,87 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001 Holger Freyther (freyher@yahoo.com) + based on ideas from Martijn and Simon + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Many thanks to Simon tronical Hausmann +*/ + +#ifndef __kguiitem_h__ +#define __kguiitem_h__ + +#include <qstring.h> +#include <qiconset.h> +#include <qpixmap.h> +#include <qvaluelist.h> +//US#include <kicontheme.h> +#include <kglobal.h> + +//US added the following files +#include <kiconloader.h> + +class KGuiItem +{ +public: + KGuiItem(); + + KGuiItem( const QString &text, + const QString &iconName = QString::null, + const QString &toolTip = QString::null, + const QString &whatsThis = QString::null ); + + KGuiItem( const QString &text, const QIconSet &iconSet, + const QString &toolTip = QString::null, + const QString &whatsThis = QString::null ); + + KGuiItem( const KGuiItem &rhs ); + KGuiItem &operator=( const KGuiItem &rhs ); + + ~KGuiItem(); + + QString text() const; + QString plainText() const; + QIconSet iconSet( KIcon::Group, int size = 0/*US , KInstance* instance = KGlobal::instance()*/) const; + +#ifndef KDE_NO_COMPAT + QIconSet iconSet() const { return iconSet( KIcon::Small); } +#endif + + QString iconName() const; + QString toolTip() const; + QString whatsThis() const; + bool isEnabled() const; + bool hasIcon() const; +#ifndef KDE_NO_COMPAT + bool hasIconSet() const { return hasIcon(); } +#endif + + void setText( const QString &text ); + void setIconSet( const QIconSet &iconset ); + void setIconName( const QString &iconName ); + void setToolTip( const QString &tooltip ); + void setWhatsThis( const QString &whatsThis ); + void setEnabled( bool enable ); + +private: + class KGuiItemPrivate; + KGuiItemPrivate *d; +}; + +/* vim: et sw=4 + */ + +#endif + diff --git a/microkde/kdeui/kjanuswidget.cpp b/microkde/kdeui/kjanuswidget.cpp new file mode 100644 index 0000000..7d25854 --- a/dev/null +++ b/microkde/kdeui/kjanuswidget.cpp @@ -0,0 +1,1176 @@ +/* This file is part of the KDE Libraries + * Copyright (C) 1999-2000 Espen Sand (espensa@online.no) + * Copyright (C) 2003 Ravikiran Rajagopal (ravi@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <qpixmap.h> +#include <qbitmap.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qwidgetstack.h> +#include <qtabwidget.h> +#include <qlistview.h> +#include <qhbox.h> +#include <qvbox.h> +#include <qgrid.h> +#include <qpainter.h> +#include <qobjectlist.h> + +/*US +#include <qbitmap.h> +#include <qgrid.h> +#include <qhbox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qobjectlist.h> +#include <qpixmap.h> +#include <qsplitter.h> +#include <qtabwidget.h> +#include <qvbox.h> +#include <qwidgetstack.h> +#include <qpainter.h> +#include <qstyle.h> + +#include <kapplication.h> +#include <klocale.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kseparator.h> +#include <kdebug.h> +#include "kjanuswidget.h" +#include <klistview.h> + +*/ + +#include <kseparator.h> +#include <kdialog.h> // Access to some static members +#include <kdebug.h> +#include <klistview.h> + +#include "kjanuswidget.h" + +class KJanusWidget::IconListItem : public QListBoxItem +{ + public: + IconListItem( QListBox *listbox, const QPixmap &pixmap, + const QString &text ); + virtual int height( const QListBox *lb ) const; + virtual int width( const QListBox *lb ) const; + int expandMinimumWidth( int width ); + + protected: + const QPixmap &defaultPixmap(); + void paint( QPainter *painter ); + + private: + QPixmap mPixmap; + int mMinimumWidth; +}; + +class KJanusWidget::KJanusWidgetPrivate +{ +public: + KJanusWidgetPrivate() : mNextPageIndex(0) { } + + int mNextPageIndex; // The next page index. + + // Dictionary for multipage modes. + QMap<int,QWidget*> mIntToPage; + // Reverse dictionary. Used because showPage() may be performance critical. + QMap<QWidget*,int> mPageToInt; + // Dictionary of title string associated with page. + QMap<int, QString> mIntToTitle; +}; + +template class QPtrList<QListViewItem>; + + +KJanusWidget::KJanusWidget( QWidget *parent, const char *name, int face ) + : QWidget( parent, name ), + mValid(false), mPageList(0), + mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0), + mShowIconsInTreeList(false), d(0) +{ + QVBoxLayout *topLayout = new QVBoxLayout( this ); + if( mFace == TreeList || mFace == IconList ) + { + d = new KJanusWidgetPrivate; + + QFrame *page = 0; + if( mFace == TreeList ) + { + //US + qDebug("KJanusWidget::KJanusWidget TreeList not implemented yet"); +/*US + QSplitter *splitter = new QSplitter( this ); + topLayout->addWidget( splitter, 10 ); + mTreeListResizeMode = QSplitter::KeepSize; + + mTreeList = new KListView( splitter ); + mTreeList->addColumn( QString::null ); + mTreeList->header()->hide(); + mTreeList->setRootIsDecorated(true); + mTreeList->setSorting( -1 ); + connect( mTreeList, SIGNAL(selectionChanged()), SLOT(slotShowPage()) ); + connect( mTreeList, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *))); + + // + // Page area. Title at top with a separator below and a pagestack using + // all available space at bottom. + // + QFrame *p = new QFrame( splitter ); + + QHBoxLayout *hbox = new QHBoxLayout( p, 0, 0 ); + hbox->addSpacing( KDialog::marginHint() ); + + page = new QFrame( p ); + hbox->addWidget( page, 10 ); +*/ + } + else + { + QHBoxLayout *hbox = new QHBoxLayout( topLayout ); + mIconList = new IconListBox( this ); + + QFont listFont( mIconList->font() ); + listFont.setBold( true ); + mIconList->setFont( listFont ); + + mIconList->verticalScrollBar()->installEventFilter( this ); + hbox->addWidget( mIconList ); + connect( mIconList, SIGNAL(selectionChanged()), SLOT(slotShowPage())); + hbox->addSpacing( KDialog::marginHint() ); + page = new QFrame( this ); + hbox->addWidget( page, 10 ); + } + + // + // Rest of page area. Title at top with a separator below and a + // pagestack using all available space at bottom. + // + + QVBoxLayout *vbox = new QVBoxLayout( page, 0, KDialog::spacingHint() ); + + mTitleLabel = new QLabel( QString::fromLatin1("Empty page"), page, "KJanusWidgetTitleLabel" ); + vbox->addWidget( mTitleLabel ); + + QFont titleFont( mTitleLabel->font() ); + titleFont.setBold( true ); + mTitleLabel->setFont( titleFont ); + + mTitleSep = new KSeparator( page ); + mTitleSep->setFrameStyle( QFrame::HLine|QFrame::Plain ); + vbox->addWidget( mTitleSep ); + + mPageStack = new QWidgetStack( page ); + connect(mPageStack, SIGNAL(aboutToShow(QWidget *)), + SIGNAL(aboutToShowPage(QWidget *))); + vbox->addWidget( mPageStack, 10 ); + } + else if( mFace == Tabbed ) + { + d = new KJanusWidgetPrivate; + + mTabControl = new QTabWidget( this ); + mTabControl->setMargin (KDialog::marginHint()); + topLayout->addWidget( mTabControl, 10 ); + } + else if( mFace == Swallow ) + { + mSwallowPage = new QWidget( this ); + topLayout->addWidget( mSwallowPage, 10 ); + } + else + { + mFace = Plain; + mPlainPage = new QFrame( this ); + topLayout->addWidget( mPlainPage, 10 ); + } +/*US + if ( kapp ) + connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged())); +*/ + mValid = true; + setSwallowedWidget(0); // Set default size if 'mFace' is Swallow. +} + + +KJanusWidget::~KJanusWidget() +{ + +/*US the destroyed signal caused a segmentation fault while closing the dialog and destructing + all pages. Why not just remove all pages in the destructor?? +*/ +// LR we have all subwidgets with parent-child relation +// LR we do not need to delete here anything by the private class +/* + if( mFace == Tabbed ) + { + QMap<QWidget*,int>::Iterator it; + for (it = d->mPageToInt.begin(); it != d->mPageToInt.end(); ++it) { + QObject*page = (QObject*)it.key(); + pageGone(page); + } + } + else + qDebug("KJanusWidget::~KJanusWidget so far "); +*/ +//US end + + delete d; + + +} + + +bool KJanusWidget::isValid() const +{ + return( mValid ); +} + + +QFrame *KJanusWidget::plainPage() +{ + return( mPlainPage ); +} + + +int KJanusWidget::face() const +{ + return( mFace ); +} + +QWidget *KJanusWidget::FindParent() +{ + if( mFace == Tabbed ) { + return mTabControl; + } + else { + return this; + } +} + +QFrame *KJanusWidget::addPage( const QStringList &items, const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) + { + kdDebug() << "addPage: Invalid object" << endl; + return( 0 ); + } + + QFrame *page = new QFrame( FindParent(), "page" ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +void KJanusWidget::pageGone( QObject *obj ) +{ +// QObject* obj = (QObject*)sender(); + removePage( static_cast<QWidget*>( obj ) ); +} + +void KJanusWidget::slotReopen( QListViewItem * item ) +{ + if( item ) + item->setOpen( true ); +} + +QFrame *KJanusWidget::addPage( const QString &itemName, const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addPage(items, header, pixmap); +} + + + +QVBox *KJanusWidget::addVBoxPage( const QStringList &items, + const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) + { + qDebug("addPage: Invalid object "); + + return( 0 ); + } + + QVBox *page = new QVBox(FindParent() , "vbox_page" ); + page->setSpacing( KDialog::spacingHintSmall() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +QVBox *KJanusWidget::addVBoxPage( const QString &itemName, + const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addVBoxPage(items, header, pixmap); +} + +QHBox *KJanusWidget::addHBoxPage( const QStringList &items, + const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) { + kdDebug() << "addPage: Invalid object" << endl; + return( 0 ); + } + + QHBox *page = new QHBox(FindParent(), "hbox_page"); + page->setSpacing( KDialog::spacingHint() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +QHBox *KJanusWidget::addHBoxPage( const QString &itemName, + const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addHBoxPage(items, header, pixmap); +} + +QGrid *KJanusWidget::addGridPage( int n, QGrid::Direction dir, + const QStringList &items, + const QString &header, + const QPixmap &pixmap ) +{ + if( mValid == false ) + { + kdDebug() << "addPage: Invalid object" << endl; + return( 0 ); + } + + QGrid *page = new QGrid( n, dir, FindParent(), "page" ); + page->setSpacing( KDialog::spacingHint() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + + +QGrid *KJanusWidget::addGridPage( int n, QGrid::Direction dir, + const QString &itemName, + const QString &header, + const QPixmap &pixmap ) +{ + QStringList items; + items << itemName; + return addGridPage(n, dir, items, header, pixmap); +} + +void KJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page) +{ + bool isTop = true; + QListViewItem *curTop = 0, *child, *last, *newChild; + unsigned int index = 1; + QStringList curPath; + + for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) { + QString name = (*it); + bool isPath = ( index != items.count() ); + + // Find the first child. + if (isTop) { + child = mTreeList->firstChild(); + } + else { + child = curTop->firstChild(); + } + + // Now search for a child with the current Name, and if it we doesn't + // find it, then remember the location of the last child. + for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling()); + + if (last == 0 && child == 0) { + // This node didn't have any children at all, lets just insert the + // new child. + if (isTop) + newChild = new QListViewItem(mTreeList, name); + else + newChild = new QListViewItem(curTop, name); + + } + else if (child != 0) { + // we found the given name in this child. + if (!isPath) { + kdDebug() << "The element inserted was already in the TreeList box!" << endl; + return; + } + else { + // Ok we found the folder + newChild = child; + } + } + else { + // the node had some children, but we didn't find the given name + if (isTop) + newChild = new QListViewItem(mTreeList, last, name); + else + newChild = new QListViewItem(curTop, last, name); + } + + // Now make the element expandable if it is a path component, and make + // ready for next loop + if (isPath) { + newChild->setExpandable(true); + curTop = newChild; + isTop = false; + curPath << name; + + QString key = curPath.join("_/_"); + if (mFolderIconMap.contains(key)) { + QPixmap p = mFolderIconMap[key]; + newChild->setPixmap(0,p); + } + } + else { + if (mShowIconsInTreeList) { + newChild->setPixmap(0, pixmap); + } + mTreeListToPageStack.insert(newChild, page); + } + } +} + +void KJanusWidget::addPageWidget( QFrame *page, const QStringList &items, + const QString &header,const QPixmap &pixmap ) +{ +/*US the following signal causes a segmentation fault while closing the dialog. + Why not just remove all pages in the destructor?? +*/ +//US connect(page, SIGNAL(destroyed(QObject*)), this, SLOT(pageGone(QObject*))); +// we have the SIGNAL(destroyed(QObject*) only in Qt3 +#ifdef DESKTOP_VERSION + // connect(page, SIGNAL(destroyed(QObject*)), this, SLOT(pageGone(QObject*))); +#endif + if( mFace == Tabbed ) + { + mTabControl->addTab (page, items.last()); + d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page); + d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex; + d->mNextPageIndex++; + } + else if( mFace == TreeList || mFace == IconList ) + { + d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page); + d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex; + mPageStack->addWidget( page, 0 ); + + if (items.count() == 0) { + kdDebug() << "Invalid QStringList, with zero items" << endl; + return; + } + + if( mFace == TreeList ) + { + InsertTreeListItem(items, pixmap, page); + } + else // mFace == IconList + { + QString itemName = items.last(); + IconListItem *item = new IconListItem( mIconList, pixmap, itemName ); + mIconListToPageStack.insert(item, page); + mIconList->invalidateHeight(); + mIconList->invalidateWidth(); + + if (mIconList->isVisible()) + mIconList->updateWidth(); + } + + // + // Make sure the title label is sufficiently wide + // + QString lastName = items.last(); + const QString &title = (!header.isNull() ? header : lastName); + QRect r = mTitleLabel->fontMetrics().boundingRect( title ); + if( mTitleLabel->minimumWidth() < r.width() ) + { + mTitleLabel->setMinimumWidth( r.width() ); + } + d->mIntToTitle[d->mNextPageIndex] = title; + if( d->mIntToTitle.count() == 1 ) + { + showPage(0); + } + d->mNextPageIndex++; + } + else + { + kdDebug() << "KJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" << endl; + } + +} + +void KJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap) +{ + QString key = path.join("_/_"); + mFolderIconMap.insert(key,pixmap); +} + + + +bool KJanusWidget::setSwallowedWidget( QWidget *widget ) +{ + if( mFace != Swallow || mValid == false ) + { + return( false ); + } + + // + // Remove current layout and make a new. + // + if( mSwallowPage->layout() != 0 ) + { + delete mSwallowPage->layout(); + } + QGridLayout *gbox = new QGridLayout( mSwallowPage, 1, 1, 0 ); + + // + // Hide old children + // + QObjectList *l = (QObjectList*)mSwallowPage->children(); // silence please + for( uint i=0; i < l->count(); i++ ) + { + QObject *o = l->at(i); + if( o->isWidgetType() ) + { + ((QWidget*)o)->hide(); + } + } + + // + // Add new child or make default size + // + if( widget == 0 ) + { + gbox->addRowSpacing(0,100); + gbox->addColSpacing(0,100); + mSwallowPage->setMinimumSize(100,100); + } + else + { + if( widget->parent() != mSwallowPage ) + { + widget->reparent( mSwallowPage, 0, QPoint(0,0) ); + } + gbox->addWidget(widget, 0, 0 ); + gbox->activate(); + mSwallowPage->setMinimumSize( widget->minimumSize() ); + } + + return( true ); +} + +bool KJanusWidget::slotShowPage() +{ + if( mValid == false ) + { + return( false ); + } + + if( mFace == TreeList ) + { + QListViewItem *node = mTreeList->selectedItem(); + if( node == 0 ) { return( false ); } + + QWidget *stackItem = mTreeListToPageStack[node]; + // Make sure to call through the virtual function showPage(int) + return showPage(d->mPageToInt[stackItem]); + } + else if( mFace == IconList ) + { + QListBoxItem *node = mIconList->item( mIconList->currentItem() ); + if( node == 0 ) { return( false ); } + QWidget *stackItem = mIconListToPageStack[node]; + // Make sure to call through the virtual function showPage(int) + return showPage(d->mPageToInt[stackItem]); + } + + return( false ); +} + + +bool KJanusWidget::showPage( int index ) +{ + if( d == 0 || mValid == false ) + { + return( false ); + } + else + { + return showPage(d->mIntToPage[index]); + } +} + + +bool KJanusWidget::showPage( QWidget *w ) +{ + if( w == 0 || mValid == false ) + { + return( false ); + } + + if( mFace == TreeList || mFace == IconList ) + { + mPageStack->raiseWidget( w ); + mActivePageWidget = w; + + int index = d->mPageToInt[w]; + mTitleLabel->setText( d->mIntToTitle[index] ); + if( mFace == TreeList ) + { + QMap<QListViewItem *, QWidget *>::Iterator it; + for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){ + QListViewItem *key = it.key(); + QWidget *val = it.data(); + if (val == w) { + mTreeList->setSelected(key, true ); + break; + } + } + } + else + { + QMap<QListBoxItem *, QWidget *>::Iterator it; + for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){ + QListBoxItem *key = it.key(); + QWidget *val = it.data(); + if (val == w) { + mIconList->setSelected( key, true ); + break; + } + } + } + } + else if( mFace == Tabbed ) + { + mTabControl->showPage(w); + mActivePageWidget = w; + } + else + { + return( false ); + } + + return( true ); +} + + +int KJanusWidget::activePageIndex() const +{ + if( mFace == TreeList) { + QListViewItem *node = mTreeList->selectedItem(); + if( node == 0 ) { return -1; } + QWidget *stackItem = mTreeListToPageStack[node]; + return d->mPageToInt[stackItem]; + } + else if (mFace == IconList) { + QListBoxItem *node = mIconList->item( mIconList->currentItem() ); + if( node == 0 ) { return( false ); } + QWidget *stackItem = mIconListToPageStack[node]; + return d->mPageToInt[stackItem]; + } + else if( mFace == Tabbed ) { + QWidget *widget = mTabControl->currentPage(); + return( widget == 0 ? -1 : d->mPageToInt[widget] ); + } + else { + return( -1 ); + } +} + + +int KJanusWidget::pageIndex( QWidget *widget ) const +{ + if( widget == 0 ) + { + return( -1 ); + } + else if( mFace == TreeList || mFace == IconList ) + { + return( d->mPageToInt[widget] ); + } + else if( mFace == Tabbed ) + { + // + // The user gets the real page widget with addVBoxPage(), addHBoxPage() + // and addGridPage() but not with addPage() which returns a child of + // the toplevel page. addPage() returns a QFrame so I check for that. + // + if( widget->isA("QFrame") ) + { + return( d->mPageToInt[widget->parentWidget()] ); + } + else + { + return( d->mPageToInt[widget] ); + } + } + else + { + return( -1 ); + } +} +/*US not yet implemented +void KJanusWidget::slotFontChanged() +{ + if( mTitleLabel != 0 ) + { + mTitleLabel->setFont( KGlobalSettings::generalFont() ); + QFont titleFont( mTitleLabel->font() ); + titleFont.setBold( true ); + mTitleLabel->setFont( titleFont ); + } + + if( mFace == IconList ) + { + QFont listFont( mIconList->font() ); + listFont.setBold( true ); + mIconList->setFont( listFont ); + mIconList->invalidateHeight(); + mIconList->invalidateWidth(); + } +} +*/ + +// makes the treelist behave like the list of kcontrol +void KJanusWidget::slotItemClicked(QListViewItem *it) +{ + if(it && (it->childCount()>0)) + it->setOpen(!it->isOpen()); +} + +void KJanusWidget::setFocus() +{ + if( mValid == false ) { return; } + if( mFace == TreeList ) + { + mTreeList->setFocus(); + } + if( mFace == IconList ) + { + mIconList->setFocus(); + } + else if( mFace == Tabbed ) + { + mTabControl->setFocus(); + } + else if( mFace == Swallow ) + { + mSwallowPage->setFocus(); + } + else if( mFace == Plain ) + { + mPlainPage->setFocus(); + } +} + + +QSize KJanusWidget::minimumSizeHint() const +{ + if( mFace == TreeList || mFace == IconList ) + { + QSize s1( KDialog::spacingHint(), KDialog::spacingHint()*2 ); + QSize s2(0,0); + QSize s3(0,0); + QSize s4( mPageStack->sizeHint() ); + + if( mFace == TreeList ) + { +/*US + s1.rwidth() += style().pixelMetric( QStyle::PM_SplitterWidth ); + s2 = mTreeList->minimumSize(); +*/ + } + else + { + mIconList->updateMinimumHeight(); + mIconList->updateWidth(); + s2 = mIconList->minimumSize(); + } + + if( mTitleLabel->isVisible() == true ) + { + s3 += mTitleLabel->sizeHint(); + s3.rheight() += mTitleSep->minimumSize().height(); + } + + // + // Select the tallest item. It has only effect in IconList mode + // + int h1 = s1.rheight() + s3.rheight() + s4.height(); + int h2 = QMAX( h1, s2.rheight() ); + + return( QSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 ) ); + } + else if( mFace == Tabbed ) + { + return( mTabControl->sizeHint() ); + } + else if( mFace == Swallow ) + { + return( mSwallowPage->minimumSize() ); + } + else if( mFace == Plain ) + { + return( mPlainPage->sizeHint() ); + } + else + { + return( QSize( 100, 100 ) ); // Should never happen though. + } + +} + + +QSize KJanusWidget::sizeHint() const +{ + return( minimumSizeHint() ); +} + + +void KJanusWidget::setTreeListAutoResize( bool state ) +{ + if( mFace == TreeList ) + { +/*US + mTreeListResizeMode = state == false ? + QSplitter::KeepSize : QSplitter::Stretch; + QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget()); + splitter->setResizeMode( mTreeList, mTreeListResizeMode ); +*/ + } +} + + +void KJanusWidget::setIconListAllVisible( bool state ) +{ + if( mFace == IconList ) + { + mIconList->setShowAll( state ); + } +} + +void KJanusWidget::setShowIconsInTreeList( bool state ) +{ + mShowIconsInTreeList = state; +} + +void KJanusWidget::setRootIsDecorated( bool state ) +{ + if( mFace == TreeList ) { + mTreeList->setRootIsDecorated(state); + } +} + +void KJanusWidget::unfoldTreeList( bool persist ) +{ + if( mFace == TreeList ) + { + if( persist ) + connect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) ); + else + disconnect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) ); + + for( QListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() ) + item->setOpen( true ); + } +} + +void KJanusWidget::showEvent( QShowEvent * ) +{ + if( mFace == TreeList ) + { +/*US + QSplitter *splitter = (QSplitter*)(mTreeList->parentWidget()); + splitter->setResizeMode( mTreeList, mTreeListResizeMode ); +*/ + } +} + + +// +// 2000-13-02 Espen Sand +// It should be obvious that this eventfilter must only be +// be installed on the vertical scrollbar of the mIconList. +// +bool KJanusWidget::eventFilter( QObject *o, QEvent *e ) +{ + if( e->type() == QEvent::Show ) + { + IconListItem *item = (IconListItem*)mIconList->item(0); + if( item != 0 ) + { + int lw = item->width( mIconList ); + int sw = mIconList->verticalScrollBar()->sizeHint().width(); + mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 ); + } + } + else if( e->type() == QEvent::Hide ) + { + IconListItem *item = (IconListItem*)mIconList->item(0); + if( item != 0 ) + { + int lw = item->width( mIconList ); + mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 ); + } + } + return QWidget::eventFilter( o, e ); +} + + + +// +// Code for the icon list box +// + + +KJanusWidget::IconListBox::IconListBox( QWidget *parent, const char *name, + WFlags f ) + :KListBox( parent, name, f ), mShowAll(false), mHeightValid(false), + mWidthValid(false) +{ +} + + +void KJanusWidget::IconListBox::updateMinimumHeight() +{ + if( mShowAll == true && mHeightValid == false ) + { + int h = frameWidth()*2; + for( QListBoxItem *i = item(0); i != 0; i = i->next() ) + { + h += i->height( this ); + } + setMinimumHeight( h ); + mHeightValid = true; + } +} + + +void KJanusWidget::IconListBox::updateWidth() +{ + if( mWidthValid == false ) + { + int maxWidth = 10; + for( QListBoxItem *i = item(0); i != 0; i = i->next() ) + { + int w = ((IconListItem *)i)->width(this); + maxWidth = QMAX( w, maxWidth ); + } + + for( QListBoxItem *i = item(0); i != 0; i = i->next() ) + { + ((IconListItem *)i)->expandMinimumWidth( maxWidth ); + } + + if( verticalScrollBar()->isVisible() ) + { + maxWidth += verticalScrollBar()->sizeHint().width(); + } + + setFixedWidth( maxWidth + frameWidth()*2 ); + mWidthValid = true; + } +} + + +void KJanusWidget::IconListBox::invalidateHeight() +{ + mHeightValid = false; +} + + +void KJanusWidget::IconListBox::invalidateWidth() +{ + mWidthValid = false; +} + + +void KJanusWidget::IconListBox::setShowAll( bool showAll ) +{ + mShowAll = showAll; + mHeightValid = false; +} + + + +KJanusWidget::IconListItem::IconListItem( QListBox *listbox, const QPixmap &pixmap, + const QString &text ) + : QListBoxItem( listbox ) +{ + mPixmap = pixmap; + if( mPixmap.isNull() == true ) + { + mPixmap = defaultPixmap(); + } + setText( text ); + mMinimumWidth = 0; +} + + +int KJanusWidget::IconListItem::expandMinimumWidth( int width ) +{ + mMinimumWidth = QMAX( mMinimumWidth, width ); + return( mMinimumWidth ); +} + + +const QPixmap &KJanusWidget::IconListItem::defaultPixmap() +{ + static QPixmap *pix=0; + if( pix == 0 ) + { + pix = new QPixmap( 32, 32 ); + QPainter p( pix ); + p.eraseRect( 0, 0, pix->width(), pix->height() ); + p.setPen( Qt::red ); + p.drawRect ( 0, 0, pix->width(), pix->height() ); + p.end(); + + QBitmap mask( pix->width(), pix->height(), true); + mask.fill( Qt::black ); + p.begin( &mask ); + p.setPen( Qt::white ); + p.drawRect ( 0, 0, pix->width(), pix->height() ); + p.end(); + + pix->setMask( mask ); + } + return( *pix ); +} + + +void KJanusWidget::IconListItem::paint( QPainter *painter ) +{ + QFontMetrics fm = painter->fontMetrics(); + //int wt = fm.boundingRect(text()).width(); + int wp = mPixmap.width(); + int ht = fm.lineSpacing(); + int hp = mPixmap.height(); + + painter->drawPixmap( (mMinimumWidth-wp)/2, 5, mPixmap ); + if( text().isEmpty() == false ) + { + painter->drawText( 0, hp+7, mMinimumWidth, ht, Qt::AlignCenter, text() ); + } +} + +int KJanusWidget::IconListItem::height( const QListBox *lb ) const +{ + if( text().isEmpty() == true ) + { + return( mPixmap.height() ); + } + else + { + return( mPixmap.height() + lb->fontMetrics().lineSpacing()+10 ); + } +} + + +int KJanusWidget::IconListItem::width( const QListBox *lb ) const +{ + int wt = lb->fontMetrics().boundingRect(text()).width()+10; + int wp = mPixmap.width() + 10; + int w = QMAX( wt, wp ); + return( QMAX( w, mMinimumWidth ) ); +} + + +void KJanusWidget::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +// TODO: In TreeList, if the last child of a node is removed, and there is no corrsponding widget for that node, allow the caller to +// delete the node. +void KJanusWidget::removePage( QWidget *page ) +{ +//US qDebug("KJanusWidget::removePage 1 %lu , %lu, %lu", d, page, &(d->mPageToInt)); + if (!d || !(d->mPageToInt.contains(page))) + { + return; + } + + int index = d->mPageToInt[page]; + + if ( mFace == TreeList ) + { + QMap<QListViewItem*, QWidget *>::Iterator i; + for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i ) + if (i.data()==page) + { + delete i.key(); + mPageStack->removeWidget(page); + mTreeListToPageStack.remove(i); + d->mIntToTitle.remove(index); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + break; + } + } + else if ( mFace == IconList ) + { + QMap<QListBoxItem*, QWidget *>::Iterator i; + for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i ) + if (i.data()==page) + { + delete i.key(); + mPageStack->removeWidget(page); + mIconListToPageStack.remove(i); + d->mIntToTitle.remove(index); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + break; + } + } + else // Tabbed + { + mTabControl->removePage(page); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + } +} + +QString KJanusWidget::pageTitle(int index) const +{ + if (!d || !d->mIntToTitle.contains(index)) + return QString::null; + else + return d->mIntToTitle[index]; +} + +QWidget *KJanusWidget::pageWidget(int index) const +{ + if (!d || !d->mIntToPage.contains(index)) + return 0; + else + return d->mIntToPage[index]; +} + +//US #include "kjanuswidget.moc" diff --git a/microkde/kdeui/kjanuswidget.h b/microkde/kdeui/kjanuswidget.h new file mode 100644 index 0000000..6d3f23d --- a/dev/null +++ b/microkde/kdeui/kjanuswidget.h @@ -0,0 +1,565 @@ +/* This file is part of the KDE Libraries + * Copyright (C) 1999-2000 Espen Sand (espen@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _KJANUS_WIDGET_H_ +#define _KJANUS_WIDGET_H_ + +#include <qptrlist.h> +#include <qwidget.h> +#include <qmap.h> +#include <qgrid.h> +#include <klistbox.h> + +/*US +#include <qptrlist.h> +#include <qpixmap.h> +#include <qsplitter.h> + +#include <qstringlist.h> +#include <qmap.h> + +*/ + +class KSeparator; +class KListView; +class QWidgetStack; +class QLabel; +class QTabWidget; +class QListViewItem; +class QVBox; +class QHBox; + +/** + * Provides a number of ready to use layouts (faces). It is used + * as an internal widget in @ref KDialogBase, but can also used as a + * widget of its own. + * + * It provides TreeList, IconList, Tabbed, Plain and Swallow layouts. + * + * The TreeList face provides a list in the left area and pages in the + * right. The area are separated by a movable splitter. The style is somewhat + * similar to the layout in the Control Center. A page is raised by + * selecting the corresponding tree list item. + * + * The IconList face provides an icon list in the left area and pages in the + * right. For each entry the Icon is on top with the text below. The style + * is somewhat similar to the layout of the Eudora configuation dialog box. + * A page is raised by selecting the corresponding icon list item. The + * preferred icon size is 32x32 pixels. + * + * The Tabbed face is a common tabbed widget. The procedure for creating a + * page is similar for creating a TreeList. This has the advantage that if + * your widget contain too many pages it is trivial to convert it into a + * TreeList. Just change the face in the KJanusWidget constructor to + * KJanusWidget::TreeList and you have a tree list layout instead. + * + * The Plain face provides an empty widget (QFrame) where you can place your + * widgets. The KJanusWidget makes no assumptions regarding the contents so + * you are free to add whatever you want. + * + * The Swallow face is provided in order to simplify the usage of existing + * widgets and to allow changing the visible widget. You specify the widget + * to be displayed by @ref #setSwallowedWidget(). Your widget will be + * reparented inside the widget. You can specify a Null (0) widget. A empty + * space is then displayed. + * + * For all modes it is important that you specify the @ref QWidget::minimumSize() + * on the page, plain widget or the swallowed widget. If you use a QLayout + * on the page, plain widget or the swallowed widget this will be taken care + * of automatically. The size is used when the KJanusWidget determines its + * own minimum size. You get the minimum size by using the + * @ref #minimumSizeHint() or @ref #sizeHint() methods. + * + * Pages that have been added in TreeList, IconList or Tabbed mode can be + * removed by simply deleting the page. However, it would be preferable to use + * the QObject::deleteLater() function on the page as the main event loop + * may have optimized UI update events of the page by scheduling them for later. + * + * @short Easy to use widget with many layouts + * @author Espen Sand (espen@kde.org) + */ +class KJanusWidget : public QWidget +{ + Q_OBJECT + + private: + class IconListBox : public KListBox + { + public: + IconListBox( QWidget *parent=0, const char *name=0, WFlags f=0 ); + void updateMinimumHeight(); + void updateWidth(); + void invalidateHeight(); + void invalidateWidth(); + void setShowAll( bool showAll ); + + private: + bool mShowAll; + bool mHeightValid; + bool mWidthValid; + }; + + public: + enum Face + { + TreeList = 0, + Tabbed, + Plain, + Swallow, + IconList + }; + + public: + + /** + * Constructor where you specify the face. + * + * @param parent Parent of the widget. + * @param name Widget name. + * @param int face The kind of dialog, Use TreeList, Tabbed, Plain or + * Swallow. + */ + KJanusWidget( QWidget *parent=0, const char *name=0, int face=Plain ); + + /** + * Destructor. + */ + ~KJanusWidget(); + + /** + * Raises the page which was added by @ref addPage(). + * + * @param index The index of the page you want to raise. + */ + virtual bool showPage( int index ); + + /** + * Returns the index of the page that are currently displayed. + * + * @return The index or -1 if the face is not Tabbed, TreeList or + * IconList. + */ + virtual int activePageIndex() const; + + /** + * Use this to verify + * that no memory allocation failed. + * + * @return true if the widget was properly created. + */ + virtual bool isValid() const; + + /** + * Returns the face type. + * + * @return The face type. + */ + virtual int face() const; + + /** + * Returns the minimum size that must be made available for the widget + * so that UIs can be displayed properly + * + * @return The minimum size. + */ + virtual QSize minimumSizeHint() const; + + /** + * Returns the recommended size for the widget in order to be displayed + * properly. + * + * @return The recommended size. + */ + virtual QSize sizeHint() const; + + /** + * Returns the empty widget that is available in Plain mode. + * + * @return The widget or 0 if the face in not Plain. + */ + virtual QFrame *plainPage(); + + /** + * Add a new page when the class is used in TreeList, IconList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. In most cases you must create a layout + * manager and associate it with this widget as well. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. + */ + virtual QFrame *addPage(const QString &item,const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ + virtual QFrame *addPage(const QStringList &items, const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * Add a new page when the class is used in TreeList, IconList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. The returned widget is a @ref QVBox + * so it contains a QVBoxLayout layout that lines up the child widgets + * are vertically. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. */ + virtual QVBox *addVBoxPage( const QString &item, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addVBoxPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ + virtual QVBox *addVBoxPage( const QStringList &items, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * Add a new page when the class is used in TreeList, IconList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. The returned widget is a @ref QHBox + * so it contains a QHBoxLayout layout that lines up the child widgets + * are horizontally. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. + */ + virtual QHBox *addHBoxPage( const QString &itemName, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addHBoxPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ + virtual QHBox *addHBoxPage( const QStringList &items, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * Add a new page when the class is used in either TreeList or Tabbed + * mode. The returned widget is empty and you must add your widgets + * as children to this widget. The returned widget is a @ref QGrid + * so it contains a QGridLayout layout that places up the child widgets + * in a grid. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + * + * @param n Specifies the number of columns if 'dir' is QGrid::Horizontal + * or the number of rows if 'dir' is QGrid::Vertical. + * @param dir Can be QGrid::Horizontal or QGrid::Vertical. + * @param item String used in the list or Tab item. + * @param header A longer string used in TreeList and IconList mode to + * describe the contents of a page. If empty, the item string + * will be used instead. + * @param pixmap Used in IconList mode or in TreeList mode. You should + * prefer a pixmap with size 32x32 pixels. + * + * @return The empty page or 0 if the face is not TreeList, IconList or + * Tabbed. + */ +//US changed Orientation into Direction for compatibility + virtual QGrid *addGridPage( int n, QGrid::Direction dir, + const QString &itemName, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * This is like addGridPage just above, with the difference that the first + * element is a list of strings. These strings are used to form a path + * of folders down to the given page. The initial elements are names + * for the folders, while the last element is the name of the page. + * Note: This does yet only work for the TreeList face. Later this may + * be added for the IconList face too. In other faces than the + * TreeList, all the strings except the last one is ignored. + * + * Deleting the returned frame will cause the listitem or tab to be + * removed (you can re-add a page with the same name later. + **/ +//US changed Orientation into Direction for compatibility + virtual QGrid *addGridPage( int n, QGrid::Direction dir, + const QStringList &items, + const QString &header=QString::null, + const QPixmap &pixmap=QPixmap() ); + + /** + * @short Removes a page created with @ref addPage, @ref addVBoxPage, + * @ref addHBoxPage or @ref addGridPage. If the page has already + * been deleted or has already been removed, nothing happens. The widget + * itself is not deleted. + * + * @param page The widget returned by @ref addPage , @ref addVBoxPage , + * @ref addHBoxPage or @ref addGridPage . + */ + void removePage( QWidget *page ); + + + /** + * Returns the index of a page created with @ref addPage , + * @ref addVBoxPage , @ref addHBoxPage or @ref addGridPage . + * You can can compare this index with the value returned from + * @ref activePageIndex if you need to do some page specific actions + * in your code. + * + * The returned index will never change so you can safely use this + * function once and save the value. + * + * @param widget The widget returned by @ref addPage , @ref addVBoxPage , + * @ref addHBoxPage or @ref addGridPage . + * + * @return The index or -1 if the face is not Tabbed, TreeList or + * IconList + */ + virtual int pageIndex( QWidget *widget ) const; + + /** + * Defines the widget to be swallowed. + * + * This method can be used several + * times. Only the latest defined widget will be shown. + * + * @param widget The widget to be swallowed. If 0, then an empty rectangle + * is displayed. + */ + virtual bool setSwallowedWidget( QWidget *widget ); + + /** + * This function has only effect in TreeList mode. + * + * Defines how the tree list is resized when the widget is resized + * horizontally. By default the tree list keeps its width when the + * widget becomes wider. + * + * @param state The resize mode. If false (default) the TreeList keeps + * its current width when the widget becomes wider. + */ + virtual void setTreeListAutoResize( bool state ); + + /** + * This function has only effect in TreeList mode. + * + * This tells the widgets whether the icons given in the @ref addPage, + * @ref addVBoxPage, @ref addHBoxPage, or @ref addGridPage methods should + * be shown in the TreeList. + * + * Note: This method must be called before calling any of the methods + * which add icons to the page. + * + * @param state If true the icons are shown. + **/ + virtual void setShowIconsInTreeList(bool state); + + /** + * This function has only effect in TreeList mode. + * + * This tells the widgets whether the root should be decorated. + * For details see @ref QListView::setRootIsDecorated + * + * @param state Root will be decorated if true. + **/ + virtual void setRootIsDecorated( bool state ); + + /** + * This function has only effect in TreeList mode. + * + * This tells the TreeList to unfold the whole tree so that all entries + * are visible. + * + * If the list is empty when you call this method newly created entries + * will not automatically be opened. If the @p persist flag is set opened + * entries cannot be closed again, though. + * + * @param persist If true the tree always stays unfolded. + * @since 3.2 + */ + /*virtual*/ void unfoldTreeList( bool persist = false ); //### KDE4 BIC add virtual + + /** + * This function has only effect in IconList mode. + * + * Defines how the icon list widget is displayed. By default it is + * the widgets in the pages that decide the minimum height + * of the toplevel widget. A vertical scrollbar can be used in + * the icon list area. + * + * @param state The visibility mode. If true, the minimum height is + * adjusted so that every icon in the list is visible at the + * same time. The vertical scrollbar will never be visible. + */ + virtual void setIconListAllVisible( bool state ); + + /** + * Sets the icon used in TreeList Mode for the given path. + * @param path The path for which this icon should be shown. + * @param pixmap The icon used. + **/ + virtual void setFolderIcon(const QStringList &path, const QPixmap &pixmap); + /** + * Returns the title string associated with a page index in TreeList or IconList mode. + * @param index The index of the page or null if there is no such page. + * @see @ref #pageIndex() + * @since 3.2 + */ + /*virtual*/ QString pageTitle(int index) const; + /** + * Returns the page widget associated with a page index or null if there is + * no such page. + * @param index The index of the page. + * @see @ref #pageIndex() + * @since 3.2 + */ + /*virtual*/ QWidget *pageWidget(int index) const; + + signals: + void aboutToShowPage(QWidget *page); + + public slots: + /** + * Give the keyboard input focus to the widget. + */ + virtual void setFocus(); + + protected: + /** + * Reimplemented to handle the splitter width when the the face + * is TreeList + */ + virtual void showEvent( QShowEvent * ); + + /** + * This function is used internally when in IconList mode. If you + * reimplement this class a make your own event filter, make sure to + * call this function from your filter. + * + * @param o Object that has received an event. + * @param e The event. + */ + virtual bool eventFilter( QObject *o, QEvent *e ); + + private slots: + bool slotShowPage(); +//US not yet implemented void slotFontChanged(); + void slotItemClicked(QListViewItem *it); + void pageGone( QObject *obj); // signal from the added page's "destroyed" signal + void slotReopen(QListViewItem *item); + + protected: + bool showPage( QWidget *w ); + void addPageWidget( QFrame *page, const QStringList &items, + const QString &header, const QPixmap &pixmap ); + void InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page); + QWidget *FindParent(); + + private: + bool mValid; + + // Obsolete members. Remove in KDE 4. + QPtrList<QWidget> *mPageList; + QStringList *mTitleList; + + int mFace; + KListView *mTreeList; + IconListBox *mIconList; + QWidgetStack *mPageStack; + QLabel *mTitleLabel; + QTabWidget *mTabControl; + QFrame *mPlainPage; + QWidget *mSwallowPage; + QWidget *mActivePageWidget; + KSeparator *mTitleSep; +//US QSplitter::ResizeMode mTreeListResizeMode; + bool mShowIconsInTreeList; + QMap<QListViewItem *, QWidget *> mTreeListToPageStack; + QMap<QListBoxItem *, QWidget *> mIconListToPageStack; + QMap<QString, QPixmap> mFolderIconMap; + QMap<QString, QStringList> mChildrenNames; + QMap<QString, QWidget *> mChildPages; + + public: + class IconListItem; + protected: + virtual void virtual_hook( int id, void* data ); + private: + class KJanusWidgetPrivate; + KJanusWidgetPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/klistbox.cpp b/microkde/kdeui/klistbox.cpp new file mode 100644 index 0000000..c65b892 --- a/dev/null +++ b/microkde/kdeui/klistbox.cpp @@ -0,0 +1,314 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#include <qtimer.h> + +#include <kglobalsettings.h> +//US#include <kcursor.h> +#include <kapplication.h> +//US#include <kipc.h> +#include <kdebug.h> + +#include "klistbox.h" + +#ifdef Q_WS_X11 +#include <X11/Xlib.h> +#endif +#ifdef _WIN32_ +#define Q_WS_QWS +#endif +KListBox::KListBox( QWidget *parent, const char *name, WFlags f ) + : QListBox( parent, name, f ) +{ + connect( this, SIGNAL( onViewport() ), + this, SLOT( slotOnViewport() ) ); + connect( this, SIGNAL( onItem( QListBoxItem * ) ), + this, SLOT( slotOnItem( QListBoxItem * ) ) ); + + connect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ), + this, SLOT( slotMouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ) ); +/*US + + slotSettingsChanged(KApplication::SETTINGS_MOUSE); + if (kapp) + { + connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) ); + kapp->addKipcEventMask( KIPC::SettingsChanged ); + } +*/ + m_pCurrentItem = 0L; +//US set single to true + m_bUseSingle = true; + m_pAutoSelect = new QTimer( this ); + connect( m_pAutoSelect, SIGNAL( timeout() ), + this, SLOT( slotAutoSelect() ) ); +} + +void KListBox::slotOnItem( QListBoxItem *item ) +{ +/*US + if ( item && m_bChangeCursorOverItem && m_bUseSingle ) + viewport()->setCursor( KCursor().handCursor() ); +*/ + if ( item && (m_autoSelectDelay > -1) && m_bUseSingle ) { + m_pAutoSelect->start( m_autoSelectDelay, true ); + m_pCurrentItem = item; + } +} + +void KListBox::slotOnViewport() +{ +/*US + if ( m_bChangeCursorOverItem ) + viewport()->unsetCursor(); +*/ + m_pAutoSelect->stop(); + m_pCurrentItem = 0L; +} + + +/*US +void KListBox::slotSettingsChanged(int category) +{ + if (category != KApplication::SETTINGS_MOUSE) + return; + + m_bUseSingle = KGlobalSettings::singleClick(); + m_bUseSingle = true; + + disconnect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ), + this, SLOT( slotMouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ) ); +// disconnect( this, SIGNAL( doubleClicked( QListBoxItem *, +// const QPoint & ) ), +// this, SLOT( slotExecute( QListBoxItem *, +// const QPoint & ) ) ); + + if( m_bUseSingle ) + { + connect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ), + this, SLOT( slotMouseButtonClicked( int, QListBoxItem *, + const QPoint & ) ) ); + } + else + { +// connect( this, SIGNAL( doubleClicked( QListBoxItem *, +// const QPoint & ) ), +// this, SLOT( slotExecute( QListBoxItem *, +// const QPoint & ) ) ); + } + + m_bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon(); + m_autoSelectDelay = KGlobalSettings::autoSelectDelay(); + + if( !m_bUseSingle || !m_bChangeCursorOverItem ) + viewport()->unsetCursor(); + +} +*/ +void KListBox::slotAutoSelect() +{ + // check that the item still exists + if( index( m_pCurrentItem ) == -1 ) + return; + + //Give this widget the keyboard focus. + if( !hasFocus() ) + setFocus(); + +#ifdef Q_WS_X11 //FIXME + Window root; + Window child; + int root_x, root_y, win_x, win_y; + uint keybstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &keybstate ); +#endif + + QListBoxItem* previousItem = item( currentItem() ); + setCurrentItem( m_pCurrentItem ); + + if( m_pCurrentItem ) { +#ifndef Q_WS_QWS //FIXME + //Shift pressed? + if( (keybstate & ShiftMask) ) { +#endif + bool block = signalsBlocked(); + blockSignals( true ); + +#ifndef Q_WS_QWS //FIXME + //No Ctrl? Then clear before! + if( !(keybstate & ControlMask) ) + clearSelection(); +#endif + +//US in my QT version it is called isSelected() So what is right? +//US bool select = !m_pCurrentItem->isSelected(); + bool select = !m_pCurrentItem->selected(); + bool update = viewport()->isUpdatesEnabled(); + viewport()->setUpdatesEnabled( false ); + + bool down = index( previousItem ) < index( m_pCurrentItem ); + QListBoxItem* it = down ? previousItem : m_pCurrentItem; + for (;it ; it = it->next() ) { + if ( down && it == m_pCurrentItem ) { + setSelected( m_pCurrentItem, select ); + break; + } + if ( !down && it == previousItem ) { + setSelected( previousItem, select ); + break; + } + setSelected( it, select ); + } + + blockSignals( block ); + viewport()->setUpdatesEnabled( update ); + triggerUpdate( false ); + + emit selectionChanged(); + + if( selectionMode() == QListBox::Single ) + emit selectionChanged( m_pCurrentItem ); + } +#ifndef Q_WS_QWS //FIXME + else if( (keybstate & ControlMask) ) + setSelected( m_pCurrentItem, !m_pCurrentItem->isSelected() ); +#endif + else { + bool block = signalsBlocked(); + blockSignals( true ); + +//US in my QT version it is called isSelected() So what is right? +//US if( !m_pCurrentItem->isSelected() ) + if( !m_pCurrentItem->selected() ) + clearSelection(); + + blockSignals( block ); + + setSelected( m_pCurrentItem, true ); + } +#ifndef Q_WS_QWS //FIXME + } + else + kdDebug() << "Thats not supposed to happen!!!!" << endl; +#endif +} + +void KListBox::emitExecute( QListBoxItem *item, const QPoint &pos ) +{ +#ifdef Q_WS_X11 //FIXME + Window root; + Window child; + int root_x, root_y, win_x, win_y; + uint keybstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &keybstate ); +#endif + + m_pAutoSelect->stop(); + +#ifndef Q_WS_QWS //FIXME + //Dont emit executed if in SC mode and Shift or Ctrl are pressed + if( !( m_bUseSingle && ((keybstate & ShiftMask) || (keybstate & ControlMask)) ) ) { +#endif + emit executed( item ); + emit executed( item, pos ); +#ifndef Q_WS_QWS //FIXME + } +#endif +} + +// +// 2000-16-01 Espen Sand +// This widget is used in dialogs. It should ignore +// F1 (and combinations) and Escape since these are used +// to start help or close the dialog. This functionality +// should be done in QListView but it is not (at least now) +// +void KListBox::keyPressEvent(QKeyEvent *e) +{ + if( e->key() == Key_Escape ) + { + e->ignore(); + } + else if( e->key() == Key_F1 ) + { + e->ignore(); + } + else + { + QListBox::keyPressEvent(e); + } +} + +void KListBox::focusOutEvent( QFocusEvent *fe ) +{ + m_pAutoSelect->stop(); + + QListBox::focusOutEvent( fe ); +} + +void KListBox::leaveEvent( QEvent *e ) +{ + m_pAutoSelect->stop(); + + QListBox::leaveEvent( e ); +} + +void KListBox::contentsMousePressEvent( QMouseEvent *e ) +{ + if( (selectionMode() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) ) { + bool block = signalsBlocked(); + blockSignals( true ); + + clearSelection(); + + blockSignals( block ); + } + + QListBox::contentsMousePressEvent( e ); +} + +void KListBox::contentsMouseDoubleClickEvent ( QMouseEvent * e ) +{ + QListBox::contentsMouseDoubleClickEvent( e ); + + QListBoxItem* item = itemAt( e->pos() ); + + if( item ) { + emit doubleClicked( item, e->globalPos() ); + + if( (e->button() == LeftButton) && !m_bUseSingle ) + emitExecute( item, e->globalPos() ); + } +} + +void KListBox::slotMouseButtonClicked( int btn, QListBoxItem *item, const QPoint &pos ) +{ + if( (btn == LeftButton) && item ) + emitExecute( item, pos ); +} + +void KListBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "klistbox.moc" diff --git a/microkde/kdeui/klistbox.h b/microkde/kdeui/klistbox.h new file mode 100644 index 0000000..8023780 --- a/dev/null +++ b/microkde/kdeui/klistbox.h @@ -0,0 +1,141 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KLISTBOX_H +#define KLISTBOX_H + +#include <qlistbox.h> + +/** + * Extends the functionality of @ref QListBox to honor the system + * wide settings for Single Click/Double Click mode, Auto Selection and + * Change Cursor over Link. + * + * There is a new signal @ref executed(). It gets connected to either + * @ref QListBox::clicked() or @ref QListBox::doubleClicked() + * depending on the KDE wide Single Click/Double Click settings. It is + * strongly recomended that you use this signal instead of the above + * mentioned. This way you don't need to care about the current + * settings. If you want to get informed when the user selects + * something connect to the @ref QListBox::selectionChanged() signal. + * + * @short A variant of @ref QListBox that honors KDE's system-wide settings. + **/ +class KListBox : public QListBox +{ + Q_OBJECT + +public: + KListBox( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + +signals: + + /** + * Emitted whenever the user executes an listbox item. + * + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listbox item. + * + * Note that you may not delete any @ref QListBoxItem objects in slots + * connected to this signal. + */ + void executed( QListBoxItem *item ); + + /** + * Emitted whenever the user executes an listbox item. + * + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listbox item. + * @param pos is the position where the user has clicked + * + * Note that you may not delete any @ref QListBoxItem objects in slots + * connected to this signal. + */ + void executed( QListBoxItem *item, const QPoint &pos ); + + /** + * This signal gets emitted whenever the user double clicks into the + * listbox. + * + * @param item The pointer to the clicked listbox item. + * @param pos The position where the user has clicked. + * + * Note that you may not delete any @ref QListBoxItem objects in slots + * connected to this signal. + * + * This signal is more or less here for the sake of completeness. + * You should normally not need to use this. In most cases it's better + * to use @ref executed() instead. + */ + void doubleClicked( QListBoxItem *item, const QPoint &pos ); + +protected slots: + void slotOnItem( QListBoxItem *item ); + void slotOnViewport(); + +//US void slotSettingsChanged(int); + + /** + * Auto selection happend. + */ + void slotAutoSelect(); + +protected: + void emitExecute( QListBoxItem *item, const QPoint &pos ); + + /** + * @reimplemented + */ + virtual void keyPressEvent(QKeyEvent *e); + /** + * @reimplemented + */ + virtual void focusOutEvent( QFocusEvent *fe ); + /** + * @reimplemented + */ + virtual void leaveEvent( QEvent *e ); + /** + * @reimplemented + */ + virtual void contentsMousePressEvent( QMouseEvent *e ); + /** + * @reimplemented + */ + virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e ); + + bool m_bUseSingle; +//US bool m_bChangeCursorOverItem; + + QListBoxItem* m_pCurrentItem; + + QTimer* m_pAutoSelect; + int m_autoSelectDelay; + +private slots: + void slotMouseButtonClicked( int btn, QListBoxItem *item, const QPoint &pos ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KListBoxPrivate; + KListBoxPrivate *d; +}; + +#endif diff --git a/microkde/kdeui/klistview.cpp b/microkde/kdeui/klistview.cpp new file mode 100644 index 0000000..b53a88a --- a/dev/null +++ b/microkde/kdeui/klistview.cpp @@ -0,0 +1,2191 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2000 Charles Samuels <charles@kde.org> + Copyright (C) 2000 Peter Putzer + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qdragobject.h> +#include <qtimer.h> +#include <qheader.h> +#include <qcursor.h> +#include <qtooltip.h> +#include <qstyle.h> +#include <qpainter.h> + +#include <kglobalsettings.h> +#include <kconfig.h> +#include <kconfigbase.h> +//US #include <kcursor.h> +#include <kapplication.h> +//US #include <kipc.h> +#include <kdebug.h> +#ifdef _WIN32_ +#define Q_WS_QWS +#endif +#ifndef _WIN32_ +#define private public +#include <qlistview.h> +#undef private +#endif +#include "klistview.h" +//US #include "klistviewlineedit.h" +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#endif + +// /*US +class KListView::Tooltip : public QToolTip +{ +public: + Tooltip (KListView* parent, QToolTipGroup* group = 0L); + virtual ~Tooltip () {} + +protected: + // */ + /** + * Reimplemented from QToolTip for internal reasons. + */ + // /*US + virtual void maybeTip (const QPoint&); + +private: + KListView* mParent; +}; + +KListView::Tooltip::Tooltip (KListView* parent, QToolTipGroup* group) + : QToolTip (parent, group), + mParent (parent) +{ +} + +void KListView::Tooltip::maybeTip (const QPoint&) +{ + // FIXME +} +// */ + +class KListView::KListViewPrivate +{ +public: + KListViewPrivate (KListView* listview) + : pCurrentItem (0L), + autoSelectDelay(1), +//US dragDelay (KGlobalSettings::dndEventDelay()), + + dragDelay (10), +//US editor (new KListViewLineEdit (listview)), + cursorInExecuteArea(false), + bUseSingle(false), + bChangeCursorOverItem(false), + itemsMovable (true), + selectedBySimpleMove(false), + selectedUsingMouse(false), + showContextMenusOnPress(true), + itemsRenameable (false), + validDrag (false), + dragEnabled (false), + autoOpen (true), + dropVisualizer (true), + dropHighlighter (false), + createChildren (true), + pressedOnSelected (false), + wasShiftEvent (false), + fullWidth (false), + sortAscending(true), + tabRename(true), + sortColumn(0), + selectionDirection(0), + tooltipColumn (0), + selectionMode (Single), +//US contextMenuKey (KGlobalSettings::contextMenuKey()), +//US showContextMenusOnPress (KGlobalSettings::showContextMenusOnPress()), + mDropVisualizerWidth (4) + { + renameable += 0; +//US connect(editor, SIGNAL(done(QListViewItem*,int)), listview, SLOT(doneEditing(QListViewItem*,int))); + } + + ~KListViewPrivate () + { +//US delete editor; + } + + QListViewItem* pCurrentItem; + + QTimer autoSelect; + int autoSelectDelay; + + QTimer dragExpand; + QListViewItem* dragOverItem; + QPoint dragOverPoint; + + QPoint startDragPos; + int dragDelay; + +//US KListViewLineEdit *editor; + QValueList<int> renameable; + + bool cursorInExecuteArea:1; + bool bUseSingle:1; + bool bChangeCursorOverItem:1; + bool itemsMovable:1; + bool selectedBySimpleMove : 1; + bool selectedUsingMouse:1; + bool itemsRenameable:1; + bool validDrag:1; + bool dragEnabled:1; + bool autoOpen:1; + bool dropVisualizer:1; + bool dropHighlighter:1; + bool createChildren:1; + bool pressedOnSelected:1; + bool wasShiftEvent:1; + bool fullWidth:1; + bool sortAscending:1; + bool tabRename:1; + + int sortColumn; + + //+1 means downwards (y increases, -1 means upwards, 0 means not selected), aleXXX + int selectionDirection; + int tooltipColumn; + + SelectionModeExt selectionMode; + int contextMenuKey; + bool showContextMenusOnPress; + + QRect mOldDropVisualizer; + int mDropVisualizerWidth; + QRect mOldDropHighlighter; + QListViewItem *afterItemDrop; + QListViewItem *parentItemDrop; + + QColor alternateBackground; +}; + +/*US +KListViewLineEdit::KListViewLineEdit(KListView *parent) + : KLineEdit(parent->viewport()), item(0), col(0), p(parent) +{ + setFrame( false ); + hide(); + connect( parent, SIGNAL( selectionChanged() ), SLOT( slotSelectionChanged() )); +} + +KListViewLineEdit::~KListViewLineEdit() +{ +} + +void KListViewLineEdit::load(QListViewItem *i, int c) +{ + item=i; + col=c; + + QRect rect(p->itemRect(i)); + setText(item->text(c)); + + int fieldX = rect.x() - 1; + int fieldW = p->columnWidth(col) + 2; + + int pos = p->header()->mapToIndex(col); + for ( int index = 0; index < pos; index++ ) + fieldX += p->columnWidth( p->header()->mapToSection( index )); + + if ( col == 0 ) { + int d = i->depth() + (p->rootIsDecorated() ? 1 : 0); + d *= p->treeStepSize(); + fieldX += d; + fieldW -= d; + } + + if ( i->pixmap( col ) ) {// add width of pixmap + int d = i->pixmap( col )->width(); + fieldX += d; + fieldW -= d; + } + + setGeometry(fieldX, rect.y() - 1, fieldW, rect.height() + 2); + show(); + setFocus(); +} +*/ +/* Helper functions to for + * tabOrderedRename functionality. + */ + +static int nextCol (KListView *pl, QListViewItem *pi, int start, int dir) +{ + if (pi) + { + // Find the next renameable column in the current row + for (; ((dir == +1) ? (start < pl->columns()) : (start >= 0)); start += dir) + if (pl->isRenameable(start)) + return start; + } + + return -1; +} + +static QListViewItem *prevItem (QListViewItem *pi) +{ + QListViewItem *pa = pi->itemAbove(); + + /* Does what the QListViewItem::previousSibling() + * of my dreams would do. + */ + if (pa && pa->parent() == pi->parent()) + return pa; + + return NULL; +} + +static QListViewItem *lastQChild (QListViewItem *pi) +{ + if (pi) + { + /* Since there's no QListViewItem::lastChild(). + * This finds the last sibling for the given + * item. + */ + for (QListViewItem *pt = pi->nextSibling(); pt; pt = pt->nextSibling()) + pi = pt; + } + + return pi; +} +/*US +void KListViewLineEdit::selectNextCell (QListViewItem *pitem, int column, bool forward) +{ + const int ncols = p->columns(); + const int dir = forward ? +1 : -1; + const int restart = forward ? 0 : (ncols - 1); + QListViewItem *top = (pitem && pitem->parent()) + ? pitem->parent()->firstChild() + : p->firstChild(); + QListViewItem *pi = pitem; + + terminate(); // Save current changes + + do + { +*/ + /* Check the rest of the current row for an editable column, + * if that fails, check the entire next/previous row. The + * last case goes back to the first item in the current branch + * or the last item in the current branch depending on the + * direction. + */ +/*US + if ((column = nextCol(p, pi, column + dir, dir)) != -1 || + (column = nextCol(p, (pi = (forward ? pi->nextSibling() : prevItem(pi))), restart, dir)) != -1 || + (column = nextCol(p, (pi = (forward ? top : lastQChild(pitem))), restart, dir)) != -1) + { + if (pi) + { + p->setCurrentItem(pi); // Calls terminate + p->rename(pi, column); +*/ + /* Some listviews may override rename() to + * prevent certain items from being renamed, + * if this is done, [m_]item will be NULL + * after the rename() call... try again. + */ +/*US + if (!item) + continue; + + break; + } + } + } + while (pi && !item); +} +*/ + +/*US +#ifdef KeyPress +#undef KeyPress +#endif + +bool KListViewLineEdit::event (QEvent *pe) +{ + if (pe->type() == QEvent::KeyPress) + { + QKeyEvent *k = (QKeyEvent *) pe; + + if ((k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab) && + p->tabOrderedRenaming() && p->itemsRenameable() && + !(k->state() & ControlButton || k->state() & AltButton)) + { + selectNextCell(item, col, + (k->key() == Key_Tab && !(k->state() & ShiftButton))); + return true; + } + } + + return KLineEdit::event(pe); +} + +void KListViewLineEdit::keyPressEvent(QKeyEvent *e) +{ + if(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter ) + terminate(true); + else if(e->key() == Qt::Key_Escape) + terminate(false); + else if (e->key() == Qt::Key_Down || e->key() == Qt::Key_Up) + { + terminate(true); + KLineEdit::keyPressEvent(e); + } + else + KLineEdit::keyPressEvent(e); +} + +void KListViewLineEdit::terminate() +{ + terminate(true); +} + +void KListViewLineEdit::terminate(bool commit) +{ + if ( item ) + { + //kdDebug() << "KListViewLineEdit::terminate " << commit << endl; + if (commit) + item->setText(col, text()); + int c=col; + QListViewItem *i=item; + col=0; + item=0; + hide(); // will call focusOutEvent, that's why we set item=0 before + emit done(i,c); + } +} + +void KListViewLineEdit::focusOutEvent(QFocusEvent *ev) +{ + QFocusEvent * focusEv = static_cast<QFocusEvent*>(ev); + // Don't let a RMB close the editor + if (focusEv->reason() != QFocusEvent::Popup && focusEv->reason() != QFocusEvent::ActiveWindow) + terminate(true); +} + +void KListViewLineEdit::paintEvent( QPaintEvent *e ) +{ + KLineEdit::paintEvent( e ); + + if ( !frame() ) { + QPainter p( this ); + p.setClipRegion( e->region() ); + p.drawRect( rect() ); + } +} + +// selection changed -> terminate. As our "item" can be already deleted, +// we can't call terminate(false), because that would emit done() with +// a dangling pointer to "item". +void KListViewLineEdit::slotSelectionChanged() +{ + item = 0; + col = 0; + hide(); +} +*/ + +KListView::KListView( QWidget *parent, const char *name ) + : QListView( parent, name ), + d (new KListViewPrivate (this)) +{ +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold ); +#endif +//US setDragAutoScroll(true); + + connect( this, SIGNAL( onViewport() ), + this, SLOT( slotOnViewport() ) ); + connect( this, SIGNAL( onItem( QListViewItem * ) ), + this, SLOT( slotOnItem( QListViewItem * ) ) ); + + connect (this, SIGNAL(contentsMoving(int,int)), + this, SLOT(cleanDropVisualizer())); + connect (this, SIGNAL(contentsMoving(int,int)), + this, SLOT(cleanItemHighlighter())); + +/*US + slotSettingsChanged(KApplication::SETTINGS_MOUSE); + + if (kapp) + { + connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) ); + kapp->addKipcEventMask( KIPC::SettingsChanged ); + } +*/ + slotSettingsChanged(1); //US do this to initialize the connections + + + connect(&d->autoSelect, SIGNAL( timeout() ), + this, SLOT( slotAutoSelect() ) ); + connect(&d->dragExpand, SIGNAL( timeout() ), + this, SLOT( slotDragExpand() ) ); + + // context menu handling + if (d->showContextMenusOnPress) + { + connect (this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + else + { + connect (this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + + connect (this, SIGNAL (menuShortCutPressed (KListView*, QListViewItem*)), + this, SLOT (emitContextMenu (KListView*, QListViewItem*))); + + + //qDebug("KListView::KListView make alternate color configurable"); +//US d->alternateBackground = KGlobalSettings::alternateBackgroundColor(); + d->alternateBackground = QColor(240, 240, 240); +} + + + +KListView::~KListView() +{ + delete d; +} + +bool KListView::isExecuteArea( const QPoint& point ) +{ + if ( itemAt( point ) ) + return isExecuteArea( point.x() ); + + return false; +} + +bool KListView::isExecuteArea( int x ) +{ + if( allColumnsShowFocus() ) + return true; + else { + int offset = 0; + int width = columnWidth( 0 ); + int pos = header()->mapToIndex( 0 ); + + for ( int index = 0; index < pos; index++ ) + offset += columnWidth( header()->mapToSection( index ) ); + + x += contentsX(); // in case of a horizontal scrollbar + return ( x > offset && x < ( offset + width ) ); + } +} + +void KListView::slotOnItem( QListViewItem *item ) +{ + QPoint vp = viewport()->mapFromGlobal( QCursor::pos() ); + if ( item && isExecuteArea( vp.x() ) && (d->autoSelectDelay > -1) && d->bUseSingle ) { + d->autoSelect.start( d->autoSelectDelay, true ); + d->pCurrentItem = item; + } +} + +void KListView::slotOnViewport() +{ + if ( d->bChangeCursorOverItem ) + viewport()->unsetCursor(); + + d->autoSelect.stop(); + d->pCurrentItem = 0L; +} + +void KListView::slotSettingsChanged(int category) +{ +qDebug("KListView::slotSettingsChanged has to be verified"); +/*US + + switch (category) + { + case KApplication::SETTINGS_MOUSE: + d->dragDelay = KGlobalSettings::dndEventDelay(); + d->bUseSingle = KGlobalSettings::singleClick(); + + disconnect(this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), + this, SLOT (slotMouseButtonClicked (int, QListViewItem*, const QPoint &, int))); + + if( d->bUseSingle ) + connect (this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), + this, SLOT (slotMouseButtonClicked( int, QListViewItem*, const QPoint &, int))); + + d->bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon(); + d->autoSelectDelay = KGlobalSettings::autoSelectDelay(); + + if( !d->bUseSingle || !d->bChangeCursorOverItem ) + viewport()->unsetCursor(); + + break; + + case KApplication::SETTINGS_POPUPMENU: + d->contextMenuKey = KGlobalSettings::contextMenuKey (); + d->showContextMenusOnPress = KGlobalSettings::showContextMenusOnPress (); + + if (d->showContextMenusOnPress) + { + disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + + connect(this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + else + { + disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + + connect(this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)), + this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); + } + break; + + default: + break; + } +*/ + + if( d->bUseSingle ) + connect (this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), + this, SLOT (slotMouseButtonClicked( int, QListViewItem*, const QPoint &, int))); + +} + +void KListView::slotAutoSelect() +{ + // check that the item still exists + if( itemIndex( d->pCurrentItem ) == -1 ) + return; + + if (!isActiveWindow()) + { + d->autoSelect.stop(); + return; + } + + //Give this widget the keyboard focus. + if( !hasFocus() ) + setFocus(); + + QListViewItem* previousItem = currentItem(); + setCurrentItem( d->pCurrentItem ); + +#if 0 +#ifndef Q_WS_QWS + // FIXME(E): Implement for Qt Embedded + if( d->pCurrentItem ) { + //Shift pressed? + if( (keybstate & ShiftMask) ) { + bool block = signalsBlocked(); + blockSignals( true ); + + //No Ctrl? Then clear before! + if( !(keybstate & ControlMask) ) + clearSelection(); + + bool select = !d->pCurrentItem->isSelected(); + bool update = viewport()->isUpdatesEnabled(); + viewport()->setUpdatesEnabled( false ); + + bool down = previousItem->itemPos() < d->pCurrentItem->itemPos(); + QListViewItemIterator lit( down ? previousItem : d->pCurrentItem ); + for ( ; lit.current(); ++lit ) { + if ( down && lit.current() == d->pCurrentItem ) { + d->pCurrentItem->setSelected( select ); + break; + } + if ( !down && lit.current() == previousItem ) { + previousItem->setSelected( select ); + break; + } + lit.current()->setSelected( select ); + } + + blockSignals( block ); + viewport()->setUpdatesEnabled( update ); + triggerUpdate(); + + emit selectionChanged(); + + if( selectionMode() == QListView::Single ) + emit selectionChanged( d->pCurrentItem ); + } + else if( (keybstate & ControlMask) ) + setSelected( d->pCurrentItem, !d->pCurrentItem->isSelected() ); + else { + bool block = signalsBlocked(); + blockSignals( true ); + + if( !d->pCurrentItem->isSelected() ) + clearSelection(); + + blockSignals( block ); + + setSelected( d->pCurrentItem, true ); + } + } + else + kdDebug() << "KListView::slotAutoSelect: Thats not supposed to happen!!!!" << endl; +#endif +#endif +} + +void KListView::slotHeaderChanged() +{ + if (d->fullWidth && columns()) + { + int w = 0; + for (int i = 0; i < columns() - 1; ++i) w += columnWidth(i); + setColumnWidth( columns() - 1, viewport()->width() - w - 1 ); + } +} + +void KListView::emitExecute( QListViewItem *item, const QPoint &pos, int c ) +{ + if( isExecuteArea( viewport()->mapFromGlobal(pos) ) ) { + + // Double click mode ? + if ( !d->bUseSingle ) + { + emit executed( item ); + emit executed( item, pos, c ); + } + else + { +#if 0 +#ifndef Q_WS_QWS + // FIXME(E): Implement for Qt Embedded + Window root; + Window child; + int root_x, root_y, win_x, win_y; + uint keybstate; + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &keybstate ); + + d->autoSelect.stop(); + + //Dont emit executed if in SC mode and Shift or Ctrl are pressed + if( !( ((keybstate & ShiftMask) || (keybstate & ControlMask)) ) ) { + emit executed( item ); + emit executed( item, pos, c ); + } +#endif +#endif + } + } +} + +void KListView::focusInEvent( QFocusEvent *fe ) +{ + // kdDebug()<<"KListView::focusInEvent()"<<endl; + QListView::focusInEvent( fe ); + if ((d->selectedBySimpleMove) + && (d->selectionMode == FileManager) + && (fe->reason()!=QFocusEvent::Popup) + && (fe->reason()!=QFocusEvent::ActiveWindow) + && (currentItem()!=0)) + { + currentItem()->setSelected(true); + currentItem()->repaint(); + emit selectionChanged(); + }; +} + +void KListView::focusOutEvent( QFocusEvent *fe ) +{ + cleanDropVisualizer(); + cleanItemHighlighter(); + + d->autoSelect.stop(); + + if ((d->selectedBySimpleMove) + && (d->selectionMode == FileManager) + && (fe->reason()!=QFocusEvent::Popup) + && (fe->reason()!=QFocusEvent::ActiveWindow) + && (currentItem()!=0) +/*US && (!d->editor->isVisible()) */ + ) + { + currentItem()->setSelected(false); + currentItem()->repaint(); + emit selectionChanged(); + }; + + QListView::focusOutEvent( fe ); +} + +void KListView::leaveEvent( QEvent *e ) +{ + d->autoSelect.stop(); + + QListView::leaveEvent( e ); +} + +bool KListView::event( QEvent *e ) +{ + if (e->type() == QEvent::ApplicationPaletteChange) { +qDebug("KListView::event make alternate color configurable"); +//US d->alternateBackground=KGlobalSettings::alternateBackgroundColor(); + d->alternateBackground = QColor(240, 240, 240); + } + + return QListView::event(e); +} + +void KListView::contentsMousePressEvent( QMouseEvent *e ) +{ + if( (selectionModeExt() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) ) + { + bool block = signalsBlocked(); + blockSignals( true ); + + clearSelection(); + + blockSignals( block ); + } + else if ((selectionModeExt()==FileManager) && (d->selectedBySimpleMove)) + { + d->selectedBySimpleMove=false; + d->selectedUsingMouse=true; + if (currentItem()!=0) + { + currentItem()->setSelected(false); + currentItem()->repaint(); +// emit selectionChanged(); + }; + }; + + QPoint p( contentsToViewport( e->pos() ) ); + QListViewItem *at = itemAt (p); + + // true if the root decoration of the item "at" was clicked (i.e. the +/- sign) + bool rootDecoClicked = at + && ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) + + treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ) + && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) ); + + if (e->button() == LeftButton && !rootDecoClicked) + { + //Start a drag + d->startDragPos = e->pos(); + + if (at) + { + d->validDrag = true; + d->pressedOnSelected = at->isSelected(); + } + } + + QListView::contentsMousePressEvent( e ); +} + +void KListView::contentsMouseMoveEvent( QMouseEvent *e ) +{ + if (!dragEnabled() || d->startDragPos.isNull() || !d->validDrag) { + QListView::contentsMouseMoveEvent (e); + return; + } + + QPoint vp = contentsToViewport(e->pos()); + QListViewItem *item = itemAt( vp ); + + //do we process cursor changes at all? + if ( item && d->bChangeCursorOverItem && d->bUseSingle ) + { + //Cursor moved on a new item or in/out the execute area + if( (item != d->pCurrentItem) || + (isExecuteArea(vp) != d->cursorInExecuteArea) ) + { + d->cursorInExecuteArea = isExecuteArea(vp); +qDebug("KListView::contentsMouseMoveEvent drag&drop not supported yet"); +/*US + if( d->cursorInExecuteArea ) //cursor moved in execute area + viewport()->setCursor( KCursor::handCursor() ); + else //cursor moved out of execute area + viewport()->unsetCursor(); +*/ + } + } + + bool dragOn = dragEnabled(); + QPoint newPos = e->pos(); + if (dragOn && d->validDrag && + (newPos.x() > d->startDragPos.x()+d->dragDelay || + newPos.x() < d->startDragPos.x()-d->dragDelay || + newPos.y() > d->startDragPos.y()+d->dragDelay || + newPos.y() < d->startDragPos.y()-d->dragDelay)) + //(d->startDragPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) + { + QListView::contentsMouseReleaseEvent( 0 ); + startDrag(); + d->startDragPos = QPoint(); + d->validDrag = false; + } +} + +void KListView::contentsMouseReleaseEvent( QMouseEvent *e ) +{ + if (e->button() == LeftButton) + { + // If the row was already selected, maybe we want to start an in-place editing + if ( d->pressedOnSelected && itemsRenameable() ) + { + QPoint p( contentsToViewport( e->pos() ) ); + QListViewItem *at = itemAt (p); + if ( at ) + { + // true if the root decoration of the item "at" was clicked (i.e. the +/- sign) + bool rootDecoClicked = + ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) + + treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ) + && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) ); + + if (!rootDecoClicked) + { + int col = header()->mapToLogical( header()->cellAt( p.x() ) ); + if ( d->renameable.contains(col) ) + rename(at, col); + } + } + } + + d->pressedOnSelected = false; + d->validDrag = false; + d->startDragPos = QPoint(); + } + QListView::contentsMouseReleaseEvent( e ); +} + +void KListView::contentsMouseDoubleClickEvent ( QMouseEvent *e ) +{ + // We don't want to call the parent method because it does setOpen, + // whereas we don't do it in single click mode... (David) + //QListView::contentsMouseDoubleClickEvent( e ); + + QPoint vp = contentsToViewport(e->pos()); + QListViewItem *item = itemAt( vp ); + emit QListView::doubleClicked( item ); // we do it now + + int col = item ? header()->mapToLogical( header()->cellAt( vp.x() ) ) : -1; + + if( item ) { + emit doubleClicked( item, e->globalPos(), col ); + + if( (e->button() == LeftButton) && !d->bUseSingle ) + emitExecute( item, e->globalPos(), col ); + } +} + +void KListView::slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c ) +{ + if( (btn == LeftButton) && item ) + emitExecute(item, pos, c); +} + +void KListView::contentsDropEvent(QDropEvent* e) +{ +qDebug("KListView::contentsDropEvent drag&drop not supported yet"); +/*US + cleanDropVisualizer(); + cleanItemHighlighter(); + d->dragExpand.stop(); + + if (acceptDrag (e)) + { + e->acceptAction(); + QListViewItem *afterme; + QListViewItem *parent; + findDrop(e->pos(), parent, afterme); + + if (e->source() == viewport() && itemsMovable()) + movableDropEvent(parent, afterme); + else + { + + emit dropped(e, afterme); + emit dropped(this, e, afterme); + emit dropped(e, parent, afterme); + emit dropped(this, e, parent, afterme); + + } + } +*/ + +} + +void KListView::movableDropEvent (QListViewItem* parent, QListViewItem* afterme) +{ + QPtrList<QListViewItem> items, afterFirsts, afterNows; + QListViewItem *current=currentItem(); + bool hasMoved=false; + for (QListViewItem *i = firstChild(), *iNext=0; i != 0; i = iNext) + { + iNext=i->itemBelow(); + if (!i->isSelected()) + continue; + + // don't drop an item after itself, or else + // it moves to the top of the list + if (i==afterme) + continue; + + i->setSelected(false); + + QListViewItem *afterFirst = i->itemAbove(); + + if (!hasMoved) + { + emit aboutToMove(); + hasMoved=true; + } + + moveItem(i, parent, afterme); + + // ###### This should include the new parent !!! -> KDE 3.0 + // If you need this right now, have a look at keditbookmarks. + emit moved(i, afterFirst, afterme); + + items.append (i); + afterFirsts.append (afterFirst); + afterNows.append (afterme); + + afterme = i; + } + clearSelection(); + for (QListViewItem *i=items.first(); i != 0; i=items.next() ) + i->setSelected(true); + if (current) + setCurrentItem(current); + + emit moved(items,afterFirsts,afterNows); + + if (firstChild()) + emit moved(); +} + +void KListView::contentsDragMoveEvent(QDragMoveEvent *event) +{ +qDebug("KListView::contentsDropEvent drag&drop not supported yet"); +/*US + if (acceptDrag(event)) + { + event->acceptAction(); + //Clean up the view + + findDrop(event->pos(), d->parentItemDrop, d->afterItemDrop); + QPoint vp = contentsToViewport( event->pos() ); + QListViewItem *item = isExecuteArea( vp ) ? itemAt( vp ) : 0L; + + if ( item != d->dragOverItem ) + { + d->dragExpand.stop(); + d->dragOverItem = item; + d->dragOverPoint = vp; + if ( d->dragOverItem && d->dragOverItem->isExpandable() && !d->dragOverItem->isOpen() ) + d->dragExpand.start( QApplication::startDragTime(), true ); + } + if (dropVisualizer()) + { + QRect tmpRect = drawDropVisualizer(0, d->parentItemDrop, d->afterItemDrop); + if (tmpRect != d->mOldDropVisualizer) + { + cleanDropVisualizer(); + d->mOldDropVisualizer=tmpRect; + viewport()->repaint(tmpRect); + } + } + if (dropHighlighter()) + { + QRect tmpRect = drawItemHighlighter(0, d->afterItemDrop); + if (tmpRect != d->mOldDropHighlighter) + { + cleanItemHighlighter(); + d->mOldDropHighlighter=tmpRect; + viewport()->repaint(tmpRect); + } + } + } + else + event->ignore(); +*/ +} + +void KListView::slotDragExpand() +{ + if ( itemAt( d->dragOverPoint ) == d->dragOverItem ) + d->dragOverItem->setOpen( true ); +} + +void KListView::contentsDragLeaveEvent (QDragLeaveEvent*) +{ + d->dragExpand.stop(); + cleanDropVisualizer(); + cleanItemHighlighter(); +} + +void KListView::cleanDropVisualizer() +{ + if (d->mOldDropVisualizer.isValid()) + { + QRect rect=d->mOldDropVisualizer; + d->mOldDropVisualizer = QRect(); + viewport()->repaint(rect, true); + } +} + +int KListView::depthToPixels( int depth ) +{ + return treeStepSize() * ( depth + (rootIsDecorated() ? 1 : 0) ) + itemMargin(); +} + +void KListView::findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after) +{ + QPoint p (contentsToViewport(pos)); + + // Get the position to put it in + QListViewItem *atpos = itemAt(p); + + QListViewItem *above; + if (!atpos) // put it at the end + above = lastItem(); + else + { + // Get the closest item before us ('atpos' or the one above, if any) + if (p.y() - itemRect(atpos).topLeft().y() < (atpos->height()/2)) + above = atpos->itemAbove(); + else + above = atpos; + } + + if (above) + { + // Now, we know we want to go after "above". But as a child or as a sibling ? + // We have to ask the "above" item if it accepts children. + if (above->isExpandable()) + { + // The mouse is sufficiently on the right ? - doesn't matter if 'above' has visible children + if (p.x() >= depthToPixels( above->depth() + 1 ) || + (above->isOpen() && above->childCount() > 0) ) + { + parent = above; + after = 0L; + return; + } + } + + // Ok, there's one more level of complexity. We may want to become a new + // sibling, but of an upper-level group, rather than the "above" item + QListViewItem * betterAbove = above->parent(); + QListViewItem * last = above; + while ( betterAbove ) + { + // We are allowed to become a sibling of "betterAbove" only if we are + // after its last child + if ( last->nextSibling() == 0 ) + { + if (p.x() < depthToPixels ( betterAbove->depth() + 1 )) + above = betterAbove; // store this one, but don't stop yet, there may be a better one + else + break; // not enough on the left, so stop + last = betterAbove; + betterAbove = betterAbove->parent(); // up one level + } else + break; // we're among the child of betterAbove, not after the last one + } + } + // set as sibling + after = above; + parent = after ? after->parent() : 0L ; +} + +QListViewItem* KListView::lastChild () const +{ + QListViewItem* lastchild = firstChild(); + + if (lastchild) + for (; lastchild->nextSibling(); lastchild = lastchild->nextSibling()); + + return lastchild; +} + +QListViewItem *KListView::lastItem() const +{ + QListViewItem* last = lastChild(); + + for (QListViewItemIterator it (last); it.current(); ++it) + last = it.current(); + + return last; +} + +KLineEdit *KListView::renameLineEdit() const +{ +//US return d->editor; +qDebug("KListView::renameLineEdit returns 0. Might crash"); +return 0; +} + +void KListView::startDrag() +{ +qDebug("KListView::startDrag drag&drop not supported yet."); +/*US + QDragObject *drag = dragObject(); + + if (!drag) + return; + + if (drag->drag() && drag->target() != viewport()) + emit moved(); +*/ +} + +QDragObject *KListView::dragObject() +{ + if (!currentItem()) + return 0; + + return new QStoredDrag("application/x-qlistviewitem", viewport()); +} + +void KListView::setItemsMovable(bool b) +{ + d->itemsMovable=b; +} + +bool KListView::itemsMovable() const +{ + return d->itemsMovable; +} + +void KListView::setItemsRenameable(bool b) +{ + d->itemsRenameable=b; +} + +bool KListView::itemsRenameable() const +{ + return d->itemsRenameable; +} + + +void KListView::setDragEnabled(bool b) +{ + d->dragEnabled=b; +} + +bool KListView::dragEnabled() const +{ + return d->dragEnabled; +} + +void KListView::setAutoOpen(bool b) +{ + d->autoOpen=b; +} + +bool KListView::autoOpen() const +{ + return d->autoOpen; +} + +bool KListView::dropVisualizer() const +{ + return d->dropVisualizer; +} + +void KListView::setDropVisualizer(bool b) +{ + d->dropVisualizer=b; +} + +QPtrList<QListViewItem> KListView::selectedItems() const +{ + QPtrList<QListViewItem> list; + for (QListViewItem *i=firstChild(); i!=0; i=i->itemBelow()) + if (i->isSelected()) list.append(i); + return list; +} + + +void KListView::moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after) +{ + // sanity check - don't move a item into it's own child structure + QListViewItem *i = parent; + while(i) + { + if(i == item) + return; + i = i->parent(); + } + + // Basically reimplementing the QListViewItem(QListViewItem*, QListViewItem*) constructor + // in here, without ever deleting the item. + if (item->parent()) + item->parent()->takeItem(item); + else + takeItem(item); + + if (parent) + parent->insertItem(item); + else + insertItem(item); + + if (after) + ;//item->moveToJustAfter(after); +} + +void KListView::contentsDragEnterEvent(QDragEnterEvent *event) +{ +qDebug("KListView::contentsDragEnterEvent drag&drop not supported yet."); +/*US + if (acceptDrag (event)) + event->accept(); +*/ +} + +void KListView::setDropVisualizerWidth (int w) +{ + d->mDropVisualizerWidth = w > 0 ? w : 1; +} + +QRect KListView::drawDropVisualizer(QPainter *p, QListViewItem *parent, + QListViewItem *after) +{ + QRect insertmarker; + + if (!after && !parent) + insertmarker = QRect (0, 0, viewport()->width(), d->mDropVisualizerWidth/2); + else + { + int level = 0; + if (after) + { + QListViewItem* it = 0L; + if (after->isOpen()) + { + // Look for the last child (recursively) + it = after->firstChild(); + if (it) + while (it->nextSibling() || it->firstChild()) + if ( it->nextSibling() ) + it = it->nextSibling(); + else + it = it->firstChild(); + } + + insertmarker = itemRect (it ? it : after); + level = after->depth(); + } + else if (parent) + { + insertmarker = itemRect (parent); + level = parent->depth() + 1; + } + insertmarker.setLeft( treeStepSize() * ( level + (rootIsDecorated() ? 1 : 0) ) + itemMargin() ); + insertmarker.setRight (viewport()->width()); + insertmarker.setTop (insertmarker.bottom() - d->mDropVisualizerWidth/2 + 1); + insertmarker.setBottom (insertmarker.bottom() + d->mDropVisualizerWidth/2); + } + + // This is not used anymore, at least by KListView itself (see viewportPaintEvent) + // Remove for KDE 3.0. + if (p) + p->fillRect(insertmarker, Dense4Pattern); + + return insertmarker; +} + +QRect KListView::drawItemHighlighter(QPainter *painter, QListViewItem *item) +{ + QRect r; + + if (item) + { + r = itemRect(item); + r.setLeft(r.left()+(item->depth()+1)*treeStepSize()); + if (painter) { +//US style().drawPrimitive(QStyle::PE_FocusRect, painter, r, colorGroup(), +//US QStyle::Style_FocusAtBorder, colorGroup().highlight()); + const QColor* pHighl = &(colorGroup().highlight()); + //LR style().drawFocusRect(painter, r, colorGroup(), pHighl, true); + +qDebug("KListView::drawItemHighlighter has to be verified"); + + } + + } + + return r; +} + +void KListView::cleanItemHighlighter () +{ + if (d->mOldDropHighlighter.isValid()) + { + QRect rect=d->mOldDropHighlighter; + d->mOldDropHighlighter = QRect(); + viewport()->repaint(rect, true); + } +} + +void KListView::rename(QListViewItem *item, int c) +{ + if (d->renameable.contains(c)) + { + ensureItemVisible(item); +//US d->editor->load(item,c); +qDebug("KListView::rename has to be verified"); + + } +} + +bool KListView::isRenameable (int col) const +{ + return d->renameable.contains(col); +} + +void KListView::setRenameable (int col, bool yesno) +{ + if (col>=header()->count()) return; + + d->renameable.remove(col); + if (yesno && d->renameable.find(col)==d->renameable.end()) + d->renameable+=col; + else if (!yesno && d->renameable.find(col)!=d->renameable.end()) + d->renameable.remove(col); +} + +void KListView::doneEditing(QListViewItem *item, int row) +{ + emit itemRenamed(item, item->text(row), row); + emit itemRenamed(item); +} + +bool KListView::acceptDrag(QDropEvent* e) const +{ +qDebug("KListView::acceptDrag drag&drop not supported yet"); +//US return acceptDrops() && itemsMovable() && (e->source()==viewport()); +return false; +} + +void KListView::setCreateChildren(bool b) +{ + d->createChildren=b; +} + +bool KListView::createChildren() const +{ + return d->createChildren; +} + + +int KListView::tooltipColumn() const +{ + return d->tooltipColumn; +} + +void KListView::setTooltipColumn(int column) +{ + d->tooltipColumn=column; +} + +void KListView::setDropHighlighter(bool b) +{ + d->dropHighlighter=b; +} + +bool KListView::dropHighlighter() const +{ + return d->dropHighlighter; +} + +bool KListView::showTooltip(QListViewItem *item, const QPoint &, int column) const +{ + return ((tooltip(item, column).length()>0) && (column==tooltipColumn())); +} + +QString KListView::tooltip(QListViewItem *item, int column) const +{ + return item->text(column); +} + +void KListView::setTabOrderedRenaming(bool b) +{ + d->tabRename = b; +} + +bool KListView::tabOrderedRenaming() const +{ + return d->tabRename; +} + +void KListView::keyPressEvent (QKeyEvent* e) +{ + //don't we need a contextMenuModifier too ? (aleXXX) + if (e->key() == d->contextMenuKey) + { + emit menuShortCutPressed (this, currentItem()); + return; + } + if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) + { + emit signalDelete ( ); + return; + } + + if (d->selectionMode != FileManager) + QListView::keyPressEvent (e); + else + fileManagerKeyPressEvent (e); +} + +void KListView::activateAutomaticSelection() +{ + d->selectedBySimpleMove=true; + d->selectedUsingMouse=false; + if (currentItem()!=0) + { + selectAll(false); + currentItem()->setSelected(true); + currentItem()->repaint(); + emit selectionChanged(); + }; +} + +void KListView::deactivateAutomaticSelection() +{ + d->selectedBySimpleMove=false; +} + +bool KListView::automaticSelection() const +{ + return d->selectedBySimpleMove; +} + +void KListView::fileManagerKeyPressEvent (QKeyEvent* e) +{ + //don't care whether it's on the keypad or not + int e_state=(e->state() & ~Keypad); + + int oldSelectionDirection(d->selectionDirection); + + if ((e->key()!=Key_Shift) && (e->key()!=Key_Control) + && (e->key()!=Key_Meta) && (e->key()!=Key_Alt)) + { + if ((e_state==ShiftButton) && (!d->wasShiftEvent) && (!d->selectedBySimpleMove)) + selectAll(FALSE); + d->selectionDirection=0; + d->wasShiftEvent = (e_state == ShiftButton); + }; + + //d->wasShiftEvent = (e_state == ShiftButton); + + + QListViewItem* item = currentItem(); + if (item==0) return; + + QListViewItem* repaintItem1 = item; + QListViewItem* repaintItem2 = 0L; + QListViewItem* visItem = 0L; + + QListViewItem* nextItem = 0L; + int items = 0; + + bool shiftOrCtrl((e_state==ControlButton) || (e_state==ShiftButton)); + int selectedItems(0); + for (QListViewItem *tmpItem=firstChild(); tmpItem!=0; tmpItem=tmpItem->nextSibling()) + if (tmpItem->isSelected()) selectedItems++; + + if (((selectedItems==0) || ((selectedItems==1) && (d->selectedUsingMouse))) + && (e_state==NoButton) + && ((e->key()==Key_Down) + || (e->key()==Key_Up) + || (e->key()==Key_Next) + || (e->key()==Key_Prior) + || (e->key()==Key_Home) + || (e->key()==Key_End))) + { + d->selectedBySimpleMove=true; + d->selectedUsingMouse=false; + } + else if (selectedItems>1) + d->selectedBySimpleMove=false; + + bool emitSelectionChanged(false); + + switch (e->key()) + { + case Key_Escape: + selectAll(FALSE); + emitSelectionChanged=TRUE; + break; + + case Key_Space: + //toggle selection of current item + if (d->selectedBySimpleMove) + d->selectedBySimpleMove=false; + item->setSelected(!item->isSelected()); + emitSelectionChanged=TRUE; + break; + + case Key_Insert: + //toggle selection of current item and move to the next item + if (d->selectedBySimpleMove) + { + d->selectedBySimpleMove=false; + if (!item->isSelected()) item->setSelected(TRUE); + } + else + { + item->setSelected(!item->isSelected()); + }; + + nextItem=item->itemBelow(); + + if (nextItem!=0) + { + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + }; + d->selectionDirection=1; + emitSelectionChanged=TRUE; + break; + + case Key_Down: + nextItem=item->itemBelow(); + //toggle selection of current item and move to the next item + if (shiftOrCtrl) + { + d->selectionDirection=1; + if (d->selectedBySimpleMove) + d->selectedBySimpleMove=false; + else + { + if (oldSelectionDirection!=-1) + { + item->setSelected(!item->isSelected()); + emitSelectionChanged=TRUE; + }; + }; + } + else if ((d->selectedBySimpleMove) && (nextItem!=0)) + { + item->setSelected(false); + emitSelectionChanged=TRUE; + }; + + if (nextItem!=0) + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + }; + break; + + case Key_Up: + nextItem=item->itemAbove(); + d->selectionDirection=-1; + //move to the prev. item and toggle selection of this one + // => No, can't select the last item, with this. For symmetry, let's + // toggle selection and THEN move up, just like we do in down (David) + if (shiftOrCtrl) + { + if (d->selectedBySimpleMove) + d->selectedBySimpleMove=false; + else + { + if (oldSelectionDirection!=1) + { + item->setSelected(!item->isSelected()); + emitSelectionChanged=TRUE; + }; + } + } + else if ((d->selectedBySimpleMove) && (nextItem!=0)) + { + item->setSelected(false); + emitSelectionChanged=TRUE; + }; + + if (nextItem!=0) + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + }; + break; + + case Key_End: + //move to the last item and toggle selection of all items inbetween + nextItem=item; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + d->selectedBySimpleMove=false; + + while(nextItem!=0) + { + if (shiftOrCtrl) + nextItem->setSelected(!nextItem->isSelected()); + if (nextItem->itemBelow()==0) + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + repaintItem2=nextItem; + visItem=nextItem; + setCurrentItem(nextItem); + } + nextItem=nextItem->itemBelow(); + } + emitSelectionChanged=TRUE; + break; + + case Key_Home: + // move to the first item and toggle selection of all items inbetween + nextItem = firstChild(); + visItem = nextItem; + repaintItem2 = visItem; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + { + d->selectedBySimpleMove=false; + + while ( nextItem != item ) + { + nextItem->setSelected( !nextItem->isSelected() ); + nextItem = nextItem->itemBelow(); + } + item->setSelected( !item->isSelected() ); + } + setCurrentItem( firstChild() ); + emitSelectionChanged=TRUE; + break; + + case Key_Next: + items=visibleHeight()/item->height(); + nextItem=item; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + { + d->selectedBySimpleMove=false; + d->selectionDirection=1; + }; + + for (int i=0; i<items; i++) + { + if (shiftOrCtrl) + nextItem->setSelected(!nextItem->isSelected()); + //the end + if ((i==items-1) || (nextItem->itemBelow()==0)) + + { + if (shiftOrCtrl) + nextItem->setSelected(!nextItem->isSelected()); + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + ensureItemVisible(nextItem); + setCurrentItem(nextItem); + update(); + if ((shiftOrCtrl) || (d->selectedBySimpleMove)) + { + emit selectionChanged(); + } + return; + } + nextItem=nextItem->itemBelow(); + } + break; + + case Key_Prior: + items=visibleHeight()/item->height(); + nextItem=item; + if (d->selectedBySimpleMove) + item->setSelected(false); + if (shiftOrCtrl) + { + d->selectionDirection=-1; + d->selectedBySimpleMove=false; + }; + + for (int i=0; i<items; i++) + { + if ((nextItem!=item) &&(shiftOrCtrl)) + nextItem->setSelected(!nextItem->isSelected()); + //the end + if ((i==items-1) || (nextItem->itemAbove()==0)) + + { + if (d->selectedBySimpleMove) + nextItem->setSelected(true); + ensureItemVisible(nextItem); + setCurrentItem(nextItem); + update(); + if ((shiftOrCtrl) || (d->selectedBySimpleMove)) + { + emit selectionChanged(); + } + return; + } + nextItem=nextItem->itemAbove(); + } + break; + + case Key_Minus: + if ( item->isOpen() ) + setOpen( item, FALSE ); + break; + case Key_Plus: + if ( !item->isOpen() && (item->isExpandable() || item->childCount()) ) + setOpen( item, TRUE ); + break; + default: + bool realKey = ((e->key()!=Key_Shift) && (e->key()!=Key_Control) + && (e->key()!=Key_Meta) && (e->key()!=Key_Alt)); + + bool selectCurrentItem = (d->selectedBySimpleMove) && (item->isSelected()); + if (realKey && selectCurrentItem) + item->setSelected(false); + //this is mainly for the "goto filename beginning with pressed char" feature (aleXXX) + QListView::SelectionMode oldSelectionMode = selectionMode(); + setSelectionMode (QListView::Multi); + QListView::keyPressEvent (e); + setSelectionMode (oldSelectionMode); + if (realKey && selectCurrentItem) + { + currentItem()->setSelected(true); + emitSelectionChanged=TRUE; + } + repaintItem2=currentItem(); + if (realKey) + visItem=currentItem(); + break; + } + + if (visItem) + ensureItemVisible(visItem); + + QRect ir; + if (repaintItem1) + ir = ir.unite( itemRect(repaintItem1) ); + if (repaintItem2) + ir = ir.unite( itemRect(repaintItem2) ); + + if ( !ir.isEmpty() ) + { // rectangle to be repainted + if ( ir.x() < 0 ) + ir.moveBy( -ir.x(), 0 ); + viewport()->repaint( ir, FALSE ); + } + /*if (repaintItem1) + repaintItem1->repaint(); + if (repaintItem2) + repaintItem2->repaint();*/ + update(); + if (emitSelectionChanged) + emit selectionChanged(); +} + +void KListView::setSelectionModeExt (SelectionModeExt mode) +{ + d->selectionMode = mode; + + switch (mode) + { + case Single: + case Multi: + case Extended: + case NoSelection: + setSelectionMode (static_cast<QListView::SelectionMode>(static_cast<int>(mode))); + break; + + case FileManager: + setSelectionMode (QListView::Extended); + break; + + default: + kdWarning () << "Warning: illegal selection mode " << int(mode) << " set!" << endl; + break; + } +} + +KListView::SelectionModeExt KListView::selectionModeExt () const +{ + return d->selectionMode; +} + +int KListView::itemIndex( const QListViewItem *item ) const +{ + if ( !item ) + return -1; + + if ( item == firstChild() ) + return 0; + else { + QListViewItemIterator it(firstChild()); + uint j = 0; + for (; it.current() && it.current() != item; ++it, ++j ); + + if( !it.current() ) + return -1; + + return j; + } +} + +QListViewItem* KListView::itemAtIndex(int index) +{ + if (index<0) + return 0; + + int j(0); + for (QListViewItemIterator it=firstChild(); it.current(); it++) + { + if (j==index) + return it.current(); + j++; + }; + return 0; +} + + +void KListView::emitContextMenu (KListView*, QListViewItem* i) +{ + QPoint p; + qDebug("KListView::emitContextMenu "); + + if (i) + p = viewport()->mapToGlobal(itemRect(i).center()); + else + p = mapToGlobal(rect().center()); + + emit contextMenu (this, i, p); +} + +void KListView::emitContextMenu (QListViewItem* i, const QPoint& p, int) +{ + qDebug("KListView::emitContextMenu "); + emit contextMenu (this, i, p); +} + +void KListView::setAcceptDrops (bool val) +{ + QListView::setAcceptDrops (val); + viewport()->setAcceptDrops (val); +} + +int KListView::dropVisualizerWidth () const +{ + return d->mDropVisualizerWidth; +} + + +void KListView::viewportPaintEvent(QPaintEvent *e) +{ + QListView::viewportPaintEvent(e); + + if (d->mOldDropVisualizer.isValid() && e->rect().intersects(d->mOldDropVisualizer)) + { + QPainter painter(viewport()); + + // This is where we actually draw the drop-visualizer + painter.fillRect(d->mOldDropVisualizer, Dense4Pattern); + } + if (d->mOldDropHighlighter.isValid() && e->rect().intersects(d->mOldDropHighlighter)) + { + QPainter painter(viewport()); + +qDebug("KListView::viewportPaintEvent has to be verified"); + + // This is where we actually draw the drop-highlighter +//US style().drawPrimitive(QStyle::PE_FocusRect, &painter, d->mOldDropHighlighter, colorGroup(), +//US QStyle::Style_FocusAtBorder); + +//LR style().drawFocusRect(&painter, d->mOldDropHighlighter, colorGroup(), (const QColor*)0, true); + + + } +} + +void KListView::setFullWidth() +{ + setFullWidth(true); +} + +void KListView::setFullWidth(bool fullWidth) +{ + d->fullWidth = fullWidth; +//US header()->setStretchEnabled(fullWidth, columns()-1); +} + +bool KListView::fullWidth() const +{ + return d->fullWidth; +} + +int KListView::addColumn(const QString& label, int width) +{ + int result = QListView::addColumn(label, width); + if (d->fullWidth) { +//US header()->setStretchEnabled(false, columns()-2); +//US header()->setStretchEnabled(true, columns()-1); + } + return result; +} + +int KListView::addColumn(const QIconSet& iconset, const QString& label, int width) +{ + int result = QListView::addColumn(iconset, label, width); + if (d->fullWidth) { +//US header()->setStretchEnabled(false, columns()-2); +//US header()->setStretchEnabled(true, columns()-1); + } + return result; +} + +void KListView::removeColumn(int index) +{ + QListView::removeColumn(index); +//US if (d->fullWidth && index == columns()) header()->setStretchEnabled(true, columns()-1); +} + +void KListView::viewportResizeEvent(QResizeEvent* e) +{ + QListView::viewportResizeEvent(e); +} + +const QColor &KListView::alternateBackground() const +{ + return d->alternateBackground; +} + +void KListView::setAlternateBackground(const QColor &c) +{ + d->alternateBackground = c; + repaint(); +} + +void KListView::saveLayout(KConfig *config, const QString &group) const +{ + KConfigGroupSaver saver(config, group); + QStringList widths, order; + for (int i = 0; i < columns(); ++i) + { + widths << QString::number(columnWidth(i)); + order << QString::number(header()->mapToIndex(i)); + } + config->writeEntry("ColumnWidths", widths); + config->writeEntry("ColumnOrder", order); + config->writeEntry("SortColumn", d->sortColumn); + config->writeEntry("SortAscending", d->sortAscending); +} + +void KListView::restoreLayout(KConfig *config, const QString &group) +{ + KConfigGroupSaver saver(config, group); + QStringList cols = config->readListEntry("ColumnWidths"); + int i = 0; + for (QStringList::ConstIterator it = cols.begin(); it != cols.end(); ++it) + setColumnWidth(i++, (*it).toInt()); + + cols = config->readListEntry("ColumnOrder"); + i = 0; + for (QStringList::ConstIterator it = cols.begin(); it != cols.end(); ++it) + header()->moveSection(i++, (*it).toInt()); + +/*US I changed the following code, because hasKey is not available. +!!! check if my version is correct + if (config->hasKey("SortColumn")) + setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true)); +*/ + QStringList langLst = config->readListEntry( "SortColumn" ); + if (!langLst.isEmpty()) + setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true)); +} + +void KListView::setSorting(int column, bool ascending) +{ + d->sortColumn = column; + d->sortAscending = ascending; + QListView::setSorting(column, ascending); +} + +int KListView::columnSorted(void) const +{ + return d->sortColumn; +} + +bool KListView::ascendingSort(void) const +{ + return d->sortAscending; +} + +KListViewItem::KListViewItem(QListView *parent) + : QListViewItem(parent) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent) + : QListViewItem(parent) +{ + init(); +} + +KListViewItem::KListViewItem(QListView *parent, QListViewItem *after) + : QListViewItem(parent, after) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after) + : QListViewItem(parent, after) +{ + init(); +} + +KListViewItem::KListViewItem(QListView *parent, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::KListViewItem(QListView *parent, QListViewItem *after, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, QString label8) + : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8) +{ + init(); +} + +KListViewItem::~KListViewItem() +{ +} + +void KListViewItem::init() +{ + m_known = false; +} + +const QColor &KListViewItem::backgroundColor() +{ + if (isAlternate()) + return static_cast< KListView* >(listView())->alternateBackground(); + return listView()->viewport()->colorGroup().base(); +} + +bool KListViewItem::isAlternate() +{ + KListView *lv = static_cast<KListView *>(listView()); + if (lv && lv->alternateBackground().isValid()) + { + KListViewItem *above = 0; +//US above = dynamic_cast<KListViewItem *>(itemAbove()); + above = (KListViewItem *)(itemAbove()); + m_known = above ? above->m_known : true; + if (m_known) + { + m_odd = above ? !above->m_odd : false; + } + else + { + KListViewItem *item; + bool previous = true; + if (parent()) + { +//US item = dynamic_cast<KListViewItem *>(parent()); + item = (KListViewItem *)(parent()); + if (item) + previous = item->m_odd; +//US item = dynamic_cast<KListViewItem *>(parent()->firstChild()); + item = (KListViewItem *)(parent()->firstChild()); + } + else + { +//US item = dynamic_cast<KListViewItem *>(lv->firstChild()); + item = (KListViewItem *)(lv->firstChild()); + } + + while(item) + { + item->m_odd = previous = !previous; + item->m_known = true; +//US item = dynamic_cast<KListViewItem *>(item->nextSibling()); + item = (KListViewItem *)(item->nextSibling()); + } + } + return m_odd; + } + return false; +} + +void KListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + QColorGroup _cg = cg; + const QPixmap *pm = listView()->viewport()->backgroundPixmap(); + if (pm && !pm->isNull()) + { + _cg.setBrush(QColorGroup::Base, QBrush(backgroundColor(), *pm)); + QPoint o = p->brushOrigin(); + p->setBrushOrigin( o.x()-listView()->contentsX(), o.y()-listView()->contentsY() ); + } + else if (isAlternate()) { +//US if (listView()->viewport()->backgroundMode()==Qt::FixedColor) + if (listView()->viewport()->backgroundMode()==QWidget::PaletteBackground) + _cg.setColor(QColorGroup::Background, static_cast< KListView* >(listView())->alternateBackground()); + else + _cg.setColor(QColorGroup::Base, static_cast< KListView* >(listView())->alternateBackground()); + } + QListViewItem::paintCell(p, _cg, column, width, alignment); +} + +void KListView::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "klistview.moc" +//US #include "klistviewlineedit.moc" + +// vim: ts=2 sw=2 et diff --git a/microkde/kdeui/klistview.h b/microkde/kdeui/klistview.h new file mode 100644 index 0000000..f7d9f85 --- a/dev/null +++ b/microkde/kdeui/klistview.h @@ -0,0 +1,1033 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2000 Charles Samuels <charles@kde.org> + Copyright (C) 2000 Peter Putzer <putzer@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KLISTVIEW_H +#define KLISTVIEW_H + +#include <qlistview.h> + +#include <qptrlist.h> + +//US +class QDropEvent; +class QDragLeaveEvent; +class QDragMoveEvent; +class QDragEnterEvent; + +class QDragObject; +class KConfig; +class KLineEdit; +/** + * This Widget extends the functionality of QListView to honor the system + * wide settings for Single Click/Double Click mode, AutoSelection and + * ChangeCursorOverLink (TM). + * + * There is a new signal executed(). It gets connected to either + * @ref QListView::clicked() or @ref QListView::doubleClicked() depending on the KDE + * wide Single Click/Double Click settings. It is strongly recommended that + * you use this signal instead of the above mentioned. This way you dont + * need to care about the current settings. + * If you want to get informed when the user selects something connect to the + * QListView::selectionChanged() signal. + * + * Drag-and-Drop is supported with the signal @ref #dropped(), just @ref #setAcceptDrops(true) + * and connect it to a suitable slot. + * To see where you are dropping, @ref setDropVisualizer(true). + * And also you'll need @ref acceptDrag(QDropEvent*) + * + * KListView is drag-enabled, too: to benefit from that you've got derive from it. + * Reimplement @ref dragObject() and (possibly) @ref startDrag(), + * and @ref setDragEnabled(true). + * + * @version $Id$ + */ +class KListView : public QListView +{ + Q_OBJECT + Q_ENUMS( SelectionModeExt ) + Q_PROPERTY( bool fullWidth READ fullWidth WRITE setFullWidth ) + Q_PROPERTY( bool itemsMovable READ itemsMovable WRITE setItemsMovable ) + Q_PROPERTY( bool itemsRenameable READ itemsRenameable WRITE setItemsRenameable ) + Q_PROPERTY( bool dragEnabled READ dragEnabled WRITE setDragEnabled ) + Q_PROPERTY( bool autoOpen READ autoOpen WRITE setAutoOpen ) + Q_PROPERTY( bool dropVisualizer READ dropVisualizer WRITE setDropVisualizer ) +//US Q_PROPERTY( int tooltipColumn READ tooltipColumn WRITE setTooltipColumn ) + Q_PROPERTY( int dropVisualizerWidth READ dropVisualizerWidth WRITE setDropVisualizerWidth ) + Q_PROPERTY( QColor alternateBackground READ alternateBackground WRITE setAlternateBackground ) + + Q_OVERRIDE( SelectionModeExt selectionMode READ selectionModeExt WRITE setSelectionModeExt ) + +public: + /** + * Possible selection modes. + * + * The first four correspond directly to QListView::SelectionMode, while + * the FileManager selection mode is defined as follows: + * @li home: move to the first + * @li end: move to the last + * @li PgUp/PgDn: move one page up/down + * @li up/down: move one item up/down + * @li insert: toggle selection of current and move to the next + * @li space: toggle selection of the current + * @li CTRL+up: move to the previous item and toggle selection of this one + * @li CTRL+down: toggle selection of the current item and move to the next + * @li CTRL+end: toggle selection from (including) the current + * item to (including) the last item + * @li CTRL+home: toggle selection from (including) the current + * item to the (including) the first item + * @li CTRL+PgDn: toggle selection from (including) the current + * item to (excluding) the item one page down + * @li CTRL+PgUp: toggle selection from (excluding) the current + * item to (including) the item one page up + * + * The combinations work the same with SHIFT instead of CTRL, except + * that if you start selecting something using SHIFT everything selected + * before will be deselected first. + * + * Additionally the current item is always selected automatically when + * navigating using the keyboard, except other items were selected explicitely. + * + * This way e.g. SHIFT+up/PgUp then SHIFT+down/PgDn leaves no item selected + */ + enum SelectionModeExt { + Single = QListView::Single, + Multi = QListView::Multi, + Extended = QListView::Extended, + NoSelection = QListView::NoSelection, + FileManager + }; + void repaintContents( bool erase = true ) + { + QScrollView::repaintContents( contentsX(), contentsY(), + visibleWidth(), visibleHeight(), erase ); + }; + /** + * Constructor. + * + * The parameters @p parent and @p name are handled by + * @ref QListView, as usual. + */ + KListView (QWidget *parent = 0, const char *name = 0); + + /** + * Destructor. + */ + virtual ~KListView(); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void setAcceptDrops (bool); + + /** + * This function determines whether the given coordinates are within the + * execute area. The execute area is the part of a @ref QListViewItem where mouse + * clicks or double clicks respectively generate a @ref #executed() signal. + * Depending on @ref QListView::allColumnsShowFocus() this is either the + * whole item or only the first column. + * @return true if point is inside execute area of an item, false in all + * other cases including the case that it is over the viewport. + */ + virtual bool isExecuteArea( const QPoint& point ); + + /** + * Same thing, but from an x coordinate only. This only checks if x is in + * the first column (if all columns don't show focus), without testing if + * the y coordinate is over an item or not. + */ + bool isExecuteArea( int x ); + + /** + * @return a list containing the currently selected items. + */ + QPtrList<QListViewItem> selectedItems() const; // ### BIC: KDE 4: use an implicitly shared class! (QValueList?) + + /** + * Arbitrarily move @p item to @p parent, positioned immediately after item @p after. + */ + void moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after); + + /** + * @return the last item (not child!) of this listview. + * + * @see lastChild() + */ + QListViewItem *lastItem() const; + + /** + * @return the last child of this listview. + * + * @see lastItem() + */ + QListViewItem* lastChild () const; + + /** + * @return the lineedit used for inline renaming. + * Use that to setup a @ref KCompletion or @ref QValidator for the lineedit + * + * @since 3.2 + */ + KLineEdit* renameLineEdit() const; + + /** + * @returns if it is legal to move items in the list view. True by default. + * + * @see #setDragEnabled() + * @see #setItemsMovable() + */ + bool itemsMovable() const; + + /** + * @return whether inplace-renaming has been enabled. False by default. + * + * @see #setItemsRenameable() + */ + bool itemsRenameable() const; + + /** + * @return whether dragging is enabled. False by default. + * + * @see #setDragEnabled() + */ + bool dragEnabled() const; + + /** + * @return true if AutoOpen is enabled (not implemented currently). + * + * @see #setAutoOpen() + */ + bool autoOpen() const; + + /** + * @return true if @p column is renamable. + * + * @see #setRenameable() + */ + bool isRenameable (int column) const; + + /** + * @return true if drawing of the drop-visualizer has been enabled. True by default. + * + * @see #setDropVisualizer() + */ + bool dropVisualizer() const; + + /** + * @return the column for which tooltips are displayed (or -1 if none set). + * + * @see #setTooltipColumn() + */ + int tooltipColumn() const; + + /** + * For future expansions. + * + * Do not use. + * @deprecated + */ + bool createChildren() const; + + /** + * @return true if drawing of the drop-highlighter has been enabled. False by default. + * + * @see #setDropHighlighter() + */ + bool dropHighlighter() const; + + /** + * The dropVisualizerWidth defaults to 4. + * + * @see #setDropVisualizerWidth() + * @return the current width of the drop-visualizer. + */ + int dropVisualizerWidth () const; + + /** + * @return the "extended" selection mode of this listview. + * + * @see SelectionModeExt + * @see setSelectionModeExt + */ + SelectionModeExt selectionModeExt () const; + + /** + * Returns the index of @p item within the item tree or -1 if + * @p item doesn't exist in this list view. This function takes + * all items into account not only the visible ones. + */ + int itemIndex( const QListViewItem *item ) const; + + /** + * Returns the item of @p index within the item tree or 0 if + * @p index doesn't exist in this list view. This function takes + * all items into account not only the visible ones. + */ + QListViewItem* itemAtIndex(int index); + + /** + * @deprecated + * @see #setFullWidth() + */ + void setFullWidth(); + + /** + * Let the last column fit exactly all the available width. + * + * @see #fullWidth() + */ + void setFullWidth(bool fullWidth); + + /** + * Returns whether the last column is set to fit the available width. + * + * @see #setFullWidth() + */ + bool fullWidth() const; + + /** + * Reimplemented for full width support + * + * @see #removeColumn() + */ + virtual int addColumn(const QString& label, int width = -1); + /** + * Reimplemented for full width support + */ + virtual int addColumn(const QIconSet& iconset, const QString& label, int width = -1); + /** + * Reimplemented for full width support + * + * @see #addColumn() + */ + virtual void removeColumn(int index); + + /** + * sets the alternate background background color. + * This only has an effect if the items are KListViewItems + * + * @param c the color to use for every other item. Set to an invalid + * colour to disable alternate colours. + * + * @see #alternateBackground() + **/ + void setAlternateBackground(const QColor &c); + /** + * @return the alternate background color + * + * @see #setAlternateBackground() + */ + const QColor &alternateBackground() const; + + /** + * Saves the list view's layout (column widtsh, column order, sort column) + * to a KConfig group + * + * @param config the @ref KConfig object to write to + * @param group the config group to use + */ + void saveLayout(KConfig *config, const QString &group) const; + /** + * Reads the list view's layout from a KConfig group as stored with + * @ref #saveLayout + * + * @param config the @ref KConfig object to read from + * @param group the config group to use + */ + void restoreLayout(KConfig *config, const QString &group); + /** + * Reimplemented to remember the current sort column and order. + * @param column is the column to be sorted, or -1 to sort in order of + * insertion + * @param whether to sort ascending (or descending) + */ + virtual void setSorting(int column, bool ascending = true); + + /** + * @return the currently sorted column, or -1 if none is sorted + */ + int columnSorted(void) const; + + /** + * @return whether the current sort is ascending (or descending) + */ + bool ascendingSort(void) const; + +signals: + + /** + * This signal is emitted whenever the user executes an listview item. + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listview item. + * + * Note that you may not delete any @ref QListViewItem objects in slots + * connected to this signal. + */ + void executed( QListViewItem *item ); + + /** + * This signal is emitted whenever the user executes an listview item. + * That means depending on the KDE wide Single Click/Double Click + * setting the user clicked or double clicked on that item. + * @param item is the pointer to the executed listview item. + * @param pos is the position where the user has clicked + * @param c is the column into which the user clicked. + * + * Note that you may not delete any @ref QListViewItem objects in slots + * connected to this signal. + */ + void executed( QListViewItem *item, const QPoint &pos, int c ); + + /** + * This signal gets emitted whenever the user double clicks into the + * listview. + * @param item is the pointer to the clicked listview item. + * @param pos is the position where the user has clicked, and + * @param c is the column into which the user clicked. + * + * Note that you may not delete any @ref QListViewItem objects in slots + * connected to this signal. + * + * This signal is more or less here for the sake of completeness. + * You should normally not need to use this. In most cases its better + * to use @ref #executed() instead. + */ + void doubleClicked( QListViewItem *item, const QPoint &pos, int c ); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * @param e is the drop event itself (it has already been accepted) + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items) + * + * @see #acceptDrop() + */ + void dropped (QDropEvent * e, QListViewItem *after); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * This is an overloaded version of the above (provided to simplify + * processing drops outside of the class). + * + * @param list is the listview + * @param e is the drop event itself (it has already been accepted) + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items + */ + void dropped (KListView* list, QDropEvent* e, QListViewItem* after); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * This function also provides a parent, in the event that your listview + * is a tree + * @param list is the listview + * @param e is the drop event itself (it has already been accepted) + * @param parent the item that is to be the parent of the new item + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items + */ + void dropped (KListView* list, QDropEvent* e, QListViewItem* parent, QListViewItem* after); + + /** + * This signal gets emitted whenever something acceptable is + * dropped onto the listview. + * + * This function also provides a parent, in the event that your listview + * is a tree + * @param e is the drop event itself (it has already been accepted) + * @param parent the item that is to be the parent of the new item + * @param after is the item after which the drop occured (or 0L, if + * the drop was above all items + */ + void dropped (QDropEvent* e, QListViewItem* parent, QListViewItem* after); + + /** + * This signal is emitted when ever the user moves an item in the list via + * DnD. + * If more than one item is moved at the same time, this signal is only emitted + * once. + */ + void moved(); + + /** + * Connect to this signal if you want to do some preprocessing before + * a move is made, for example, to disable sorting + * + * This is sent only once per each groups of moves. That is, for each + * drop that is a move this will be emitted once, before KListView calls + * @see moveItem() + */ + void aboutToMove(); + + /** + * This signal is emitted when ever the user moves an item in the list via + * DnD. + * If more than one item is moved at the same time, @p afterFirst and + * @p afterNow will reflect what was true before the move. + * This differs from @ref moved(), so be careful. All the items will have been + * moved before @ref moved() is emitted, which is not true in this method. // FIXME + * @param item the item that was moved + * @param afterFirst the item that parameter item was in before the move, in the list + * @param afterNow the item it's currently after. + */ + void moved (QListViewItem *item, QListViewItem *afterFirst, QListViewItem *afterNow); + + + /** + * This signal is emitted after all the items have been moved. It reports info for + * each and every item moved, in order. The first element in @p items associates + * with the first of afterFirst and afterNow. + */ + void moved(QPtrList<QListViewItem> &items, QPtrList<QListViewItem> &afterFirst, QPtrList<QListViewItem> &afterNow); + + /** + * This signal gets emitted when an item is renamed via in-place renaming. + * + * @param item is the renamed item. + * @param str is the new value of column @p col. + * @param col is the renamed column. + */ + void itemRenamed(QListViewItem* item, const QString &str, int col); + + /** + * Same as above, but without the extra information. + */ + void itemRenamed(QListViewItem* item); + void signalDelete(); + + /** + * This signal is emitted when the shortcut key for popup-menus is pressed. + * + * Normally you should not use this, just connect a slot to signal + * @ref contextMenu (KListView*, QListViewItem*, const QPoint&) to correctly + * handle showing context menus regardless of settings. + * + * @param list is this listview. + * @param item is the @ref currentItem() at the time the key was pressed. May be 0L. + */ + void menuShortCutPressed (KListView* list, QListViewItem* item); + + /** + * This signal is emitted whenever a context-menu should be shown for item @p i. + * It automatically adjusts for all settings involved (Menu key, showMenuOnPress/Click). + * + * @param l is this listview. + * @param i is the item for which the menu should be shown. May be 0L. + * @param p is the point at which the menu should be shown. + */ + void contextMenu (KListView* l, QListViewItem* i, const QPoint& p); + +public slots: + /** + * Rename column @p c of @p item. + */ + virtual void rename(QListViewItem *item, int c); + + /** + * By default, if you called setItemsRenameable(true), + * only the first column is renameable. + * Use this function to enable the feature on other columns. + * + * If you want more intelligent (dynamic) selection, + * you'll have to derive from KListView, + * and override @ref rename() and call only call it + * if you want the item to be renamed. + */ + void setRenameable (int column, bool yesno=true); + + /** + * Set whether items in the list view can be moved. + * It is enabled by default. + * + * @see itemsMovable() + */ + virtual void setItemsMovable(bool b); + + /** + * Enables inplace-renaming of items. + * It is disabled by default. + * + * @see itemsRenameable() + * @see setRenameable() + */ + virtual void setItemsRenameable(bool b); + + /** + * Enable/Disable the dragging of items. + * It is disabled by default. + */ + virtual void setDragEnabled(bool b); + + /** + * Enable/Disable AutoOpen (not implemented currently). + */ + virtual void setAutoOpen(bool b); + + /** + * Enable/Disable the drawing of a drop-visualizer + * (a bar that shows where a dropped item would be inserted). + * It is enabled by default, if dragging is enabled + */ + virtual void setDropVisualizer(bool b); + + /** + * Set the width of the (default) drop-visualizer. + * If you don't call this method, the width is set to 4. + */ + void setDropVisualizerWidth (int w); + + /** + * Set which column should be used for automatic tooltips. + * + * @param column is the column for which tooltips will be shown. + * Set -1 to disable this feature. + */ + virtual void setTooltipColumn(int column); + + /** + * Enable/Disable the drawing of a drop-highlighter + * (a rectangle around the item under the mouse cursor). + * It is disabled by default. + */ + virtual void setDropHighlighter(bool b); + + /** + * For future expansions. + * + * Do not use. + * @deprecated + */ + virtual void setCreateChildren(bool b); + + /** + * Set the selection mode. + * + * A different name was chosen to avoid API-clashes with @ref QListView::setSelectionMode(). + */ + void setSelectionModeExt (SelectionModeExt mode); + + /** + * Enable/disable tabbing between editable cells + * @since 3.1 + */ + void setTabOrderedRenaming(bool b); + + /** + * Returns whether tab ordered renaming is enabled + * @since 3.1 + */ + bool tabOrderedRenaming() const; + +protected: + /** + * Determine whether a drop on position @p p would count as + * being above or below the QRect @p rect. + * + * @param rect is the rectangle we examine. + * @param p is the point located in the rectangle, p is assumed to be in + * viewport coordinates. + */ + inline bool below (const QRect& rect, const QPoint& p) + { + return (p.y() > (rect.top() + (rect.bottom() - rect.top())/2)); + } + + /** + * An overloaded version of below(const QRect&, const QPoint&). + * + * It differs from the above only in what arguments it takes. + * + * @param i the item whose rect() is passed to the above function. + * @param p is translated from contents coordinates to viewport coordinates + * before being passed to the above function. + */ + inline bool below (QListViewItem* i, const QPoint& p) + { + return below (itemRect(i), contentsToViewport(p)); + } + + /** + * Reimplemented to reload the alternate background in palette changes. + * @internal + */ + virtual bool event( QEvent * ); + + /** + * Emit signal @ref #executed. + * @internal + */ + void emitExecute( QListViewItem *item, const QPoint &pos, int c ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void focusInEvent(QFocusEvent* fe); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void focusOutEvent( QFocusEvent *fe ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void leaveEvent( QEvent *e ); + + /** + * @return the tooltip for @p column of @p item. + */ + virtual QString tooltip(QListViewItem* item, int column) const; + + /** + * @return whether the tooltip for @p column of @p item shall be shown at point @p pos. + */ + virtual bool showTooltip(QListViewItem *item, const QPoint &pos, int column) const; + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDragMoveEvent (QDragMoveEvent *event); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMousePressEvent( QMouseEvent *e ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMouseMoveEvent( QMouseEvent *e ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e ); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDragLeaveEvent (QDragLeaveEvent *event); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsMouseReleaseEvent (QMouseEvent*); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDropEvent (QDropEvent*); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void contentsDragEnterEvent (QDragEnterEvent *); + + /** + * @return a dragobject encoding the current selection. + * + * @see setDragEnabled() + */ + virtual QDragObject *dragObject(); + + /** + * @return true if the @p event provides some acceptable + * format. + * A common mistake is to forget the "const" in your reimplementation + */ + virtual bool acceptDrag (QDropEvent* event) const; + + /** + * Paint the drag line. If painter is null, don't try to :) + * + * If after == 0 then the marker should be drawn at the top. + * + * @return the rectangle that you painted to. + */ + virtual QRect drawDropVisualizer (QPainter *p, QListViewItem *parent, QListViewItem *after); + + /** + * Paint the drag rectangle. If painter is null, don't try to :) + * + * + * @return the rectangle that you painted to. + */ + virtual QRect drawItemHighlighter(QPainter *painter, QListViewItem *item); + + /** + * This method calls @ref dragObject() and starts the drag. + * + * Reimplement it to do fancy stuff like setting a pixmap or + * using a non-default DragMode + */ + virtual void startDrag(); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void keyPressEvent (QKeyEvent*); + + /** + * Reimplemented for internal reasons. + * Further reimplementations should call this function or else + * some features may not work correctly. + * + * The API is unaffected. + */ + virtual void viewportPaintEvent(QPaintEvent*); + + /** + * In FileManager selection mode: explicitely activate the mode + * in which the current item is automatically selected. + */ + void activateAutomaticSelection(); + /** + * In FileManager selection mode: explicitely deactivate the mode + * in which the current item is automatically selected. + */ + void deactivateAutomaticSelection(); + /** + * In FileManager selection mode: return whether it is currently in the mode + * where the current item is selected automatically. + * Returns false if items were selected explicitely, e.g. using the mouse. + */ + bool automaticSelection() const; + + /** + * Reimplemented for setFullWidth() + */ + virtual void viewportResizeEvent(QResizeEvent* e); + +protected slots: + /** + * Update internal settings whenever the global ones change. + * @internal + */ + void slotSettingsChanged(int); + + void slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c ); + void doneEditing(QListViewItem *item, int row); + + /** + * Repaint the rect where I was drawing the drop line. + */ + void cleanDropVisualizer(); + + /** + * Repaint the rect where I was drawing the drop rectangle. + */ + void cleanItemHighlighter(); + + /** + * Emit the @ref contextMenu signal. This slot is for mouse actions. + */ + void emitContextMenu (QListViewItem*, const QPoint&, int); + + /** + * Emit the @ref #contextMenu signal. This slot is for key presses. + */ + void emitContextMenu (KListView*, QListViewItem*); + + /** + * Accessory slot for AutoSelect + * @internal + */ + void slotOnItem( QListViewItem *item ); + + /** + * Accessory slot for AutoSelect/ChangeCursorOverItem + * @internal + */ + void slotOnViewport(); + + /** + * Process AutoSelection. + * @internal + */ + void slotAutoSelect(); + + void slotDragExpand(); + + /** + * Reacts to header changes in full width mode + * @internal + */ + void slotHeaderChanged(); + +protected: + /** + * Handle dropEvent when itemsMovable() is set to true. + */ + virtual void movableDropEvent (QListViewItem* parent, QListViewItem* afterme); + + /** + * Where is the nearest QListViewItem that I'm going to drop? + * + * FIXME KDE 4.0: Make this method const so it can be called from an + * acceptDrag method without ugly casts + */ + virtual void findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after); + + /** + * A special keyPressEvent (for FileManager selection mode). + */ + void fileManagerKeyPressEvent (QKeyEvent*); + + /** + * Convert the depth of an item into its indentation in pixels + */ + int depthToPixels( int depth ); + +private: + class Tooltip; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KListViewPrivate; + KListViewPrivate *d; +}; + +/** + * A listview item with support for alternate background colours. It is + * a drop-in replacement for @ref QListViewItem + * + * @short listview item with alternate background colour support + */ +class KListViewItem : public QListViewItem +{ +public: + /** + * constructors. The semantics remain as in @ref QListViewItem. + * Although they accept a @ref QListViewItem as parent, please + * don't mix KListViewItem (or subclasses) with QListViewItem + * (or subclasses). + */ + KListViewItem(QListView *parent); + KListViewItem(QListViewItem *parent); + KListViewItem(QListView *parent, QListViewItem *after); + KListViewItem(QListViewItem *parent, QListViewItem *after); + + KListViewItem(QListView *parent, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + KListViewItem(QListViewItem *parent, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + KListViewItem(QListView *parent, QListViewItem *after, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + KListViewItem(QListViewItem *parent, QListViewItem *after, + QString, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null, + QString = QString::null, QString = QString::null); + + virtual ~KListViewItem(); + + /** + * retuns true if this item is to be drawn with the alternate background + */ + bool isAlternate(); + /** + * returns the background colour for this item + */ + const QColor &backgroundColor(); + + virtual void paintCell(QPainter *p, const QColorGroup &cg, + int column, int width, int alignment); + +private: + void init(); + +private: + uint m_odd : 1; + uint m_known : 1; + uint m_unused : 30; +}; + +#endif + +// vim: ts=2 sw=2 et diff --git a/microkde/kdeui/kmainwindow.cpp b/microkde/kdeui/kmainwindow.cpp new file mode 100644 index 0000000..3a2a4d0 --- a/dev/null +++ b/microkde/kdeui/kmainwindow.cpp @@ -0,0 +1,994 @@ + /* This file is part of the KDE libraries + Copyright + (C) 2000 Reginald Stadlbauer (reggie@kde.org) + (C) 1997 Stephan Kulow (coolo@kde.org) + (C) 1997-2000 Sven Radej (radej@kde.org) + (C) 1997-2000 Matthias Ettrich (ettrich@kde.org) + (C) 1999 Chris Schlaeger (cs@kde.org) + (C) 2002 Joseph Wenninger (jowenn@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ +#include <qobjectlist.h> +#include <qstringlist.h> +#include <qtimer.h> +#include <qmenubar.h> +#include <qstatusbar.h> +#include <qapplication.h> + + +#include "kdebug.h" +#include "kmainwindow.h" +#include "kglobalsettings.h" +#include "kactioncollection.h" + +class KMainWindowPrivate { +public: +//US bool showHelpMenu:1; + + bool autoSaveSettings:1; + bool settingsDirty:1; + bool autoSaveWindowSize:1; + bool care_about_geometry:1; + QString autoSaveGroup; +//US KAccel * kaccel; +//US KMainWindowInterface *m_interface; + KDEPrivate::ToolBarHandler *toolBarHandler; + QTimer* settingsTimer; + KToggleAction *showStatusBarAction; + QRect defaultWindowSize; +}; + +static bool no_query_exit = false; + +KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f ) + : QMainWindow( parent, name, f )/*US, KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )*/ +{ + mQToolBar = 0; + initKMainWindow(name); +} + +void KMainWindow::parseGeometry(bool parsewidth) +{ +//US the following code is not getting used in the embedded version !! So disable it for now +/*US + + assert ( !kapp->geometryArgument().isNull() ); + assert ( d->care_about_geometry ); + +#ifndef Q_WS_QWS + // FIXME: (E) Implement something similar for Qt Embedded (or decide we don't need it) + int x, y; + int w, h; + int m = XParseGeometry( kapp->geometryArgument().latin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h); + if (parsewidth) { + QSize minSize = minimumSize(); + QSize maxSize = maximumSize(); + if ( (m & WidthValue) == 0 ) + w = width(); + if ( (m & HeightValue) == 0 ) + h = height(); + w = QMIN(w,maxSize.width()); + h = QMIN(h,maxSize.height()); + w = QMAX(w,minSize.width()); + h = QMAX(h,minSize.height()); + resize(w, h); + } else { + if ( parsewidth && (m & XValue) == 0 ) + x = geometry().x(); + if ( parsewidth && (m & YValue) == 0 ) + y = geometry().y(); + if ( (m & XNegative) ) + x = KApplication::desktop()->width() + x - w; + if ( (m & YNegative) ) + y = KApplication::desktop()->height() + y - h; + move(x, y); + } +#endif +*/ +} + +KMainWindow::~KMainWindow() +{ + delete d->settingsTimer; + QMenuBar* mb = internalMenuBar(); + delete mb; +//US delete d->m_interface; + + delete d; +//US memberList->remove( this ); +} + +void KMainWindow::initKMainWindow(const char *name) +{ + setDockMenuEnabled( FALSE ); +//US mHelpMenu = 0; + +//US kapp->setTopWidget( this ); + actionCollection()->setWidget( this ); +//US connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); +//US if( !memberList ) +//US memberList = new QPtrList<KMainWindow>; +/*US + + if ( !ksm ) + ksm = ksmd.setObject(new KMWSessionManaged()); + // set a unique object name. Required by session management. + QCString objname; + QCString s; + int unusedNumber; + if ( !name ) + { // no name given + objname = kapp->instanceName() + "-mainwindow#"; + s = objname + '1'; // start adding number immediately + unusedNumber = 1; + } + else if( name[ strlen( name ) - 1 ] == '#' ) + { // trailing # - always add a number + objname = name; + s = objname + '1'; // start adding number immediately + unusedNumber = 1; + } + else + { + objname = name; + s = objname; + unusedNumber = 0; // add numbers only when needed + } + for(;;) { + QWidgetList* list = kapp->topLevelWidgets(); + QWidgetListIt it( *list ); + bool found = false; + for( QWidget* w = it.current(); + w != NULL; + ++it, w = it.current()) + if( w != this && w->name() == s ) + { + found = true; + break; + } + delete list; + if( !found ) + break; + s.setNum( ++unusedNumber ); + s = objname + s; + } + setName( s ); + memberList->append( this ); +*/ + + d = new KMainWindowPrivate; +//US d->showHelpMenu = true; + d->settingsDirty = false; + d->autoSaveSettings = false; + d->autoSaveWindowSize = true; // for compatibility +//US d->kaccel = actionCollection()->kaccel(); + d->toolBarHandler = 0; + d->settingsTimer = 0; + d->showStatusBarAction = NULL; +/*US + if ((d->care_about_geometry == beeing_first)) { + beeing_first = false; + if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater + d->care_about_geometry = false; + else + parseGeometry(false); + } +*/ + d->care_about_geometry = false; + +//US setCaption( kapp->caption() ); + // attach dcop interface +//US d->m_interface = new KMainWindowInterface(this); + +//US if (!kapp->authorize("movable_toolbars")) +//US setDockWindowsMovable(false); +} + +KAction *KMainWindow::toolBarMenuAction() +{ + if ( !d->toolBarHandler ) + return 0; + + return d->toolBarHandler->toolBarMenuAction(); +} + +bool KMainWindow::canBeRestored( int number ) +{ +/*US we do not have and want to save sessioninformation. Use info from the default +application config. +*/ +//US if ( !kapp->isRestored() ) +//US return FALSE; +//US KConfig *config = kapp->sessionConfig(); + KConfig *config = KGlobal::config(); + if ( !config ) + return FALSE; + config->setGroup( QString::fromLatin1("Number") ); + int n = config->readNumEntry( QString::fromLatin1("NumberOfWindows") , 1 ); + return number >= 1 && number <= n; + +} + +const QString KMainWindow::classNameOfToplevel( int number ) +{ +/*US we do not have and want to save sessioninformation. Use info from the default +application config. +*/ +//US if ( !kapp->isRestored() ) +//US return QString::null; +//US KConfig *config = kapp->sessionConfig(); + KConfig *config = KGlobal::config(); + if ( !config ) + return QString::null; + QString s; + s.setNum( number ); + s.prepend( QString::fromLatin1("WindowProperties") ); + config->setGroup( s ); + if ( !config->hasKey( QString::fromLatin1("ClassName") ) ) + return QString::null; + else + return config->readEntry( QString::fromLatin1("ClassName") ); +} + +bool KMainWindow::restore( int number, bool show ) +{ +/*US we do not have and want to save sessioninformation. Use info from the default +application config. +*/ + if ( !canBeRestored( number ) ) + return FALSE; +//US KConfig *config = kapp->sessionConfig(); + KConfig *config = KGlobal::config(); + + if ( readPropertiesInternal( config, number ) ){ + if ( show ) + KMainWindow::show(); + return FALSE; + } + return FALSE; + +} + +void KMainWindow::setCaption( const QString &caption ) +{ +//US setPlainCaption( kapp->makeStdCaption(caption) ); + setPlainCaption( caption ); +} + +void KMainWindow::setCaption( const QString &caption, bool modified ) +{ +//US setPlainCaption( kapp->makeStdCaption(caption, true, modified) ); + setPlainCaption( caption + "modified:" ); +} + +void KMainWindow::setPlainCaption( const QString &caption ) +{ + QMainWindow::setCaption( caption ); +#ifndef Q_WS_QWS +//US the following is disabled for the embedded version +//US NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 ); +//US info.setName( caption.utf8().data() ); +#endif +} + +void KMainWindow::slotStateChanged(const QString &newstate) +{ + stateChanged(newstate, KXMLGUIClient::StateNoReverse); +} + +/* + * Get rid of this for KDE 4.0 + */ +void KMainWindow::slotStateChanged(const QString &newstate, + KXMLGUIClient::ReverseStateChange reverse) +{ + stateChanged(newstate, reverse); +} + +void KMainWindow::closeEvent ( QCloseEvent *e ) +{ + // Save settings if auto-save is enabled, and settings have changed + if (d->settingsDirty && d->autoSaveSettings) + saveAutoSaveSettings(); + + if (queryClose()) { + e->accept(); + + int not_withdrawn = 0; +/*US + QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); + for (it.toFirst(); it.current(); ++it){ + if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this ) + not_withdrawn++; + } +*/ + if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted? +/*US + if ( queryExit() && !kapp->sessionSaving()) { // Yes, Quit app? + // don't call queryExit() twice + disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); + kapp->deref(); // ...and quit aplication. + } else { + // cancel closing, it's stupid to end up with no windows at all.... + e->ignore(); + } +*/ +//US we have no sessionmanagement. Simply close app. + if ( queryExit() ) { // Yes, Quit app? + qDebug("KMainWindow::closeEvent: Exit application ???"); + // don't call queryExit() twice +//US disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); + } + + } + } +} + +bool KMainWindow::queryExit() +{ + return TRUE; +} + +bool KMainWindow::queryClose() +{ + return TRUE; +} + +void KMainWindow::saveGlobalProperties( KConfig* ) +{ +} + +void KMainWindow::readGlobalProperties( KConfig* ) +{ +} + +void KMainWindow::savePropertiesInternal( KConfig *config, int number ) +{ + bool oldASWS = d->autoSaveWindowSize; + d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size + + QString s; + s.setNum(number); + s.prepend(QString::fromLatin1("WindowProperties")); + config->setGroup(s); + + // store objectName, className, Width and Height for later restoring + // (Only useful for session management) + config->writeEntry(QString::fromLatin1("ObjectName"), name()); + config->writeEntry(QString::fromLatin1("ClassName"), className()); + + saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings. + + s.setNum(number); + config->setGroup(s); + saveProperties(config); + + d->autoSaveWindowSize = oldASWS; +} + +void KMainWindow::setStandardToolBarMenuEnabled( bool enable ) +{ + if ( enable ) + { + if ( d->toolBarHandler ) + return; + + d->toolBarHandler = new KDEPrivate::ToolBarHandler( this ); + +/*US if ( factory() ) + factory()->addClient( d->toolBarHandler ); +*/ + } + else + { + if ( !d->toolBarHandler ) + return; +/*US + if ( factory() ) + factory()->removeClient( d->toolBarHandler ); +*/ + delete d->toolBarHandler; + d->toolBarHandler = 0; + } + +} + +bool KMainWindow::isStandardToolBarMenuEnabled() const +{ + return ( d->toolBarHandler != 0 ); +} + +void KMainWindow::createStandardStatusBarAction(){ + if(!d->showStatusBarAction){ + d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection()); + connect(d->showStatusBarAction, SIGNAL(toggled(bool)), statusBar(), SLOT(setShown(bool))); + if(internalStatusBar()) + d->showStatusBarAction->setChecked(!internalStatusBar()->isHidden()); + } +} + +QToolBar *KMainWindow::tBar( ) +{ + if ( ! mQToolBar ) + mQToolBar = new QToolBar( this ); + return mQToolBar; +} + +KToolBar *KMainWindow::toolBar( const char * name ) +{ + + if (!name) + name = "mainToolBar"; + KToolBar *tb = (KToolBar*)child( name, "KToolBar" ); + if ( tb ) + return tb; + bool honor_mode = (name == "mainToolBar"); + +/*US + if ( builderClient() ) + return new KToolBar(this, name, honor_mode); // XMLGUI constructor + else +*/ + return new KToolBar(this, Top, false, name, honor_mode ); // non-XMLGUI +} + +QPtrListIterator<KToolBar> KMainWindow::toolBarIterator() +{ + toolbarList.clear(); + QPtrList<QToolBar> lst; + for ( int i = (int)QMainWindow::Unmanaged; i <= (int)Minimized; ++i ) { + lst = toolBars( (ToolBarDock)i ); + for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) { + if ( !tb->inherits( "KToolBar" ) ) + continue; + toolbarList.append( (KToolBar*)tb ); + } + } + return QPtrListIterator<KToolBar>( toolbarList ); +} + +void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize ) +{ + d->autoSaveSettings = true; + d->autoSaveGroup = groupName; + d->autoSaveWindowSize = saveWindowSize; + // Get notified when the user moves a toolbar around +//US connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ), +//US this, SLOT( setSettingsDirty() ) ); + connect( this, SIGNAL( toolBarPositionChanged(QToolBar *) ), + this, SLOT( setSettingsDirty() ) ); + + + // Get default values +//US int scnum = QApplication::desktop()->screenNumber(parentWidget()); +//US QRect desk = QApplication::desktop()->screenGeometry(scnum); + QRect desk = KGlobalSettings::desktopGeometry(0); + + d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); + // Now read the previously saved settings + applyMainWindowSettings( KGlobal::config(), groupName ); +} + + +void KMainWindow::resetAutoSaveSettings() +{ + d->autoSaveSettings = false; + if ( d->settingsTimer ) + d->settingsTimer->stop(); +} + +bool KMainWindow::autoSaveSettings() const +{ + return d->autoSaveSettings; +} + +QString KMainWindow::autoSaveGroup() const +{ + return d->autoSaveGroup; +} + +void KMainWindow::saveAutoSaveSettings() +{ + ASSERT( d->autoSaveSettings ); + //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl; + saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup ); + KGlobal::config()->sync(); + d->settingsDirty = false; + if ( d->settingsTimer ) + d->settingsTimer->stop(); +} + +void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory ) +{ + // disabling the updates prevents unnecessary redraws + setUpdatesEnabled( false ); + + // just in case we are rebuilding, let's remove our old client +//US guiFactory()->removeClient( this ); + + // make sure to have an empty GUI + QMenuBar* mb = internalMenuBar(); + if ( mb ) + mb->clear(); + + (void)toolBarIterator(); // make sure toolbarList is most-up-to-date + toolbarList.setAutoDelete( true ); + toolbarList.clear(); + toolbarList.setAutoDelete( false ); +/*US + // don't build a help menu unless the user ask for it + if (d->showHelpMenu) { + // we always want a help menu + if (helpMenu2 == 0) + helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true, + actionCollection()); + } + + // we always want to load in our global standards file + setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) ); + + // now, merge in our local xml file. if this is null, then that + // means that we will be only using the global file + if ( !xmlfile.isNull() ) { + setXMLFile( xmlfile, true ); + } else { + QString auto_file(instance()->instanceName() + "ui.rc"); + setXMLFile( auto_file, true ); + } + + // make sure we don't have any state saved already + setXMLGUIBuildDocument( QDomDocument() ); + + // do the actual GUI building + guiFactory()->addClient( this ); + + // try and get back *some* of our memory + if ( _conserveMemory ) + { + // before freeing the memory allocated by the DOM document we also + // free all memory allocated internally in the KXMLGUIFactory for + // the menubar and the toolbars . This however implies that we + // have to take care of deleting those widgets ourselves. For + // destruction this is no problem, but when rebuilding we have + // to take care of that (and we want to rebuild the GUI when + // using stuff like the toolbar editor ). + // In addition we have to take care of not removing containers + // like popupmenus, defined in the XML document. + // this code should probably go into a separate method in KMainWindow. + // there's just one problem: I'm bad in finding names ;-) , so + // I skipped this ;-) + + QDomDocument doc = domDocument(); + + QDomElement e = doc.documentElement().firstChild().toElement(); + for (; !e.isNull(); e = e.nextSibling().toElement() ) { + if ( e.tagName().lower() == "toolbar" ) + factory_->resetContainer( e.attribute( "name" ) ); + else if ( e.tagName().lower() == "menubar" ) + factory_->resetContainer( e.tagName(), true ); + } + + conserveMemory(); + } +*/ + setUpdatesEnabled( true ); + updateGeometry(); +} + +void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup) +{ + kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl; +//US QStrList entryList; + QStringList entryList; + QString oldGroup; + + if (!configGroup.isEmpty()) + { + oldGroup = config->group(); + config->setGroup(configGroup); + } + + // Called by session management - or if we want to save the window size anyway + if ( d->autoSaveWindowSize ) + saveWindowSize( config ); + + QStatusBar* sb = internalStatusBar(); + if (sb) { + entryList.clear(); + if ( sb->isHidden() ) + entryList.append("Disabled"); + else + entryList.append("Enabled"); + + if(sb->isHidden()) +//US config->writeEntry(QString::fromLatin1("StatusBar"), entryList, ';'); + config->writeEntry(QString::fromLatin1("StatusBar"), entryList); + else + config->deleteEntry(QString::fromLatin1("StatusBar")); + } + + QMenuBar* mb = internalMenuBar(); + if (mb) { + entryList.clear(); + if ( mb->isHidden() ) + entryList.append("Disabled"); + else + entryList.append("Enabled"); + + // By default we don't hide. + if(mb->isHidden()) +//US config->writeEntry(QString::fromLatin1("MenuBar"), entryList, ';'); + config->writeEntry(QString::fromLatin1("MenuBar"), entryList); + else + config->deleteEntry(QString::fromLatin1("MenuBar")); + } + + int n = 1; // Toolbar counter. toolbars are counted from 1, + KToolBar *toolbar = 0; + QPtrListIterator<KToolBar> it( toolBarIterator() ); + while ( ( toolbar = it.current() ) ) { + ++it; + QString group; + if (!configGroup.isEmpty()) + { + // Give a number to the toolbar, but prefer a name if there is one, + // because there's no real guarantee on the ordering of toolbars + group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); + group.prepend(" Toolbar"); + group.prepend(configGroup); + } + toolbar->saveSettings(config, group); + n++; + } + if (!configGroup.isEmpty()) + config->setGroup(oldGroup); +} + +bool KMainWindow::readPropertiesInternal( KConfig *config, int number ) +{ + if ( number == 1 ) + readGlobalProperties( config ); + + // in order they are in toolbar list + QString s; + s.setNum(number); + s.prepend(QString::fromLatin1("WindowProperties")); + + config->setGroup(s); + + // restore the object name (window role) + if ( config->hasKey(QString::fromLatin1("ObjectName" )) ) + setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here + + applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings. + + s.setNum(number); + config->setGroup(s); + readProperties(config); + return true; +} + +void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup) +{ + kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl; + QString entry; +//US QStrList entryList; + QStringList entryList; + int i = 0; // Number of entries in list + + if (!configGroup.isEmpty()) + config->setGroup(configGroup); + + restoreWindowSize(config); + + QStatusBar* sb = internalStatusBar(); + if (sb) { + entryList.clear(); +//US i = config->readListEntry (QString::fromLatin1("StatusBar"), entryList, ';'); + entryList = config->readListEntry (QString::fromLatin1("StatusBar")); + entry = entryList.first(); + if (entry == QString::fromLatin1("Disabled")) + sb->hide(); + else + sb->show(); + if(d->showStatusBarAction) + d->showStatusBarAction->setChecked(!sb->isHidden()); + } + + QMenuBar* mb = internalMenuBar(); + if (mb) { + entryList.clear(); +//US i = config->readListEntry (QString::fromLatin1("MenuBar"), entryList, ';'); + entryList = config->readListEntry (QString::fromLatin1("MenuBar")); + entry = entryList.first(); + if (entry==QString::fromLatin1("Disabled")) + { + mb->hide(); + } else + { + mb->show(); + } + } + + int n = 1; // Toolbar counter. toolbars are counted from 1, + KToolBar *toolbar; + QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator + + for ( ; it.current(); ++it) { + toolbar= it.current(); + QString group; + if (!configGroup.isEmpty()) + { + // Give a number to the toolbar, but prefer a name if there is one, + // because there's no real guarantee on the ordering of toolbars + group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); + group.prepend(" Toolbar"); + group.prepend(configGroup); + } + toolbar->applySettings(config, group); + n++; + } + + finalizeGUI( true ); + } + +void KMainWindow::finalizeGUI( bool force ) +{ + //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl; + // The whole reason for this is that moveToolBar relies on the indexes + // of the other toolbars, so in theory it should be called only once per + // toolbar, but in increasing order of indexes. + // Since we can't do that immediately, we move them, and _then_ + // we call positionYourself again for each of them, but this time + // the toolbariterator should give them in the proper order. + // Both the XMLGUI and applySettings call this, hence "force" for the latter. + QPtrListIterator<KToolBar> it( toolBarIterator() ); + for ( ; it.current() ; ++ it ) + it.current()->positionYourself( force ); + + d->settingsDirty = false; +} + +void KMainWindow::saveWindowSize( KConfig * config ) const +{ +/*US + int scnum = QApplication::desktop()->screenNumber(parentWidget()); + QRect desk = QApplication::desktop()->screenGeometry(scnum); +*/ + QRect desk = KGlobalSettings::desktopGeometry(0); + + QRect size( desk.width(), width(), desk.height(), height() ); + if(size != d->defaultWindowSize){ + config->writeEntry(QString::fromLatin1("Width %1").arg(desk.width()), width() ); + config->writeEntry(QString::fromLatin1("Height %1").arg(desk.height()), height() ); + } + else{ + config->deleteEntry(QString::fromLatin1("Width %1").arg(desk.width())); + config->deleteEntry(QString::fromLatin1("Height %1").arg(desk.height())); + } +} + +void KMainWindow::restoreWindowSize( KConfig * config ) +{ + if (d->care_about_geometry) { + parseGeometry(true); + } else { + // restore the size +/*US int scnum = QApplication::desktop()->screenNumber(parentWidget()); + QRect desk = QApplication::desktop()->screenGeometry(scnum); +*/ + QRect desk = KGlobalSettings::desktopGeometry(0); + + QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ), + config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) ); + if (size.isEmpty()) { + // try the KDE 2.0 way + size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ), + config->readNumEntry( QString::fromLatin1("Height"), 0 ) ); + if (!size.isEmpty()) { + // make sure the other resolutions don't get old settings + config->writeEntry( QString::fromLatin1("Width"), 0 ); + config->writeEntry( QString::fromLatin1("Height"), 0 ); + } + } + if ( !size.isEmpty() ) + resize( size ); + } +} + +bool KMainWindow::initialGeometrySet() const +{ + return d->care_about_geometry; +} + +void KMainWindow::ignoreInitialGeometry() +{ + d->care_about_geometry = false; +} + +void KMainWindow::setSettingsDirty() +{ + //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl; + d->settingsDirty = true; + if ( d->autoSaveSettings ) + { + // Use a timer to save "immediately" user-wise, but not too immediately + // (to compress calls and save only once, in case of multiple changes) + if ( !d->settingsTimer ) + { + d->settingsTimer = new QTimer( this ); + connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) ); + } + d->settingsTimer->start( 500, true ); + } +} + +bool KMainWindow::settingsDirty() const +{ + return d->settingsDirty; +} + +QString KMainWindow::settingsGroup() const +{ + return d->autoSaveGroup; +} + +void KMainWindow::resizeEvent( QResizeEvent * ) +{ + if ( d->autoSaveWindowSize ) + setSettingsDirty(); +} + +bool KMainWindow::hasMenuBar() +{ + return (internalMenuBar()); +} + +//US KMenuBar *KMainWindow::menuBar() +QMenuBar *KMainWindow::menuBar() +{ +//US KMenuBar * mb = internalMenuBar(); + QMenuBar * mb = internalMenuBar(); + if ( !mb ) { +//US mb = new KMenuBar( this ); + mb = new QMenuBar( this ); + // trigger a re-layout and trigger a call to the private + // setMenuBar method. + QMainWindow::menuBar(); + } + return mb; +} + +//US KStatusBar *KMainWindow::statusBar() +QStatusBar *KMainWindow::statusBar() +{ +//US KStatusBar * sb = internalStatusBar(); + QStatusBar * sb = internalStatusBar(); + if ( !sb ) { +//US sb = new KStatusBar( this ); + sb = new QStatusBar( this ); + // trigger a re-layout and trigger a call to the private + // setStatusBar method. + QMainWindow::statusBar(); + } + return sb; +} + +void KMainWindow::shuttingDown() +{ + // Needed for Qt <= 3.0.3 at least to prevent reentrancy + // when queryExit() shows a dialog. Check before removing! + static bool reentrancy_protection = false; + if (!reentrancy_protection) + { + reentrancy_protection = true; + // call the virtual queryExit + queryExit(); + reentrancy_protection = false; + } + +} + +//US KMenuBar *KMainWindow::internalMenuBar() +QMenuBar *KMainWindow::internalMenuBar() +{ +//US QObjectList *l = queryList( "KMenuBar", 0, false, false ); + QObjectList *l = queryList( "QMenuBar", 0, false, false ); + if ( !l || !l->first() ) { + delete l; + return 0; + } + +//US KMenuBar *m = (KMenuBar*)l->first(); + QMenuBar *m = (QMenuBar*)l->first(); + delete l; + return m; +} + +//US KStatusBar *KMainWindow::internalStatusBar() +QStatusBar *KMainWindow::internalStatusBar() +{ +//US QObjectList *l = queryList( "KStatusBar", 0, false, false ); + QObjectList *l = queryList( "QStatusBar", 0, false, false ); + if ( !l || !l->first() ) { + delete l; + return 0; + } + +//US KStatusBar *s = (KStatusBar*)l->first(); + QStatusBar *s = (QStatusBar*)l->first(); + delete l; + return s; +} + +void KMainWindow::childEvent( QChildEvent* e) +{ + QMainWindow::childEvent( e ); +} + +void KMainWindow::paintEvent( QPaintEvent * ) +{ + // do nothing +} + +QSize KMainWindow::sizeForCentralWidgetSize(QSize size) +{ + KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" ); + if (tb && !tb->isHidden()) { + switch( tb->barPos() ) + { + case KToolBar::Top: + case KToolBar::Bottom: + size += QSize(0, tb->sizeHint().height()); + break; + + case KToolBar::Left: + case KToolBar::Right: + size += QSize(toolBar()->sizeHint().width(), 0); + break; + + case KToolBar::Flat: +//US size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); + size += QSize(0, tb->sizeHint().height()); + break; + + default: + break; + } + } +//US KMenuBar *mb = menuBar(); + QMenuBar *mb = menuBar(); + if (!mb->isHidden()) { + size += QSize(0,mb->heightForWidth(size.width())); +/*US if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this)) + size += QSize( 0, dockWindowsMovable() ? 1 : 2); +*/ + size += QSize( 0, 2); + } + QStatusBar *sb = internalStatusBar(); + if( sb && !sb->isHidden() ) + size += QSize(0, sb->sizeHint().height()); + + return size; +} + +// why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; +void KMainWindow::finalizeGUI( KXMLGUIClient *client ) +{ /*US KXMLGUIBuilder::finalizeGUI( client );*/ } + +void KMainWindow::virtual_hook( int id, void* data ) +{ /*US KXMLGUIBuilder::virtual_hook( id, data );*/ + KXMLGUIClient::virtual_hook( id, data ); } diff --git a/microkde/kdeui/kmainwindow.h b/microkde/kdeui/kmainwindow.h new file mode 100644 index 0000000..e76e732 --- a/dev/null +++ b/microkde/kdeui/kmainwindow.h @@ -0,0 +1,776 @@ +/* + This file is part of the KDE libraries + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + $Id$ + +*/ + + + +#ifndef KMAINWINDOW_H +#define KMAINWINDOW_H + +/*US +#include "kxmlguifactory.h" +#include "kxmlguiclient.h" +#include "kxmlguibuilder.h" +#include <qmetaobject.h> + +class KPopupMenu; +class KXMLGUIFactory; +class KConfig; +class KHelpMenu; +class KStatusBar; +class QStatusBar; +class KMenuBar; +class KMWSessionManaged; +class KAccel; +class KToolBarMenuAction; +*/ + +class QMenuBar; +class QStatusBar; +class KMainWindowPrivate; +class KAction; + +#include <ktoolbar.h> +#include <ktoolbarhandler.h> +#include <kxmlguiclient.h> +#include <qmainwindow.h> +#include <qptrlist.h> + +class KActionCollection; + +class KMainWindow : public QMainWindow, virtual public KXMLGUIClient +{ + Q_OBJECT + +private: +//US create private defaultconstructor + KMainWindow() {;}; + +public: +public: + /** + * Construct a main window. + * + * @param parent The widget parent. This is usually 0 but it may also be the window + * group leader. In that case, the KMainWindow becomes sort of a + * secondary window. + * + * @param name The object name. For session management and window management to work + * properly, all main windows in the application should have a + * different name. When passing 0 (the default), KMainWindow will create + * a unique name, but it's recommended to explicitly pass a window name that will + * also describe the type of the window. If there can be several windows of the same + * type, append '#' (hash) to the name, and KMainWindow will append numbers to make + * the names unique. For example, for a mail client which has one main window showing + * the mails and folders, and which can also have one or more windows for composing + * mails, the name for the folders window should be e.g. "mainwindow" and + * for the composer windows "composer#". + * + * @param f Specify the widget flags. The default is + * WType_TopLevel and WDestructiveClose. TopLevel indicates that a + * main window is a toplevel window, regardless of whether it has a + * parent or not. DestructiveClose indicates that a main window is + * automatically destroyed when its window is closed. Pass 0 if + * you do not want this behavior. + * + * KMainWindows must be created on the heap with 'new', like: + * <pre> KMainWindow *kmw = new KMainWindow (...</pre> + **/ + KMainWindow( QWidget* parent = 0, const char *name = 0, WFlags f = WType_TopLevel | WDestructiveClose ); + + + /** + * Destructor. + * + * Will also destroy the toolbars, and menubar if + * needed. + */ + virtual ~KMainWindow(); + + /** + * Retrieve the standard help menu. + * + * It contains entires for the + * help system (activated by F1), an optional "What's This?" entry + * (activated by Shift F1), an application specific dialog box, + * and an "About KDE" dialog box. + * + * Example (adding a standard help menu to your application): + * <pre> + * KPopupMenu *help = helpMenu( <myTextString> ); + * menuBar()->insertItem( i18n("&Help"), help ); + * </pre> + * + * @param aboutAppText The string that is used in the application + * specific dialog box. If you leave this string empty the + * information in the global @ref KAboutData of the + * application will be used to make a standard dialog box. + * + * @param showWhatsThis Set this to false if you do not want to include + * the "What's This" menu entry. + * + * @return A standard help menu. + */ +//US KPopupMenu* helpMenu( const QString &aboutAppText = QString::null, +//US bool showWhatsThis = TRUE ); + + /** + * Returns the help menu. Creates a standard help menu if none exists yet. + * + * It contains entries for the + * help system (activated by F1), an optional "What's This?" entry + * (activated by Shift F1), an application specific dialog box, + * and an "About KDE" dialog box. You must create the application + * specific dialog box yourself. When the "About application" + * menu entry is activated, a signal will trigger the + * @ref showAboutApplication slot. See @ref showAboutApplication for more + * information. + * + * Example (adding a help menu to your application): + * <pre> + * menuBar()->insertItem( i18n("&Help"), customHelpMenu() ); + * </pre> + * + * @param showWhatsThis Set this to @p false if you do not want to include + * the "What's This" menu entry. + * + * @return A standard help menu. + */ +//US KPopupMenu* customHelpMenu( bool showWhatsThis = TRUE ); + + /** + * @sect Session Management + * + * Try to restore the toplevel widget as defined by the number (1..X). + * + * If the session did not contain so high a number, the configuration + * is not changed and @p false returned. + * + * That means clients could simply do the following: + * <pre> + * if (kapp->isRestored()){ + * int n = 1; + * while (KMainWindow::canBeRestored(n)){ + * (new childMW)->restore(n); + * n++; + * } + * } else { + * // create default application as usual + * } + * </pre> + * Note that @ref QWidget::show() is called implicitly in restore. + * + * With this you can easily restore all toplevel windows of your + * application. + * + * If your application uses different kinds of toplevel + * windows, then you can use @ref KMainWindow::classNameOfToplevel(n) + * to determine the exact type before calling the childMW + * constructor in the example from above. + * + * If your client has only one kind of toplevel widgets (which + * should be pretty usual) then you should use the RESTORE-macro + * for backwards compatibility with 3.1 and 3.0 branches: + * + * <pre> + * if (kapp->isRestored()) + * RESTORE(childMW) + * else { + * // create default application as usual + * } + * </pre> + * + * The macro expands to the term above but is easier to use and + * less code to write. + * + * For new code or if you have more than one kind of toplevel + * widget (each derived from @ref KMainWindow, of course), you can + * use the templated @ref kRestoreMainWindows global functions: + * + * <pre> + * if (kapp->isRestored()) + * kRestoreMainWindows< childMW1, childMW2, childMW3 >(); + * else { + * // create default application as usual + * } + * </pre> + * + * Currently, these functions are provided for up to three + * template arguments. If you need more, tell us. To help you in + * deciding whether or not you can use @ref kRestoreMainWindows, a + * define KDE_RESTORE_MAIN_WINDOWS_NUM_TEMPLATE_ARGS is provided. + * + * @see restore() + * @see classNameOfToplevel() + * + **/ + static bool canBeRestored( int number ); + + /** + * Returns the @ref className() of the @p number of the toplevel window which + * should be restored. + * + * This is only useful if your application uses + * different kinds of toplevel windows. + */ + static const QString classNameOfToplevel( int number ); + + /** + * Restore the session specified by @p number. + * + * Returns @p false if this + * fails, otherwise returns @p true and shows the window. + * You should call @ref canBeRestored() first. + * If @p show is true (default), this widget will be shown automatically. + */ + bool restore( int number, bool show = TRUE ); + +//US virtual KXMLGUIFactory *guiFactory(); + + /** + * Create a GUI given a local XML file. + * + * If @p xmlfile is NULL, + * then it will try to construct a local XML filename like + * appnameui.rc where 'appname' is your app's name. If that file + * does not exist, then the XML UI code will only use the global + * (standard) XML file for the layout purposes. + * + * Note that when passing true for the conserveMemory argument subsequent + * calls to guiFactory()->addClient/removeClient may not work as expected. + * Also retrieving references to containers like popup menus or toolbars using + * the container method will not work. + * + * @param xmlfile The local xmlfile (relative or absolute) + * @param _conserveMemory Specify whether createGUI() should call + * @ref KXMLGuiClient::conserveMemory() to free all memory + * allocated by the @ref QDomDocument and by the KXMLGUIFactory. + */ + void createGUI( const QString &xmlfile = QString::null, bool _conserveMemory = TRUE ); + + /** + * Enables the build of a standard help menu when calling createGUI(). + * + * The default behavior is to build one, you must call this function + * to disable it + */ + void setHelpMenuEnabled(bool showHelpMenu = true); + + /** + * Return @p true when the help menu is enabled + */ + bool isHelpMenuEnabled(); + + + /** + * Returns true, if there is a menubar + * @since 3.1 + */ + bool hasMenuBar(); + + /** + * Returns a pointer to the menu bar. + * + * If there is no menu bar yet one will be created. + **/ +//US KMenuBar *menuBar(); + QMenuBar *menuBar(); + + /** + * Returns a pointer to the status bar. + * + * If there is no + * status bar yet one will be created. + */ +//US KStatusBar *statusBar(); + QStatusBar *statusBar(); + + /** + * List of members of KMainWindow class. + */ +//US static QPtrList<KMainWindow>* memberList; + + /** + * Returns a pointer to the toolbar with the specified name. + * This refers to toolbars created dynamically from the XML UI + * framework. If the toolbar does not exist one will be created. + * + * @param name The internal name of the toolbar. If no name is + * specified "mainToolBar" is assumed. + * + * @return A pointer to the toolbar + **/ + KToolBar *toolBar( const char *name=0 ); + // method for getting rid of KDE-Crap + QToolBar *tBar( ); + + /** + * @return An iterator over the list of all toolbars for this window. + */ + QPtrListIterator<KToolBar> toolBarIterator(); + + /** + * @return A KAccel instance bound to this mainwindow. Used automatically + * by KAction to make keybindings work in all cases. + */ + KAccel *accel(); + + void setFrameBorderWidth( int ) {} + + /** + * Call this to enable "auto-save" of toolbar/menubar/statusbar settings + * (and optionally window size). + * If the *bars were moved around/shown/hidden when the window is closed, + * saveMainWindowSettings( KGlobal::config(), groupName ) will be called. + * + * @param groupName a name that identifies this "type of window". + * You can have several types of window in the same application. + * + * @param saveWindowSize set it to true to include the window size + * when saving. + * + * Typically, you will call setAutoSaveSettings() in your + * KMainWindow-inherited class constructor, and it will take care + * of restoring and saving automatically. Make sure you call this + * _after all_ your *bars have been created. + */ + void setAutoSaveSettings( const QString & groupName = QString::fromLatin1("MainWindow"), + bool saveWindowSize = true ); + + /** + * Disable the auto-save-settings feature. + * You don't normally need to call this, ever. + */ + void resetAutoSaveSettings(); + + /** + * @return the current autosave setting, i.e. true if setAutoSaveSettings() was called, + * false by default or if resetAutoSaveSettings() was called. + * @since 3.1 + */ + bool autoSaveSettings() const; + + /** + * @return the group used for setting-autosaving. + * Only meaningful if setAutoSaveSettings() was called. + * This can be useful for forcing a save or an apply, e.g. before and after + * using KEditToolbar. + * @since 3.1 + */ + QString autoSaveGroup() const; + + /** + * Read settings for statusbar, menubar and toolbar from their respective + * groups in the config file and apply them. + * + * @param config Config file to read the settings from. + * @param groupName Group name to use. If not specified, the last used + * group name is used. + */ + void applyMainWindowSettings(KConfig *config, const QString &groupName = QString::null); + + /** + * Save settings for statusbar, menubar and toolbar to their respective + * groups in the config file @p config. + * + * @param config Config file to save the settings to. + * @param groupName Group name to use. If not specified, the last used + * group name is used + */ + void saveMainWindowSettings(KConfig *config, const QString &groupName = QString::null); + + /** + * Sets whether KMainWindow should provide a menu that allows showing/hiding + * the available toolbars ( using @ref KToggleToolBarAction ) . In case there + * is only one toolbar configured a simple 'Show <toolbar name here>' menu item + * is shown. + * + * The menu / menu item is implemented using xmlgui. It will be inserted in your + * menu structure in the 'Settings' menu. + * + * If your application uses a non-standard xmlgui resource file then you can + * specify the exact position of the menu / menu item by adding a + * <Merge name="StandardToolBarMenuHandler" /> + * line to the settings menu section of your resource file ( usually appname.rc ). + * + * Note that you should enable this feature before calling createGUI() ( or similar ) . + * You enable/disable it anytime if you pass false to the conserveMemory argument of createGUI. + * @since 3.1 + */ + void setStandardToolBarMenuEnabled( bool enable ); + /// @since 3.1 + bool isStandardToolBarMenuEnabled() const; + + + /** + * Sets whether KMainWindow should provide a menu that allows showing/hiding + * of the statusbar ( using @ref KToggleStatusBarAction ). + * + * The menu / menu item is implemented using xmlgui. It will be inserted + * in your menu structure in the 'Settings' menu. + * + * Note that you should enable this feature before calling createGUI() + * ( or similar ). + * + * If an application maintains the action on its own (i.e. never calls + * this function) a connection needs to be made to let KMainWindow + * know when that status (hidden/shown) of the statusbar has changed. + * For example: + * connect(action, SIGNAL(activated()), + * kmainwindow, SLOT(setSettingsDirty())); + * Otherwise the status (hidden/show) of the statusbar might not be saved + * by KMainWindow. + * @since 3.2 + */ + void createStandardStatusBarAction(); + + + /** + * Returns a pointer to the mainwindows action responsible for the toolbars menu + * @since 3.1 + */ + KAction *toolBarMenuAction(); + + // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; + /// @since 3.1 + virtual void finalizeGUI( KXMLGUIClient *client ); + + /** + * @internal + */ + void finalizeGUI( bool force ); + + /** + * @return true if a -geometry argument was given on the command line, + * and this is the first window created (the one on which this option applies) + */ + bool initialGeometrySet() const; + + /** + * @internal + * Used from Konqueror when reusing the main window. + */ + void ignoreInitialGeometry(); + + /** + * @return the size the mainwindow should have so that the central + * widget will be of @p size. + */ + QSize sizeForCentralWidgetSize(QSize size); + +public slots: + /** + * Makes a KDE compliant caption. + * + * @param caption Your caption. @em Do @em not include the application name + * in this string. It will be added automatically according to the KDE + * standard. + */ + virtual void setCaption( const QString &caption ); + /** + * Makes a KDE compliant caption. + * + * @param caption Your caption. @em Do @em not include the application name + * in this string. It will be added automatically according to the KDE + * standard. + * @param modified Specify whether the document is modified. This displays + * an additional sign in the title bar, usually "**". + */ + virtual void setCaption( const QString &caption, bool modified ); + + /** + * Make a plain caption without any modifications. + * + * @param caption Your caption. This is the string that will be + * displayed in the window title. + */ + virtual void setPlainCaption( const QString &caption ); + + /** + * Open the help page for the application. + * + * The application name is + * used as a key to determine what to display and the system will attempt + * to open <appName>/index.html. + * + * This method is intended for use by a help button in the toolbar or + * components outside the regular help menu. Use @ref helpMenu() when you + * want to provide access to the help system from the help menu. + * + * Example (adding a help button to the first toolbar): + * + * <pre> + * KIconLoader &loader = *KGlobal::iconLoader(); + * QPixmap pixmap = loader.loadIcon( "help" ); + * toolBar(0)->insertButton( pixmap, 0, SIGNAL(clicked()), + * this, SLOT(appHelpActivated()), true, i18n("Help") ); + * </pre> + * + */ +//US void appHelpActivated( void ); + + /** + * Apply a state change + * + * Enable and disable actions as defined in the XML rc file + * @since 3.1 + */ + virtual void slotStateChanged(const QString &newstate); + + /** + * Apply a state change + * + * Enable and disable actions as defined in the XML rc file, + * can "reverse" the state (disable the actions which should be + * enabled, and vice-versa) if specified. + * @since 3.1 + */ + void slotStateChanged(const QString &newstate, + KXMLGUIClient::ReverseStateChange); // KDE 4.0: remove this + + + /** + * Apply a state change + * + * Enable and disable actions as defined in the XML rc file, + * can "reverse" the state (disable the actions which should be + * enabled, and vice-versa) if specified. + */ +// void slotStateChanged(const QString &newstate, +// bool reverse); // KDE 4.0: enable this + + /** + * Tell the main window that it should save its settings when being closed. + * This is part of the auto-save-settings feature. + * For everything related to toolbars this happens automatically, + * but you have to call setSettingsDirty() in the slot that toggles + * the visibility of the statusbar. + */ + void setSettingsDirty(); + +protected: + void paintEvent( QPaintEvent* e ); + void childEvent( QChildEvent* e); + void resizeEvent( QResizeEvent* e); + /** + * Reimplemented to call the queryClose() and queryExit() handlers. + * + * We recommend that you reimplement the handlers rather than @ref closeEvent(). + * If you do it anyway, ensure to call the base implementation to keep + * @ref queryExit() running. + */ + virtual void closeEvent ( QCloseEvent *); + + // KDE4 This seems to be flawed to me. Either the app has only one + // mainwindow, so queryClose() is enough, or if it can have more of them, + // then the windows should take care of themselves, and queryExit() + // would be useful only for the annoying 'really quit' dialog, which + // also doesn't make sense in apps with multiple mainwindows. + // And saving configuration in something called queryExit()? IMHO + // one can e.g. use KApplication::shutDown(), which if nothing else + // has at least better fitting name. + // See also KApplication::sessionSaving(). + // This stuff should get changed somehow, so that it at least doesn't + // mess with session management. + /** + Called before the very last window is closed, either by the + user or indirectly by the session manager. + + It is not recommended to do any user interaction in this + function other than indicating severe errors. Better ask the + user on @ref queryClose() (see below). + + A typical usage of @ref queryExit() is to write configuration data back. + Note that the application may continue to run after @ref queryExit() + (the user may have cancelled a shutdown), so you should not do any cleanups + here. The purpose of @ref queryExit() is purely to prepare the application + (with possible user interaction) so it can safely be closed later (without + user interaction). + + If you need to do serious things on exit (like shutting a + dial-up connection down), connect to the signal + @ref KApplication::shutDown(). + + Default implementation returns @p true. Returning @p false will + cancel the exiting. In the latter case, the last window will + remain visible. If KApplication::sessionSaving() is true, refusing + the exit will also cancel KDE logout. + + @see queryClose() + @see KApplication::sessionSaving() + */ + virtual bool queryExit(); + + /** + Called before the window is closed, either by the user or indirectly by + the session manager. + + The purpose of this function is to prepare the window in a way that it is + safe to close it, i.e. without the user losing some data. + + Default implementation returns true. Returning @p false will cancel + the closing, and, if KApplication::sessionSaving() is true, it will also + cancel KDE logout. + + Reimplement this function to prevent the user from losing data. + Example: + <pre> + + switch ( KMessageBox::warningYesNoCancel( this, + i18n("Save changes to document foo?")) ) { + case KMessageBox::Yes : + // save document here. If saving fails, return FALSE; + return TRUE; + case KMessageBox::No : + return TRUE; + default: // cancel + return FALSE; + + </pre> + + @see queryExit() + @see KApplication::sessionSaving() + + */ + virtual bool queryClose(); + /** + * Save your instance-specific properties. The function is + * invoked when the session manager requests your application + * to save its state. + * + * You @em must @em not change the group of the @p kconfig object, since + * KMainWindow uses one group for each window. Please + * reimplement these function in childclasses. + * + * Note: No user interaction is allowed + * in this function! + * + */ + virtual void saveProperties( KConfig* ) {} + + /** + * Read your instance-specific properties. + */ + virtual void readProperties( KConfig* ) {} + + /** + * Save your application-wide properties. The function is + * invoked when the session manager requests your application + * to save its state. + * + * This function is similar to @ref saveProperties() but is only called for + * the very first main window, regardless how many main window are open. + + * Override it if you need to save other data about your documents on + * session end. sessionConfig is a config to which that data should be + * saved. Normally, you don't need this function. But if you want to save + * data about your documents that are not in opened windows you might need + * it. + * + * Default implementation does nothing. + */ + virtual void saveGlobalProperties( KConfig* sessionConfig ); + + /** + * The counterpart of @ref saveGlobalProperties(). + * + * Read the application-specific properties in again. + */ + virtual void readGlobalProperties( KConfig* sessionConfig ); + void savePropertiesInternal( KConfig*, int ); + bool readPropertiesInternal( KConfig*, int ); + + /** + * For inherited classes + */ + bool settingsDirty() const; + /** + * For inherited classes + */ + QString settingsGroup() const; + /** + * For inherited classes + * Note that the group must be set before calling + */ + void saveWindowSize( KConfig * config ) const; + /** + * For inherited classes + * Note that the group must be set before calling, and that + * a -geometry on the command line has priority. + */ + void restoreWindowSize( KConfig * config ); + + /// parse the geometry from the geometry command line argument + void parseGeometry(bool parsewidth); + +protected slots: + + /** + * This slot does nothing. + * + * It must be reimplemented if you want + * to use a custom About Application dialog box. This slot is + * connected to the About Application entry in the menu returned + * by @ref customHelpMenu. + * + * Example: + * <pre> + * + * void MyMainLevel::setupInterface() + * { + * .. + * menuBar()->insertItem( i18n("&Help"), customHelpMenu() ); + * .. + * } + * + * void MyMainLevel::showAboutApplication() + * { + * <activate your custom dialog> + * } + * </pre> + */ +//US virtual void showAboutApplication(); + +private slots: + /** + * Called when the app is shutting down. + */ + void shuttingDown(); + + void saveAutoSaveSettings(); + +private: + QToolBar * mQToolBar; +//US KMenuBar *internalMenuBar(); + QMenuBar *internalMenuBar(); +//US KStatusBar *internalStatusBar(); + QStatusBar *internalStatusBar(); + + KMainWindowPrivate *d; + void initKMainWindow(const char *name); + + QPtrList<KToolBar> toolbarList; + +protected: + virtual void virtual_hook( int id, void* data ); + +}; + +#endif diff --git a/microkde/kdeui/knuminput.cpp b/microkde/kdeui/knuminput.cpp new file mode 100644 index 0000000..335d6f4 --- a/dev/null +++ b/microkde/kdeui/knuminput.cpp @@ -0,0 +1,1095 @@ +// -*- c-basic-offset: 4 -*- +/* + * knuminput.cpp + * + * Initial implementation: + * Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca> + * Rewritten and maintained by: + * Copyright (c) 2000 Dirk A. Mueller <mueller@kde.org> + * KDoubleSpinBox: + * Copyright (c) 2002 Marc Mutz <mutz@kde.org> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +//US #include <config.h> +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#include <assert.h> +#include <math.h> +#include <algorithm> + +#include <qlabel.h> +#include <qlineedit.h> +#include <qsize.h> +#include <qslider.h> +#include <qspinbox.h> +#include <qstyle.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> + +#include "knumvalidator.h" +#include "knuminput.h" + +static inline int calcDiffByTen( int x, int y ) { + // calculate ( x - y ) / 10 without overflowing ints: + return ( x / 10 ) - ( y / 10 ) + ( x % 10 - y % 10 ) / 10; +} + +// ---------------------------------------------------------------------------- + +KNumInput::KNumInput(QWidget* parent, const char* name) + : QWidget(parent, name) +{ + init(); +} + +KNumInput::KNumInput(KNumInput* below, QWidget* parent, const char* name) + : QWidget(parent, name) +{ + init(); + + if(below) { + m_next = below->m_next; + m_prev = below; + below->m_next = this; + if(m_next) + m_next->m_prev = this; + } +} + +void KNumInput::init() +{ + m_prev = m_next = 0; + m_colw1 = m_colw2 = 0; + + m_label = 0; + m_slider = 0; + m_alignment = 0; +} + +KNumInput::~KNumInput() +{ + if(m_prev) + m_prev->m_next = m_next; + + if(m_next) + m_next->m_prev = m_prev; +} + +void KNumInput::setLabel(const QString & label, int a) +{ + if(label.isEmpty()) { + delete m_label; + m_label = 0; + m_alignment = 0; + } + else { + if (m_label) m_label->setText(label); + else m_label = new QLabel(label, this, "KNumInput::QLabel"); + m_label->setAlignment((a & (~(AlignTop|AlignBottom|AlignVCenter))) + | AlignVCenter); + // if no vertical alignment set, use Top alignment + if(!(a & (AlignTop|AlignBottom|AlignVCenter))) + a |= AlignTop; + m_alignment = a; + } + + layout(true); +} + +QString KNumInput::label() const +{ + if (m_label) return m_label->text(); + return QString::null; +} + +void KNumInput::layout(bool deep) +{ + int w1 = m_colw1; + int w2 = m_colw2; + + // label sizeHint + m_sizeLabel = (m_label ? m_label->sizeHint() : QSize(0,0)); + + if(m_label && (m_alignment & AlignVCenter)) + m_colw1 = m_sizeLabel.width() + 4; + else + m_colw1 = 0; + + // slider sizeHint + m_sizeSlider = (m_slider ? m_slider->sizeHint() : QSize(0, 0)); + + doLayout(); + + if(!deep) { + m_colw1 = w1; + m_colw2 = w2; + return; + } + + KNumInput* p = this; + while(p) { + p->doLayout(); + w1 = QMAX(w1, p->m_colw1); + w2 = QMAX(w2, p->m_colw2); + p = p->m_prev; + } + + p = m_next; + while(p) { + p->doLayout(); + w1 = QMAX(w1, p->m_colw1); + w2 = QMAX(w2, p->m_colw2); + p = p->m_next; + } + + p = this; + while(p) { + p->m_colw1 = w1; + p->m_colw2 = w2; + p = p->m_prev; + } + + p = m_next; + while(p) { + p->m_colw1 = w1; + p->m_colw2 = w2; + p = p->m_next; + } + +// kdDebug() << "w1 " << w1 << " w2 " << w2 << endl; +} + +QSizePolicy KNumInput::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ); +} + +QSize KNumInput::sizeHint() const +{ + return minimumSizeHint(); +} + +void KNumInput::setSteps(int minor, int major) +{ + if(m_slider) + m_slider->setSteps( minor, major ); +} + + +// ---------------------------------------------------------------------------- + +KIntSpinBox::KIntSpinBox(QWidget *parent, const char *name) + : QSpinBox(0, 99, 1, parent, name) +{ + editor()->setAlignment(AlignRight); + val_base = 10; + setValue(0); +} + +KIntSpinBox::~KIntSpinBox() +{ +} + +KIntSpinBox::KIntSpinBox(int lower, int upper, int step, int value, int base, + QWidget* parent, const char* name) + : QSpinBox(lower, upper, step, parent, name) +{ + editor()->setAlignment(AlignRight); + val_base = base; + setValue(value); +} + +void KIntSpinBox::setBase(int base) +{ + val_base = base; +} + + +int KIntSpinBox::base() const +{ + return val_base; +} + +QString KIntSpinBox::mapValueToText(int v) +{ + return QString::number(v, val_base); +} + +int KIntSpinBox::mapTextToValue(bool* ok) +{ + return cleanText().toInt(ok, val_base); +} + +void KIntSpinBox::setEditFocus(bool mark) +{ + editor()->setFocus(); + if(mark) + editor()->selectAll(); +} + + +// ---------------------------------------------------------------------------- + +class KIntNumInput::KIntNumInputPrivate { +public: + int referencePoint; + short blockRelative; + KIntNumInputPrivate( int r ) + : referencePoint( r ), + blockRelative( 0 ) {} +}; + + +KIntNumInput::KIntNumInput(KNumInput* below, int val, QWidget* parent, + int _base, const char* name) + : KNumInput(below, parent, name) +{ + init(val, _base); +} + +KIntNumInput::KIntNumInput(QWidget *parent, const char *name) + : KNumInput(parent, name) +{ + init(0, 10); +} + +KIntNumInput::KIntNumInput(int val, QWidget *parent, int _base, const char *name) + : KNumInput(parent, name) +{ + init(val, _base); + +} + +void KIntNumInput::init(int val, int _base) +{ + d = new KIntNumInputPrivate( val ); + m_spin = new KIntSpinBox(INT_MIN, INT_MAX, 1, val, _base, this, "KIntNumInput::KIntSpinBox"); + m_spin->setValidator(new KIntValidator(this, _base, "KNumInput::KIntValidtr")); + connect(m_spin, SIGNAL(valueChanged(int)), SLOT(spinValueChanged(int))); + connect(this, SIGNAL(valueChanged(int)), + SLOT(slotEmitRelativeValueChanged(int))); + + setFocusProxy(m_spin); + layout(true); +} + +void KIntNumInput::setReferencePoint( int ref ) { + // clip to valid range: + ref = kMin( maxValue(), kMax( minValue(), ref ) ); + d->referencePoint = ref; +} + +int KIntNumInput::referencePoint() const { + return d->referencePoint; +} + +void KIntNumInput::spinValueChanged(int val) +{ + if(m_slider) + m_slider->setValue(val); + + emit valueChanged(val); +} + +void KIntNumInput::slotEmitRelativeValueChanged( int value ) { + if ( d->blockRelative || !d->referencePoint ) return; + emit relativeValueChanged( double( value ) / double( d->referencePoint ) ); +} + +void KIntNumInput::setRange(int lower, int upper, int step, bool slider) +{ + upper = kMax(upper, lower); + lower = kMin(upper, lower); + m_spin->setMinValue(lower); + m_spin->setMaxValue(upper); + m_spin->setLineStep(step); + + step = m_spin->lineStep(); // maybe QRangeControl didn't like out lineStep? + + if(slider) { + if (m_slider) + m_slider->setRange(lower, upper); + else { + m_slider = new QSlider(lower, upper, step, m_spin->value(), + QSlider::Horizontal, this); + m_slider->setTickmarks(QSlider::Below); + connect(m_slider, SIGNAL(valueChanged(int)), + m_spin, SLOT(setValue(int))); + } + + // calculate (upper-lower)/10 without overflowing int's: + int major = calcDiffByTen( upper, lower ); + if ( major==0 ) major = step; // #### workaround Qt bug in 2.1-beta4 + + m_slider->setSteps(step, major); + m_slider->setTickInterval(major); + } + else { + delete m_slider; + m_slider = 0; + } + + // check that reference point is still inside valid range: + setReferencePoint( referencePoint() ); + + layout(true); +} + +void KIntNumInput::setMinValue(int min) +{ + setRange(min, m_spin->maxValue(), m_spin->lineStep(), m_slider); +} + +int KIntNumInput::minValue() const +{ + return m_spin->minValue(); +} + +void KIntNumInput::setMaxValue(int max) +{ + setRange(m_spin->minValue(), max, m_spin->lineStep(), m_slider); +} + +int KIntNumInput::maxValue() const +{ + return m_spin->maxValue(); +} + +void KIntNumInput::setSuffix(const QString &suffix) +{ + m_spin->setSuffix(suffix); + + layout(true); +} + +QString KIntNumInput::suffix() const +{ + return m_spin->suffix(); +} + +void KIntNumInput::setPrefix(const QString &prefix) +{ + m_spin->setPrefix(prefix); + + layout(true); +} + +QString KIntNumInput::prefix() const +{ + return m_spin->prefix(); +} + +void KIntNumInput::setEditFocus(bool mark) +{ + m_spin->setEditFocus(mark); +} + +QSize KIntNumInput::minimumSizeHint() const +{ + constPolish(); + + int w; + int h; + + h = 2 + QMAX(m_sizeSpin.height(), m_sizeSlider.height()); + + // if in extra row, then count it here + if(m_label && (m_alignment & (AlignBottom|AlignTop))) + h += 4 + m_sizeLabel.height(); + else + // label is in the same row as the other widgets + h = QMAX(h, m_sizeLabel.height() + 2); + + w = m_slider ? m_slider->sizeHint().width() + 8 : 0; + w += m_colw1 + m_colw2; + + if(m_alignment & (AlignTop|AlignBottom)) + w = QMAX(w, m_sizeLabel.width() + 4); + + return QSize(w, h); +} + +void KIntNumInput::doLayout() +{ + m_sizeSpin = m_spin->sizeHint(); + m_colw2 = m_sizeSpin.width(); + + if (m_label) + m_label->setBuddy(m_spin); +} + +void KIntNumInput::resizeEvent(QResizeEvent* e) +{ + int w = m_colw1; + int h = 0; + + if(m_label && (m_alignment & AlignTop)) { + m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height()); + h += m_sizeLabel.height() + 4; + } + + if(m_label && (m_alignment & AlignVCenter)) + m_label->setGeometry(0, 0, w, m_sizeSpin.height()); + + m_spin->setGeometry(w, h, m_slider ? m_colw2 : QMAX(m_colw2, e->size().width() - w), m_sizeSpin.height()); + w += m_colw2 + 8; + + if(m_slider) + m_slider->setGeometry(w, h, e->size().width() - w, m_sizeSpin.height()); + + h += m_sizeSpin.height() + 2; + + if(m_label && (m_alignment & AlignBottom)) + m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height()); +} + +KIntNumInput::~KIntNumInput() +{ + delete d; +} + +void KIntNumInput::setValue(int val) +{ + m_spin->setValue(val); + // slider value is changed by spinValueChanged +} + +void KIntNumInput::setRelativeValue( double r ) { + if ( !d->referencePoint ) return; + ++d->blockRelative; + setValue( int( d->referencePoint * r + 0.5 ) ); + --d->blockRelative; +} + +double KIntNumInput::relativeValue() const { + if ( !d->referencePoint ) return 0; + return double( value() ) / double ( d->referencePoint ); +} + +int KIntNumInput::value() const +{ + return m_spin->value(); +} + +void KIntNumInput::setSpecialValueText(const QString& text) +{ + m_spin->setSpecialValueText(text); + layout(true); +} + +QString KIntNumInput::specialValueText() const +{ + return m_spin->specialValueText(); +} + +void KIntNumInput::setLabel(const QString & label, int a) +{ + KNumInput::setLabel(label, a); + + if(m_label) + m_label->setBuddy(m_spin); +} + +// ---------------------------------------------------------------------------- + +class KDoubleNumInput::KDoubleNumInputPrivate { +public: + KDoubleNumInputPrivate( double r ) + : spin( 0 ), + referencePoint( r ), + blockRelative ( 0 ) {} + KDoubleSpinBox * spin; + double referencePoint; + short blockRelative; +}; + +KDoubleNumInput::KDoubleNumInput(QWidget *parent, const char *name) + : KNumInput(parent, name) +{ + init(0.0, 0.0, 9999.0, 0.01, 2); +} + +KDoubleNumInput::KDoubleNumInput(double lower, double upper, double value, + double step, int precision, QWidget* parent, + const char *name) + : KNumInput(parent, name) +{ + init(value, lower, upper, step, precision); +} + +KDoubleNumInput::KDoubleNumInput(KNumInput *below, + double lower, double upper, double value, + double step, int precision, QWidget* parent, + const char *name) + : KNumInput(below, parent, name) +{ + init(value, lower, upper, step, precision); +} + +KDoubleNumInput::KDoubleNumInput(double value, QWidget *parent, const char *name) + : KNumInput(parent, name) +{ + init(value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 ); +} + +KDoubleNumInput::KDoubleNumInput(KNumInput* below, double value, QWidget* parent, + const char* name) + : KNumInput(below, parent, name) +{ + init( value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 ); +} + +KDoubleNumInput::~KDoubleNumInput() +{ + delete d; +} + +// ### remove when BIC changes are allowed again: + +bool KDoubleNumInput::eventFilter( QObject * o, QEvent * e ) { + return KNumInput::eventFilter( o, e ); +} + +void KDoubleNumInput::resetEditBox() { + +} + +// ### end stuff to remove when BIC changes are allowed again + + + +void KDoubleNumInput::init(double value, double lower, double upper, + double step, int precision ) +{ + // ### init no longer used members: + edit = 0; + m_range = true; + m_value = 0.0; + m_precision = 2; + // ### end + + d = new KDoubleNumInputPrivate( value ); + + d->spin = new KDoubleSpinBox( lower, upper, step, value, precision, + this, "KDoubleNumInput::d->spin" ); + setFocusProxy(d->spin); + connect( d->spin, SIGNAL(valueChanged(double)), + this, SIGNAL(valueChanged(double)) ); + connect( this, SIGNAL(valueChanged(double)), + this, SLOT(slotEmitRelativeValueChanged(double)) ); + + updateLegacyMembers(); + + layout(true); +} + +void KDoubleNumInput::updateLegacyMembers() { + // ### update legacy members that are either not private or for + // which an inlined getter exists: + m_lower = minValue(); + m_upper = maxValue(); + m_step = d->spin->lineStep(); + m_specialvalue = specialValueText(); +} + + +double KDoubleNumInput::mapSliderToSpin( int val ) const +{ + // map [slidemin,slidemax] to [spinmin,spinmax] + double spinmin = d->spin->minValue(); + double spinmax = d->spin->maxValue(); + double slidemin = m_slider->minValue(); // cast int to double to avoid + double slidemax = m_slider->maxValue(); // overflow in rel denominator + double rel = ( double(val) - slidemin ) / ( slidemax - slidemin ); + return spinmin + rel * ( spinmax - spinmin ); +} + +void KDoubleNumInput::sliderMoved(int val) +{ + d->spin->setValue( mapSliderToSpin( val ) ); +} + +void KDoubleNumInput::slotEmitRelativeValueChanged( double value ) +{ + if ( !d->referencePoint ) return; + emit relativeValueChanged( value / d->referencePoint ); +} + +QSize KDoubleNumInput::minimumSizeHint() const +{ + constPolish(); + + int w; + int h; + + h = 2 + QMAX(m_sizeEdit.height(), m_sizeSlider.height()); + + // if in extra row, then count it here + if(m_label && (m_alignment & (AlignBottom|AlignTop))) + h += 4 + m_sizeLabel.height(); + else + // label is in the same row as the other widgets + h = QMAX(h, m_sizeLabel.height() + 2); + + w = m_slider ? m_slider->sizeHint().width() + 8 : 0; + w += m_colw1 + m_colw2; + + if(m_alignment & (AlignTop|AlignBottom)) + w = QMAX(w, m_sizeLabel.width() + 4); + + return QSize(w, h); +} + +void KDoubleNumInput::resizeEvent(QResizeEvent* e) +{ + int w = m_colw1; + int h = 0; + + if(m_label && (m_alignment & AlignTop)) { + m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height()); + h += m_sizeLabel.height() + 4; + } + + if(m_label && (m_alignment & AlignVCenter)) + m_label->setGeometry(0, 0, w, m_sizeEdit.height()); + + d->spin->setGeometry(w, h, m_slider ? m_colw2 + : e->size().width() - w, m_sizeEdit.height()); + w += m_colw2 + 8; + + if(m_slider) + m_slider->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height()); + + h += m_sizeEdit.height() + 2; + + if(m_label && (m_alignment & AlignBottom)) + m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height()); +} + +void KDoubleNumInput::doLayout() +{ + m_sizeEdit = d->spin->sizeHint(); + m_colw2 = m_sizeEdit.width(); +} + +void KDoubleNumInput::setValue(double val) +{ + d->spin->setValue( val ); +} + +void KDoubleNumInput::setRelativeValue( double r ) +{ + if ( !d->referencePoint ) return; + ++d->blockRelative; + setValue( r * d->referencePoint ); + --d->blockRelative; +} + +void KDoubleNumInput::setReferencePoint( double ref ) +{ + // clip to valid range: + ref = kMin( maxValue(), kMax( minValue(), ref ) ); + d->referencePoint = ref; +} + +void KDoubleNumInput::setRange(double lower, double upper, double step, + bool slider) +{ + if( m_slider ) { + // don't update the slider to avoid an endless recursion + QSpinBox * spin = d->spin; + disconnect(spin, SIGNAL(valueChanged(int)), + m_slider, SLOT(setValue(int)) ); + } + d->spin->setRange( lower, upper, step, d->spin->precision() ); + + if(slider) { + // upcast to base type to get the min/maxValue in int form: + QSpinBox * spin = d->spin; + int slmax = spin->maxValue(); + int slmin = spin->minValue(); + int slvalue = spin->value(); + int slstep = spin->lineStep(); + if (m_slider) { + m_slider->setRange(slmin, slmax); + m_slider->setLineStep(slstep); + m_slider->setValue(slvalue); + } else { + m_slider = new QSlider(slmin, slmax, slstep, slvalue, + QSlider::Horizontal, this); + m_slider->setTickmarks(QSlider::Below); + // feedback line: when one moves, the other moves, too: + connect(m_slider, SIGNAL(valueChanged(int)), + SLOT(sliderMoved(int)) ); + } + connect(spin, SIGNAL(valueChanged(int)), + m_slider, SLOT(setValue(int)) ); + // calculate ( slmax - slmin ) / 10 without overflowing ints: + int major = calcDiffByTen( slmax, slmin ); + if ( !major ) major = slstep; // ### needed? + m_slider->setTickInterval(major); + } else { + delete m_slider; + m_slider = 0; + } + + setReferencePoint( referencePoint() ); + + layout(true); + updateLegacyMembers(); +} + +void KDoubleNumInput::setMinValue(double min) +{ + setRange(min, maxValue(), d->spin->lineStep(), m_slider); +} + +double KDoubleNumInput::minValue() const +{ + return d->spin->minValue(); +} + +void KDoubleNumInput::setMaxValue(double max) +{ + setRange(minValue(), max, d->spin->lineStep(), m_slider); +} + +double KDoubleNumInput::maxValue() const +{ + return d->spin->maxValue(); +} + +double KDoubleNumInput::value() const +{ + return d->spin->value(); +} + +double KDoubleNumInput::relativeValue() const +{ + if ( !d->referencePoint ) return 0; + return value() / d->referencePoint; +} + +double KDoubleNumInput::referencePoint() const +{ + return d->referencePoint; +} + +QString KDoubleNumInput::suffix() const +{ + return d->spin->suffix(); +} + +QString KDoubleNumInput::prefix() const +{ + return d->spin->prefix(); +} + +void KDoubleNumInput::setSuffix(const QString &suffix) +{ + d->spin->setSuffix( suffix ); + + layout(true); +} + +void KDoubleNumInput::setPrefix(const QString &prefix) +{ + d->spin->setPrefix( prefix ); + + layout(true); +} + +void KDoubleNumInput::setPrecision(int precision) +{ + d->spin->setPrecision( precision ); + + layout(true); +} + +int KDoubleNumInput::precision() const +{ + return d->spin->precision(); +} + +void KDoubleNumInput::setSpecialValueText(const QString& text) +{ + d->spin->setSpecialValueText( text ); + + layout(true); + updateLegacyMembers(); +} + +void KDoubleNumInput::setLabel(const QString & label, int a) +{ + KNumInput::setLabel(label, a); + + if(m_label) + m_label->setBuddy(d->spin); + +} + +// ---------------------------------------------------------------------------- + + +// We use a kind of fixed-point arithmetic to represent the range of +// doubles [mLower,mUpper] in steps of 10^(-mPrecision). Thus, the +// following relations hold: +// +// 1. factor = 10^mPrecision +// 2. basicStep = 1/factor = 10^(-mPrecision); +// 3. lowerInt = lower * factor; +// 4. upperInt = upper * factor; +// 5. lower = lowerInt * basicStep; +// 6. upper = upperInt * basicStep; +class KDoubleSpinBox::Private { +public: + Private( int precision=1 ) + : mPrecision( precision ), + mValidator( 0 ) + { + } + + int factor() const { + int f = 1; + for ( int i = 0 ; i < mPrecision ; ++i ) f *= 10; + return f; + } + + double basicStep() const { + return 1.0/double(factor()); + } + + int mapToInt( double value, bool * ok ) const { + assert( ok ); + const double f = factor(); + if ( value > double(INT_MAX) / f ) { + kdWarning() << "KDoubleSpinBox: can't represent value " << value + << "in terms of fixed-point numbers with precision " + << mPrecision << endl; + *ok = false; + return INT_MAX; + } else if ( value < double(INT_MIN) / f ) { + kdWarning() << "KDoubleSpinBox: can't represent value " << value + << "in terms of fixed-point numbers with precision " + << mPrecision << endl; + *ok = false; + return INT_MIN; + } else { + *ok = true; + return int( value * f + ( value < 0 ? -0.5 : 0.5 ) ); + } + } + + double mapToDouble( int value ) const { + return double(value) * basicStep(); + } + + int mPrecision; + KDoubleValidator * mValidator; +}; + +KDoubleSpinBox::KDoubleSpinBox( QWidget * parent, const char * name ) + : QSpinBox( parent, name ) +{ + editor()->setAlignment( Qt::AlignRight ); + d = new Private(); + updateValidator(); +} + +KDoubleSpinBox::KDoubleSpinBox( double lower, double upper, double step, + double value, int precision, + QWidget * parent, const char * name ) + : QSpinBox( parent, name ) +{ + editor()->setAlignment( Qt::AlignRight ); + d = new Private(); + setRange( lower, upper, step, precision ); + setValue( value ); + connect( this, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)) ); +} + +KDoubleSpinBox::~KDoubleSpinBox() { + delete d; d = 0; +} + +bool KDoubleSpinBox::acceptLocalizedNumbers() const { + if ( !d->mValidator ) return true; // we'll set one that does; + // can't do it now, since we're const + return d->mValidator->acceptLocalizedNumbers(); +} + +void KDoubleSpinBox::setAcceptLocalizedNumbers( bool accept ) { + if ( !d->mValidator ) updateValidator(); + d->mValidator->setAcceptLocalizedNumbers( accept ); +} + +void KDoubleSpinBox::setRange( double lower, double upper, double step, + int precision ) { + lower = kMin(upper, lower); + upper = kMax(upper, lower); + setPrecision( precision, true ); // disable bounds checking, since + setMinValue( lower ); // it's done in set{Min,Max}Value + setMaxValue( upper ); // anyway and we want lower, upper + setLineStep( step ); // and step to have the right precision +} + +int KDoubleSpinBox::precision() const { + return d->mPrecision; +} + +void KDoubleSpinBox::setPrecision( int precision ) { + setPrecision( precision, false ); +} + +void KDoubleSpinBox::setPrecision( int precision, bool force ) { + if ( precision < 1 ) return; + if ( !force ) { + int maxPrec = maxPrecision(); + if ( precision > maxPrec ) + precision = maxPrec; + } + d->mPrecision = precision; + updateValidator(); +} + +int KDoubleSpinBox::maxPrecision() const { + // INT_MAX must be > maxAbsValue * 10^precision + // ==> 10^precision < INT_MAX / maxAbsValue + // ==> precision < log10 ( INT_MAX / maxAbsValue ) + // ==> maxPrecision = floor( log10 ( INT_MAX / maxAbsValue ) ); + double maxAbsValue = kMax( fabs(minValue()), fabs(maxValue()) ); + if ( maxAbsValue == 0 ) return 6; // return arbitrary value to avoid dbz... + + return int( floor( log10( double(INT_MAX) / maxAbsValue ) ) ); +} + +double KDoubleSpinBox::value() const { + return d->mapToDouble( base::value() ); +} + +void KDoubleSpinBox::setValue( double value ) { + if ( value == this->value() ) return; + if ( value < minValue() ) + base::setValue( base::minValue() ); + else if ( value > maxValue() ) + base::setValue( base::maxValue() ); + else { + bool ok = false; + base::setValue( d->mapToInt( value, &ok ) ); + assert( ok ); + } +} + +double KDoubleSpinBox::minValue() const { + return d->mapToDouble( base::minValue() ); +} + +void KDoubleSpinBox::setMinValue( double value ) { + bool ok = false; + int min = d->mapToInt( value, &ok ); + if ( !ok ) return; + base::setMinValue( min ); + updateValidator(); +} + + +double KDoubleSpinBox::maxValue() const { + return d->mapToDouble( base::maxValue() ); +} + +void KDoubleSpinBox::setMaxValue( double value ) { + bool ok = false; + int max = d->mapToInt( value, &ok ); + if ( !ok ) return; + base::setMaxValue( max ); + updateValidator(); +} + +double KDoubleSpinBox::lineStep() const { + return d->mapToDouble( base::lineStep() ); +} + +void KDoubleSpinBox::setLineStep( double step ) { + bool ok = false; + if ( step > maxValue() - minValue() ) + base::setLineStep( 1 ); + else + base::setLineStep( kMax( d->mapToInt( step, &ok ), 1 ) ); +} + +QString KDoubleSpinBox::mapValueToText( int value ) { + if ( acceptLocalizedNumbers() ) + return KGlobal::locale() + ->formatNumber( d->mapToDouble( value ), d->mPrecision ); + else + return QString().setNum( d->mapToDouble( value ), 'f', d->mPrecision ); +} + +int KDoubleSpinBox::mapTextToValue( bool * ok ) { + double value; + if ( acceptLocalizedNumbers() ) + value = KGlobal::locale()->readNumber( cleanText(), ok ); + else + value = cleanText().toDouble( ok ); + if ( !*ok ) return 0; + if ( value > maxValue() ) + value = maxValue(); + else if ( value < minValue() ) + value = minValue(); + return d->mapToInt( value, ok ); +} + +void KDoubleSpinBox::setValidator( const QValidator * ) { + // silently discard the new validator. We don't want another one ;-) +} + +void KDoubleSpinBox::slotValueChanged( int value ) { + emit valueChanged( d->mapToDouble( value ) ); +} + +void KDoubleSpinBox::updateValidator() { + if ( !d->mValidator ) { + d->mValidator = new KDoubleValidator( minValue(), maxValue(), precision(), + this, "d->mValidator" ); + base::setValidator( d->mValidator ); + } else + d->mValidator->setRange( minValue(), maxValue(), precision() ); +} + +void KNumInput::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KIntNumInput::virtual_hook( int id, void* data ) +{ KNumInput::virtual_hook( id, data ); } + +void KDoubleNumInput::virtual_hook( int id, void* data ) +{ KNumInput::virtual_hook( id, data ); } + +void KIntSpinBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDoubleSpinBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "knuminput.moc" diff --git a/microkde/kdeui/knuminput.h b/microkde/kdeui/knuminput.h new file mode 100644 index 0000000..123fefa --- a/dev/null +++ b/microkde/kdeui/knuminput.h @@ -0,0 +1,948 @@ +/* + * knuminput.h + * + * Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca> + * Copyright (c) 2000 Dirk A. Mueller <mueller@kde.org> + * Copyright (c) 2002 Marc Mutz <mutz@kde.org> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef K_NUMINPUT_H +#define K_NUMINPUT_H + +#include <qwidget.h> +#include <qspinbox.h> + +class QLabel; +class QSlider; +class QLineEdit; +class QLayout; +class QValidator; + +class KIntSpinBox; + +/* ------------------------------------------------------------------------ */ + +/** + * You need to inherit from this class if you want to implement K*NumInput + * for a different variable type + * + */ +class KNumInput : public QWidget +{ + Q_OBJECT + Q_PROPERTY( QString label READ label WRITE setLabel ) +public: + /** + * Default constructor + * + */ + KNumInput(QWidget* parent=0, const char* name=0); + + /** + * @param below A pointer to another KNumInput. + * + */ + KNumInput(KNumInput* below, QWidget* parent=0, const char* name=0); + ~KNumInput(); + + /** + * Sets the text and alignment of the main description label. + * + * @param label The text of the label. + * Use QString::null to remove an existing one. + * + * @param a one of @p AlignLeft, @p AlignHCenter, YAlignRight and + * @p AlignTop, @p AlignVCenter, @p AlignBottom. + * default is @p AlignLeft | @p AlignTop. + * + * The vertical alignment flags have special meaning with this + * widget: + * + * @li @p AlignTop The label is placed above the edit/slider + * @li @p AlignVCenter The label is placed left beside the edit + * @li @p AlignBottom The label is placed below the edit/slider + * + */ + virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop); + + /** + * @return the text of the label. + */ + QString label() const; + + /** + * @return if the num input has a slider. + * @since 3.1 + */ + bool showSlider() const { return m_slider; } + + /** + * Sets the spacing of tickmarks for the slider. + * + * @param minor Minor tickmark separation. + * @param major Major tickmark separation. + */ + void setSteps(int minor, int major); + + /** + * Specifies that this widget may stretch horizontally, but is + * fixed vertically (like @ref QSpinBox itself). + */ + QSizePolicy sizePolicy() const; + + /** + * Returns a size which fits the contents of the control. + * + * @return the preferred size necessary to show the control + */ + virtual QSize sizeHint() const; + +protected: + /** + * Call this function whenever you change something in the geometry + * of your KNumInput child. + * + */ + void layout(bool deep); + + /** + * You need to overwrite this method and implement your layout + * calculations there. + * + * See KIntNumInput::doLayout and KDoubleNumInput::doLayout implementation + * for details. + * + */ + virtual void doLayout() = 0; + + KNumInput* m_prev, *m_next; + int m_colw1, m_colw2; + + QLabel* m_label; + QSlider* m_slider; + QSize m_sizeSlider, m_sizeLabel; + + int m_alignment; + +private: + void init(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KNumInputPrivate; + KNumInputPrivate *d; +}; + +/* ------------------------------------------------------------------------ */ + +/** + * KIntNumInput combines a @ref QSpinBox and optionally a @ref QSlider + * with a label to make an easy to use control for setting some integer + * parameter. This is especially nice for configuration dialogs, + * which can have many such combinated controls. + * + * The slider is created only when the user specifies a range + * for the control using the setRange function with the slider + * parameter set to "true". + * + * A special feature of KIntNumInput, designed specifically for + * the situation when there are several KIntNumInputs in a column, + * is that you can specify what portion of the control is taken by the + * QSpinBox (the remaining portion is used by the slider). This makes + * it very simple to have all the sliders in a column be the same size. + * + * It uses @ref KIntValidator validator class. KIntNumInput enforces the + * value to be in the given range, and can display it in any base + * between 2 and 36. + * + * @short An input widget for integer numbers, consisting of a spinbox and a slider. + * @version $Id$ + */ + +class KIntNumInput : public KNumInput +{ + Q_OBJECT + Q_PROPERTY( int value READ value WRITE setValue ) + Q_PROPERTY( int minValue READ minValue WRITE setMinValue ) + Q_PROPERTY( int maxValue READ maxValue WRITE setMaxValue ) + Q_PROPERTY( int referencePoint READ referencePoint WRITE setReferencePoint ) + Q_PROPERTY( QString suffix READ suffix WRITE setSuffix ) + Q_PROPERTY( QString prefix READ prefix WRITE setPrefix ) + Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText ) + +public: + /** + * Constructs an input control for integer values + * with base 10 and initial value 0. + */ + KIntNumInput(QWidget *parent=0, const char *name=0); + /** + * Constructor + * It constructs a QSpinBox that allows the input of integer numbers + * in the range of -INT_MAX to +INT_MAX. To set a descriptive label, + * use setLabel(). To enforce the value being in a range and optionally to + * attach a slider to it, use setRange(). + * + * @param value initial value for the control + * @param base numeric base used for display + * @param parent parent QWidget + * @param name internal name for this widget + */ + KIntNumInput(int value, QWidget* parent=0, int base = 10, const char *name=0); + + /** + * Constructor + * + * the difference to the one above is the "below" parameter. It tells + * this instance that it is visually put below some other KNumInput widget. + * Note that these two KNumInput's need not to have the same parent widget + * or be in the same layout group. + * The effect is that it'll adjust it's layout in correspondence + * with the layout of the other KNumInput's (you can build an arbitary long + * chain). + * + * @param below append KIntNumInput to the KNumInput chain + * @param value initial value for the control + * @param base numeric base used for display + * @param parent parent QWidget + * @param name internal name for this widget + */ + KIntNumInput(KNumInput* below, int value, QWidget* parent=0, int base = 10, const char *name=0); + + /** + * Destructor + * + * + */ + virtual ~KIntNumInput(); + + /** + * @return the current value. + */ + int value() const; + + /** + * @return the curent value in units of the @ref referencePoint. + * @since 3.1 + */ + double relativeValue() const; + + /** + * @return the current reference point + * @since 3.1 + */ + int referencePoint() const; + + /** + * @return the suffix displayed behind the value. + * @see #setSuffix() + */ + QString suffix() const; + /** + * @return the prefix displayed in front of the value. + * @see #setPrefix() + */ + QString prefix() const; + /** + * @return the string displayed for a special value. + * @see #setSpecialValueText() + */ + QString specialValueText() const; + + /** + * @param min minimum value + * @param max maximum value + * @param step step size for the QSlider + */ + void setRange(int min, int max, int step=1, bool slider=true); + /** + * Sets the minimum value. + */ + void setMinValue(int min); + /** + * @return the minimum value. + */ + int minValue() const; + /** + * Sets the maximum value. + */ + void setMaxValue(int max); + /** + * @return the maximum value. + */ + int maxValue() const; + + /** + * Sets the special value text. If set, the SpinBox will display + * this text instead of the numeric value whenever the current + * value is equal to minVal(). Typically this is used for indicating + * that the choice has a special (default) meaning. + */ + void setSpecialValueText(const QString& text); + + /** + * @reimplemented + */ + virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop); + + /** + * This method returns the minimum size necessary to display the + * control. The minimum size is enough to show all the labels + * in the current font (font change may invalidate the return value). + * + * @return the minimum size necessary to show the control + */ + virtual QSize minimumSizeHint() const; + +public slots: + /** + * Sets the value of the control. + */ + void setValue(int); + + /** + * Sets the value in units of the @ref referencePoint + * @since 3.1 + */ + void setRelativeValue(double); + + /** + * Sets the reference point for @ref relativeValue. + * @since 3.1 + */ + void setReferencePoint(int); + + /** + * Sets the suffix to @p suffix. + * Use QString::null to disable this feature. + * Formatting has to be provided (e.g. a space separator between the + * prepended @p value and the suffix's text has to be provided + * as the first character in the suffix). + * + * @see QSpinBox::setSuffix(), #setPrefix() + */ + void setSuffix(const QString &suffix); + + /** + * Sets the prefix to @p prefix. + * Use QString::null to disable this feature. + * Formatting has to be provided (see above). + * + * @see QSpinBox::setPrefix(), #setSuffix() + */ + void setPrefix(const QString &prefix); + + /** + * sets focus to the edit widget and marks all text in if mark == true + * + */ + void setEditFocus( bool mark = true ); + +signals: + /** + * Emitted every time the value changes (by calling @ref setValue() or + * by user interaction). + */ + void valueChanged(int); + + /** + * Emitted whenever @ref #valueChanged is. Contains the change + * relative to the @ref referencePoint. + * @since 3.1 + */ + void relativeValueChanged(double); + +private slots: + void spinValueChanged(int); + void slotEmitRelativeValueChanged(int); + +protected: + /** + * @reimplemented + */ + virtual void doLayout(); + /** + * @reimplemented + */ + void resizeEvent ( QResizeEvent * ); + + KIntSpinBox* m_spin; + QSize m_sizeSpin; + +private: + void init(int value, int _base); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KIntNumInputPrivate; + KIntNumInputPrivate *d; +}; + + +/* ------------------------------------------------------------------------ */ + +class KDoubleLine; + +/** + * KDoubleNumInput combines a @ref QSpinBox and optionally a @ref QSlider + * with a label to make an easy to use control for setting some float + * parameter. This is especially nice for configuration dialogs, + * which can have many such combinated controls. + * + * The slider is created only when the user specifies a range + * for the control using the setRange function with the slider + * parameter set to "true". + * + * A special feature of KDoubleNumInput, designed specifically for + * the situation when there are several instances in a column, + * is that you can specify what portion of the control is taken by the + * QSpinBox (the remaining portion is used by the slider). This makes + * it very simple to have all the sliders in a column be the same size. + * + * It uses the @ref KDoubleValidator validator class. KDoubleNumInput + * enforces the value to be in the given range, but see the class + * documentation of @ref KDoubleSpinBox for the tricky + * interrelationship of precision and values. All of what is said + * there applies here, too. + * + * @see KIntNumInput, KDoubleSpinBox + * @short An input control for real numbers, consisting of a spinbox and a slider. + */ + +class KDoubleNumInput : public KNumInput +{ + Q_OBJECT + Q_PROPERTY( double value READ value WRITE setValue ) + Q_PROPERTY( double minValue READ minValue WRITE setMinValue ) + Q_PROPERTY( double maxValue READ maxValue WRITE setMaxValue ) + Q_PROPERTY( QString suffix READ suffix WRITE setSuffix ) + Q_PROPERTY( QString prefix READ prefix WRITE setPrefix ) + Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText ) + Q_PROPERTY( int precision READ precision WRITE setPrecision ) + +public: + /** + * Constructs an input control for double values + * with initial value 0.00. + */ + KDoubleNumInput(QWidget *parent=0, const char *name=0); + + /** + * @deprecated (value is rounded to a multiple of 1/100) + * Constructor + * + * @param value initial value for the control + * @param parent parent QWidget + * @param name internal name for this widget + */ + KDoubleNumInput(double value, QWidget *parent=0, const char *name=0); + + /** + * Constructor + * + * @param lower lower boundary value + * @param upper upper boundary value + * @param value initial value for the control + * @param step step size to use for up/down arrow clicks + * @param precision number of digits after the decimal point + * @param parent parent QWidget + * @param name internal name for this widget + * @since 3.1 + */ + KDoubleNumInput(double lower, double upper, double value, double step=0.01, + int precision=2, QWidget *parent=0, const char *name=0); + + /** + * destructor + */ + virtual ~KDoubleNumInput(); + + /** + * @deprecated (rounds @p value to a mulitple of 1/100) + * Constructor + * + * puts it below other KNumInput + * + * @param below + * @param value initial value for the control + * @param parent parent QWidget + * @param name internal name for this widget + **/ + KDoubleNumInput(KNumInput* below, double value, QWidget* parent=0, const char* name=0); + + /** + * Constructor + * + * puts it below other KNumInput + * + * @param lower lower boundary value + * @param upper upper boundary value + * @param value initial value for the control + * @param step step size to use for up/down arrow clicks + * @param precision number of digits after the decimal point + * @param parent parent QWidget + * @param name internal name for this widget + * @since 3.1 + */ + KDoubleNumInput(KNumInput* below, + double lower, double upper, double value, double step=0.02, + int precision=2, QWidget *parent=0, const char *name=0); + + /** + * @return the current value. + */ + double value() const; + + /** + * @return the suffix. + * @see #setSuffix() + */ + QString suffix() const; + + /** + * @return the prefix. + * @see #setPrefix() + */ + QString prefix() const; + + /** + * @return the precision. + * @see #setPrecision() + */ + int precision() const; + + /** + * @return the string displayed for a special value. + * @see #setSpecialValueText() + */ + QString specialValueText() const { return m_specialvalue; } + + /** + * @param min minimum value + * @param max maximum value + * @param step step size for the QSlider + */ + void setRange(double min, double max, double step=1, bool slider=true); + /** + * Sets the minimum value. + */ + void setMinValue(double min); + /** + * @return the minimum value. + */ + double minValue() const; + /** + * Sets the maximum value. + */ + void setMaxValue(double max); + /** + * @return the maximum value. + */ + double maxValue() const; + + /** + * Specifies the number of digits to use. + */ + void setPrecision(int precision); + + /** + * @return the reference point for @ref #relativeValue calculation + * @since 3.1 + */ + double referencePoint() const; + + /** + * @return the current value in units of @ref #referencePoint. + * @since 3.1 + */ + double relativeValue() const; + + /** + * Sets the special value text. If set, the spin box will display + * this text instead of the numeric value whenever the current + * value is equal to @ref #minVal(). Typically this is used for indicating + * that the choice has a special (default) meaning. + */ + void setSpecialValueText(const QString& text); + + /** + * @reimplemented + */ + virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop); + /** + * @reimplemented + */ + virtual QSize minimumSizeHint() const; + /** + * @reimplemented + */ + virtual bool eventFilter(QObject*, QEvent*); + +public slots: + /** + * Sets the value of the control. + */ + void setValue(double); + + /** + * Sets the value in units of @ref #referencePoint. + * @since 3.1 + */ + void setRelativeValue(double); + + /** + * Sets the reference Point to @p ref. It @p ref == 0, emitting of + * @ref #relativeValueChanged is blocked and @ref #relativeValue + * just returns 0. + * @since 3.1 + */ + void setReferencePoint(double ref); + + /** + * Sets the suffix to be displayed to @p suffix. Use QString::null to disable + * this feature. Note that the suffix is attached to the value without any + * spacing. So if you prefer to display a space separator, set suffix + * to something like " cm". + * @see #setSuffix() + */ + void setSuffix(const QString &suffix); + + /** + * Sets the prefix to be displayed to @p prefix. Use QString::null to disable + * this feature. Note that the prefix is attached to the value without any + * spacing. + * @see #setPrefix() + */ + void setPrefix(const QString &prefix); + +signals: + /** + * Emitted every time the value changes (by calling @ref setValue() or + * by user interaction). + */ + void valueChanged(double); + /** + * This is an overloaded member function, provided for + * convenience. It essentially behaves like the above function. + * + * Contains the value in units of @ref #referencePoint. + * @since 3.1 + */ + void relativeValueChanged(double); + +private slots: + void sliderMoved(int); + void slotEmitRelativeValueChanged(double); + +protected: + + /** + * @reimplemented + */ + virtual void doLayout(); + /** + * @reimplemented + */ + void resizeEvent ( QResizeEvent * ); + virtual void resetEditBox(); + + // ### no longer used, remove when BIC allowed + KDoubleLine* edit; + + bool m_range; + double m_lower, m_upper, m_step; + // ### end no longer used + + QSize m_sizeEdit; + + friend class KDoubleLine; +private: + void init(double value, double lower, double upper, + double step, int precision); + double mapSliderToSpin(int) const; + void updateLegacyMembers(); + // ### no longer used, remove when BIC allowed: + QString m_specialvalue, m_prefix, m_suffix; + double m_value; + short m_precision; + // ### end remove when BIC allowed + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDoubleNumInputPrivate; + KDoubleNumInputPrivate *d; +}; + + +/* ------------------------------------------------------------------------ */ + +/** + * A @ref QSpinBox with support for arbitrary base numbers + * (e.g. hexadecimal). + * + * The class provides an easy interface to use other + * numeric systems than the decimal. + * + * @short A @ref QSpinBox with support for arbitrary base numbers. + */ +class KIntSpinBox : public QSpinBox +{ + Q_OBJECT + Q_PROPERTY( int base READ base WRITE setBase ) + +public: + + /** + * Constructor. + * + * Constructs a widget with an integer inputline with a little scrollbar + * and a slider, with minimal value 0, maximal value 99, step 1, base 10 + * and initial value 0. + */ + KIntSpinBox( QWidget *parent=0, const char *name=0); + + /** + * Constructor. + * + * Constructs a widget with an integer inputline with a little scrollbar + * and a slider. + * + * @param lower The lowest valid value. + * @param upper The greatest valid value. + * @param step The step size of the scrollbar. + * @param value The actual value. + * @param base The base of the used number system. + * @param parent The parent of the widget. + * @param name The Name of the widget. + */ + KIntSpinBox(int lower, int upper, int step, int value, int base = 10, + QWidget* parent = 0, const char* name = 0); + + /** + * Destructor. + */ + virtual ~KIntSpinBox(); + + /** + * Sets the base in which the numbers in the spin box are represented. + */ + void setBase(int base); + /** + * @return the base in which numbers in the spin box are represented. + */ + int base() const; + /** + * sets focus and optionally marks all text + * + */ + void setEditFocus(bool mark); + +protected: + + /** + * Overloaded the method in QSpinBox + * to make use of the base given in the constructor. + */ + virtual QString mapValueToText(int); + + /** + * Overloaded the method in QSpinBox + * to make use of the base given in the constructor. + */ + virtual int mapTextToValue(bool*); + +private: + int val_base; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KIntSpinBoxPrivate; + KIntSpinBoxPrivate *d; +}; + + +/* --------------------------------------------------------------------------- */ + +/** + This class provides a spin box for fractional numbers. + + @sect Parameters + + There are a number of interdependent parameters whose relation to + each other you need to understand in order to make successful use + of the spin box. + + @li precision: The number of decimals after the decimal point. + @li maxValue/minValue: upper and lower bound of the valid range + @li lineStep: the size of the step that is taken when the user hits + the up or down buttons + + Since we work with fixed-point numbers internally, the maximum + precision is a function of the valid range and vice versa. More + precisely, the following relations hold: + <pre> + max( abs(minValue()), abs(maxValue() ) <= INT_MAX/10^precision + maxPrecision = floor( log10( INT_MAX/max(abs(minValue()),abs(maxValue())) ) ) + </pre> + + Since the value, bounds and step are rounded to the current + precision, you may experience that the order of setting above + parameters matters. E.g. the following are @em not equivalent (try + it!): + + <pre> + // sets precision, + // then min/max value (rounded to precison and clipped to obtainable range if needed) + // then value and lineStep + KDoubleSpinBox * spin = new KDoubleSpinBox( 0, 9.999, 0.001, 4.321, 3, this ); + + // sets minValue to 0; maxValue to 10.00(!); value to 4.32(!) and only then + // increases the precision - too late, since e.g. value has already been rounded... + KDpubleSpinBox * spin = new KDoubleSpinBox( this ); + spin->setMinValue( 0 ); + spin->setMaxValue( 9.999 ); + spin->setValue( 4.321 ); + spin->setPrecision( 3 ); + </pre> + + @short A spin box for fractional numbers. + @author Marc Mutz <mutz@kde.org> + @version $Id$ + @since 3.1 +**/ + +class KDoubleSpinBox : public QSpinBox { + Q_OBJECT + Q_PROPERTY( bool acceptLocalizedNumbers READ acceptLocalizedNumbers WRITE setAcceptLocalizedNumbers ) + Q_OVERRIDE( double maxValue READ maxValue WRITE setMaxValue ) + Q_OVERRIDE( double minValue READ minValue WRITE setMinValue ) + Q_OVERRIDE( double lineStep READ lineStep WRITE setLineStep ) + Q_OVERRIDE( double value READ value WRITE setValue ) + Q_PROPERTY( int precision READ precision WRITE setPrecision ) + +public: + /** Constructs a @ref KDoubleSpinBox with parent @p parent and + default values for range and value (whatever @ref QRangeControl + uses) and precision (2). */ + KDoubleSpinBox( QWidget * parent=0, const char * name=0 ); + /** Constructs a @ref KDoubleSpinBox with parent @p parent, range + [@p lower,@p upper], @ref lineStep @p step, @ref precision @p + precision and initial value @p value. */ + KDoubleSpinBox( double lower, double upper, double step, double value, + int precision=2, QWidget * parent=0, const char * name=0 ); + + virtual ~KDoubleSpinBox(); + + /** @return whether the spinbox uses localized numbers */ + bool acceptLocalizedNumbers() const; + /** Sets whether to use and accept localized numbers as returned by + @ref KLocale::formatNumber() */ + virtual void setAcceptLocalizedNumbers( bool accept ); + + /** Sets a new range for the spin box values. Note that @p lower, @p + upper and @p step are rounded to @p precision decimal points + first. */ + void setRange( double lower, double upper, double step=0.01, int precision=2 ); + + /** @return the current number of decimal points displayed. */ + int precision() const; + /** Equivalent to @ref setPrecsion( @p precison, @p false ); Needed + since Qt's moc doesn't ignore trailing parameters with default + args when searching for a property setter method. */ + void setPrecision( int precision ); + /** Sets the number of decimal points to use. Note that there is a + tradeoff between the precision used and the available range of + values. See the class docs for more. + @param precision the new number of decimal points to use + + @param force disables checking of bound violations that can + arise if you increase the precision so much that the + minimum and maximum values can't be represented + anymore. Disabling is useful if you don't want to keep + the current min and max values anyway. This is what + e.g. @ref setRange() does. + **/ + virtual void setPrecision( int precision, bool force ); + + /** @return the current value */ + double value() const; + /** @return the current lower bound */ + double minValue() const; + /** Sets the lower bound of the range to @p value, subject to the + contraints that @p value is first rounded to the current + precision and then clipped to the maximum representable + interval. + @see maxValue, minValue, setMaxValue, setRange + */ + void setMinValue( double value ); + /** @return the current upper bound */ + double maxValue() const; + /** Sets the upper bound of the range to @p value, subject to the + contraints that @p value is first rounded to the current + precision and then clipped to the maximum representable + interval. + @see minValue, maxValue, setMinValue, setRange + */ + void setMaxValue( double value ); + + /** @return the current step size */ + double lineStep() const; + /** Sets the step size for clicking the up/down buttons to @p step, + subject to the constraints that @p step is first rounded to the + current precision and then clipped to the meaningful interval + [1, @p maxValue - @p minValue]. */ + void setLineStep( double step ); + + /** Overridden to ignore any setValidator() calls. */ + void setValidator( const QValidator * ); + +signals: + /** Emitted whenever @ref QSpinBox::valueChanged( int ) is emitted. */ + void valueChanged( double value ); + +public slots: + /** Sets the current value to @p value, cubject to the constraints + that @p value is frist rounded to the current precision and then + clipped to the interval [@p minvalue(),@p maxValue()]. */ + virtual void setValue( double value ); + +protected: + virtual QString mapValueToText(int); + virtual int mapTextToValue(bool*); + +protected slots: + void slotValueChanged( int value ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + typedef QSpinBox base; + void updateValidator(); + int maxPrecision() const; + + class Private; + Private * d; +}; + +#endif // K_NUMINPUT_H diff --git a/microkde/kdeui/knumvalidator.cpp b/microkde/kdeui/knumvalidator.cpp new file mode 100644 index 0000000..78a8471 --- a/dev/null +++ b/microkde/kdeui/knumvalidator.cpp @@ -0,0 +1,372 @@ +/********************************************************************** +** +** $Id$ +** +** KIntValidator, KFloatValidator: +** Copyright (C) 1999 Glen Parker <glenebob@nwlink.com> +** KDoubleValidator: +** Copyright (c) 2002 Marc Mutz <mutz@kde.org> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the Free +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +** +*****************************************************************************/ + +#include <qwidget.h> +#include <qstring.h> + +#include "knumvalidator.h" +#include <klocale.h> +#include <kglobal.h> +#include <kdebug.h> + +/////////////////////////////////////////////////////////////// +// Implementation of KIntValidator +// + +KIntValidator::KIntValidator ( QWidget * parent, int base, const char * name ) + : QValidator(parent, name) +{ + _base = base; + if (_base < 2) _base = 2; + if (_base > 36) _base = 36; + + _min = _max = 0; +} + +KIntValidator::KIntValidator ( int bottom, int top, QWidget * parent, int base, const char * name ) + : QValidator(parent, name) +{ + _base = base; + if (_base > 36) _base = 36; + + _min = bottom; + _max = top; +} + +KIntValidator::~KIntValidator () +{} + +QValidator::State KIntValidator::validate ( QString &str, int & ) const +{ + bool ok; + int val = 0; + QString newStr; + + newStr = str.stripWhiteSpace(); + if (_base > 10) + newStr = newStr.upper(); + + if (newStr == QString::fromLatin1("-")) // a special case + if ((_min || _max) && _min >= 0) + ok = false; + else + return QValidator::Acceptable; + else if (newStr.length()) + val = newStr.toInt(&ok, _base); + else { + val = 0; + ok = true; + } + + if (! ok) + return QValidator::Invalid; + + if ((! _min && ! _max) || (val >= _min && val <= _max)) + return QValidator::Acceptable; + + if (_max && _min >= 0 && val < 0) + return QValidator::Invalid; + + return QValidator::Valid; +} + +void KIntValidator::fixup ( QString &str ) const +{ + int dummy; + int val; + QValidator::State state; + + state = validate(str, dummy); + + if (state == QValidator::Invalid || state == QValidator::Acceptable) + return; + + if (! _min && ! _max) + return; + + val = str.toInt(0, _base); + + if (val < _min) val = _min; + if (val > _max) val = _max; + + str.setNum(val, _base); +} + +void KIntValidator::setRange ( int bottom, int top ) +{ + _min = bottom; + _max = top; + + if (_max < _min) + _max = _min; +} + +void KIntValidator::setBase ( int base ) +{ + _base = base; + if (_base < 2) _base = 2; +} + +int KIntValidator::bottom () const +{ + return _min; +} + +int KIntValidator::top () const +{ + return _max; +} + +int KIntValidator::base () const +{ + return _base; +} + + +/////////////////////////////////////////////////////////////// +// Implementation of KFloatValidator +// + +class KFloatValidatorPrivate +{ +public: + KFloatValidatorPrivate() + { + } + ~KFloatValidatorPrivate() + { + } + bool acceptLocalizedNumbers; +}; + + +KFloatValidator::KFloatValidator ( QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + d = new KFloatValidatorPrivate; + d->acceptLocalizedNumbers=false; + _min = _max = 0; +} + +KFloatValidator::KFloatValidator ( double bottom, double top, QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + d = new KFloatValidatorPrivate; + d->acceptLocalizedNumbers=false; + _min = bottom; + _max = top; +} + +KFloatValidator::KFloatValidator ( double bottom, double top, bool localeAware, QWidget * parent, const char * name ) + : QValidator(parent, name) +{ + d = new KFloatValidatorPrivate; + d->acceptLocalizedNumbers = localeAware; + _min = bottom; + _max = top; +} + +KFloatValidator::~KFloatValidator () +{ + delete d; +} + +void KFloatValidator::setAcceptLocalizedNumbers(bool _b) +{ + d->acceptLocalizedNumbers=_b; +} + +bool KFloatValidator::acceptLocalizedNumbers() const +{ + return d->acceptLocalizedNumbers; +} + +QValidator::State KFloatValidator::validate ( QString &str, int & ) const +{ + bool ok; + double val = 0; + QString newStr; + newStr = str.stripWhiteSpace(); + + if (newStr == QString::fromLatin1("-")) // a special case + if ((_min || _max) && _min >= 0) + ok = false; + else + return QValidator::Acceptable; + else if (newStr == QString::fromLatin1(".") || (d->acceptLocalizedNumbers && newStr==KGlobal::locale()->decimalSymbol())) // another special case + return QValidator::Acceptable; + else if (newStr.length()) + { + val = newStr.toDouble(&ok); + if(!ok && d->acceptLocalizedNumbers) + val= KGlobal::locale()->readNumber(newStr,&ok); + } + else { + val = 0; + ok = true; + } + + if (! ok) + return QValidator::Invalid; + + if (( !_min && !_max) || (val >= _min && val <= _max)) + return QValidator::Acceptable; + + if (_max && _min >= 0 && val < 0) + return QValidator::Invalid; + + if ( (_min || _max) && (val < _min || val > _max)) + return QValidator::Invalid; + + return QValidator::Valid; +} + +void KFloatValidator::fixup ( QString &str ) const +{ + int dummy; + double val; + QValidator::State state; + + state = validate(str, dummy); + + if (state == QValidator::Invalid || state == QValidator::Acceptable) + return; + + if (! _min && ! _max) + return; + + val = str.toDouble(); + + if (val < _min) val = _min; + if (val > _max) val = _max; + + str.setNum(val); +} + +void KFloatValidator::setRange ( double bottom, double top ) +{ + _min = bottom; + _max = top; + + if (_max < _min) + _max = _min; +} + +double KFloatValidator::bottom () const +{ + return _min; +} + +double KFloatValidator::top () const +{ + return _max; +} + + + + +/////////////////////////////////////////////////////////////// +// Implementation of KDoubleValidator +// + +class KDoubleValidator::Private { +public: + Private( bool accept=true ) : acceptLocalizedNumbers( accept ) {} + + bool acceptLocalizedNumbers; +}; + +KDoubleValidator::KDoubleValidator( QObject * parent, const char * name ) + : QDoubleValidator( (QWidget*)parent, name ), d( 0 ) +{ + d = new Private(); +} + +KDoubleValidator::KDoubleValidator( double bottom, double top, int decimals, + QObject * parent, const char * name ) + : QDoubleValidator( bottom, top, decimals, (QWidget*)parent, name ), d( 0 ) +{ + d = new Private(); +} + +KDoubleValidator::~KDoubleValidator() +{ + delete d; +} + +bool KDoubleValidator::acceptLocalizedNumbers() const { + return d->acceptLocalizedNumbers; +} + +void KDoubleValidator::setAcceptLocalizedNumbers( bool accept ) { + d->acceptLocalizedNumbers = accept; +} + +QValidator::State KDoubleValidator::validate( QString & input, int & p ) const { + QString s = input; + if ( acceptLocalizedNumbers() ) { + KLocale * l = KGlobal::locale(); + // ok, we have to re-format the number to have: + // 1. decimalSymbol == '.' + // 2. negativeSign == '-' + // 3. positiveSign == <empty> + // 4. thousandsSeparator() == <empty> (we don't check that there + // are exactly three decimals between each separator): + QString d = l->decimalSymbol(), + n = l->negativeSign(), + p = l->positiveSign(), + t = l->thousandsSeparator(); + // first, delete p's and t's: + if ( !p.isEmpty() ) + for ( int idx = s.find( p ) ; idx >= 0 ; idx = s.find( p, idx ) ) + s.remove( idx, p.length() ); + + + if ( !t.isEmpty() ) + for ( int idx = s.find( t ) ; idx >= 0 ; idx = s.find( t, idx ) ) + s.remove( idx, t.length() ); + + // then, replace the d's and n's + if ( ( !n.isEmpty() && n.find('.') != -1 ) || + ( !d.isEmpty() && d.find('-') != -1 ) ) { + // make sure we don't replace something twice: + kdWarning() << "KDoubleValidator: decimal symbol contains '-' or " + "negative sign contains '.' -> improve algorithm" << endl; + return Invalid; + } + + if ( !d.isEmpty() && d != "." ) + for ( int idx = s.find( d ) ; idx >= 0 ; idx = s.find( d, idx + 1 ) ) + s.replace( idx, d.length(), "."); + + if ( !n.isEmpty() && n != "-" ) + for ( int idx = s.find( n ) ; idx >= 0 ; idx = s.find( n, idx + 1 ) ) + s.replace( idx, n.length(), "-" ); + } + + return base::validate( s, p ); +} + +//US #include "knumvalidator.moc" diff --git a/microkde/kdeui/knumvalidator.h b/microkde/kdeui/knumvalidator.h new file mode 100644 index 0000000..2f0a937 --- a/dev/null +++ b/microkde/kdeui/knumvalidator.h @@ -0,0 +1,209 @@ +/********************************************************************** +** +** $Id$ +** +** Copyright (C) 1999 Glen Parker <glenebob@nwlink.com> +** Copyright (C) 2002 Marc Mutz <mutz@kde.org> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the Free +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +** +*****************************************************************************/ + +#ifndef __KNUMVALIDATOR_H +#define __KNUMVALIDATOR_H + +#include <qvalidator.h> + +class QWidget; +class QString; + +/** + * @ref QValidator for integers. + + This can be used by @ref QLineEdit or subclass to provide validated + text entry. Can be provided with a base value (default is 10), to allow + the proper entry of hexadecimal, octal, or any other base numeric data. + + @author Glen Parker <glenebob@nwlink.com> + @version 0.0.1 +*/ +class KIntValidator : public QValidator { + + public: + /** + Constuctor. Also sets the base value. + */ + KIntValidator ( QWidget * parent, int base = 10, const char * name = 0 ); + /** + * Constructor. Also sets the minimum, maximum, and numeric base values. + */ + KIntValidator ( int bottom, int top, QWidget * parent, int base = 10, const char * name = 0 ); + /** + * Destructs the validator. + */ + virtual ~KIntValidator (); + /** + * Validates the text, and return the result. Does not modify the parameters. + */ + virtual State validate ( QString &, int & ) const; + /** + * Fixes the text if possible, providing a valid string. The parameter may be modified. + */ + virtual void fixup ( QString & ) const; + /** + * Sets the minimum and maximum values allowed. + */ + virtual void setRange ( int bottom, int top ); + /** + * Sets the numeric base value. + */ + virtual void setBase ( int base ); + /** + * Returns the current minimum value allowed. + */ + virtual int bottom () const; + /** + * Returns the current maximum value allowed. + */ + virtual int top () const; + /** + * Returns the current numeric base. + */ + virtual int base () const; + + private: + int _base; + int _min; + int _max; + +}; + +class KFloatValidatorPrivate; + +/** + @obsolete Use @ref KDoubleValidator + + @ref QValidator for floating point entry. + Extends the QValidator class to properly validate double numeric data. + This can be used by @ref QLineEdit or subclass to provide validated + text entry. + + @author Glen Parker <glenebob@nwlink.com> + @version 0.0.1 +*/ +class KFloatValidator : public QValidator { + + public: + /** + * Constructor. + */ + KFloatValidator ( QWidget * parent, const char * name = 0 ); + /** + * Constructor. Also sets the minimum and maximum values. + */ + KFloatValidator ( double bottom, double top, QWidget * parent, const char * name = 0 ); + /** + * Constructor. Sets the validator to be locale aware if @p localeAware is true. + */ + KFloatValidator ( double bottom, double top, bool localeAware, QWidget * parent, const char * name = 0 ); + /** + * Destructs the validator. + */ + virtual ~KFloatValidator (); + /** + * Validates the text, and return the result. Does not modify the parameters. + */ + virtual State validate ( QString &, int & ) const; + /** + * Fixes the text if possible, providing a valid string. The parameter may be modified. + */ + virtual void fixup ( QString & ) const; + /** + * Sets the minimum and maximum value allowed. + */ + virtual void setRange ( double bottom, double top ); + /** + * Returns the current minimum value allowed. + */ + virtual double bottom () const; + /** + * Returns the current maximum value allowed. + */ + virtual double top () const; + /** + * Sets the validator to be locale aware if @p is true. In this case, the + * character KLocale::decimalSymbol() from the global locale is recognized + * as decimal separator. + */ + void setAcceptLocalizedNumbers(bool b); + /** + * Returns true if the validator is locale aware. + * @see setAcceptLocalizedNumbers(). + */ + bool acceptLocalizedNumbers() const; + + private: + double _min; + double _max; + + KFloatValidatorPrivate *d; +}; + +/** + KDoubleValidator extends @ref QDoubleValidator to be + locale-aware. That means that - subject to not being disabled - + @ref KLocale::decimalPoint(), @ref KLocale::thousandsSeparator() + and @ref KLocale::positiveSign() and @ref KLocale::negativeSign() + are respected. + + @short A locale-aware @ref QDoubleValidator + @author Marc Mutz <mutz@kde.org> + @version $Id$ + @see KIntValidator + @since 3.1 +**/ + +class KDoubleValidator : public QDoubleValidator { + Q_OBJECT + Q_PROPERTY( bool acceptLocalizedNumbers READ acceptLocalizedNumbers WRITE setAcceptLocalizedNumbers ) +public: + /** Constuct a locale-aware KDoubleValidator with default range + (whatever @ref QDoubleValidator uses for that) and parent @p + parent */ + KDoubleValidator( QObject * parent, const char * name=0 ); + /** Constuct a locale-aware KDoubleValidator for range [@p bottom,@p + top] and a precision of @p decimals decimals after the decimal + point. */ + KDoubleValidator( double bottom, double top, int decimals, + QObject * parent, const char * name=0 ); + /** Destructs the validator. + */ + virtual ~KDoubleValidator(); + + /** Overloaded for internal reasons. The API is not affected. */ + virtual QValidator::State validate( QString & input, int & pos ) const; + + /** @return whether localized numbers are accepted (default: true) */ + bool acceptLocalizedNumbers() const; + /** Sets whether to accept localized numbers (default: true) */ + void setAcceptLocalizedNumbers( bool accept ); + +private: + typedef QDoubleValidator base; + class Private; + Private * d; +}; + +#endif diff --git a/microkde/kdeui/kseparator.cpp b/microkde/kdeui/kseparator.cpp new file mode 100644 index 0000000..d028420 --- a/dev/null +++ b/microkde/kdeui/kseparator.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (C) 1997 Michael Roth <mroth@wirlweb.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <qstyle.h> + +#include <kdebug.h> +//US #include <kapplication.h> + +//US #include "kseparator.moc" + +#include "kseparator.h" + +KSeparator::KSeparator(QWidget* parent, const char* name, WFlags f) + : QFrame(parent, name, f) +{ + setLineWidth(1); + setMidLineWidth(0); + setOrientation( HLine ); +} + + + +KSeparator::KSeparator(int orientation, QWidget* parent, const char* name, WFlags f) + : QFrame(parent, name, f) +{ + setLineWidth(1); + setMidLineWidth(0); + setOrientation( orientation ); +} + + + +void KSeparator::setOrientation(int orientation) +{ + switch(orientation) + { + case Vertical: + case VLine: + setFrameStyle( QFrame::VLine | QFrame::Sunken ); + setMinimumSize(2, 0); + break; + + default: + kdWarning() << "KSeparator::setOrientation(): invalid orientation, using default orientation HLine" << endl; + + case Horizontal: + case HLine: + setFrameStyle( QFrame::HLine | QFrame::Sunken ); + setMinimumSize(0, 2); + break; + } +} + + + +int KSeparator::orientation() const +{ + if ( frameStyle() & VLine ) + return VLine; + + if ( frameStyle() & HLine ) + return HLine; + + return 0; +} + +void KSeparator::drawFrame(QPainter *p) +{ + QPoint p1, p2; + QRect r = frameRect(); + const QColorGroup & g = colorGroup(); + + if ( frameStyle() & HLine ) { + p1 = QPoint( r.x(), r.height()/2 ); + p2 = QPoint( r.x()+r.width(), p1.y() ); + } + else { + p1 = QPoint( r.x()+r.width()/2, 0 ); + p2 = QPoint( p1.x(), r.height() ); + } + +/*US + QStyleOption opt( lineWidth(), midLineWidth() ); + style().drawPrimitive( QStyle::PE_Separator, p, QRect( p1, p2 ), g, + QStyle::Style_Sunken, opt ); +*/ +//LRstyle().drawSeparator( p, p1.x(), p1.y(), p2.x(), p2.y(), g, true, lineWidth(), midLineWidth()); + +} + + +QSize KSeparator::sizeHint() const +{ + if ( frameStyle() & VLine ) + return QSize(2, 0); + + if ( frameStyle() & HLine ) + return QSize(0, 2); + + return QSize(-1, -1); +} + +void KSeparator::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + diff --git a/microkde/kdeui/kseparator.h b/microkde/kdeui/kseparator.h new file mode 100644 index 0000000..6d2712a --- a/dev/null +++ b/microkde/kdeui/kseparator.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 1997 Michael Roth <mroth@wirlweb.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __KSEPARATOR_H__ +#define __KSEPARATOR_H__ + +#include <qframe.h> + +/** + * Standard horizontal or vertical separator. + * + * @author Michael Roth <mroth@wirlweb.de> + * @version $Id$ +*/ +class KSeparator : public QFrame +{ + Q_OBJECT + Q_PROPERTY( int orientation READ orientation WRITE setOrientation ) + public: + /** + * Constructor. + **/ + KSeparator(QWidget* parent=0, const char* name=0, WFlags f=0); + /** + * Constructor. + * + * @param orientation Set the orientation of the separator. + * Possible values are HLine or Horizontal and VLine or Vertical. + **/ + KSeparator(int orientation, QWidget* parent=0, const char* name=0, + WFlags f=0); + + /** + * Returns the orientation of the separator. + * + * Possible values are VLine and HLine. + **/ + int orientation() const; + + /** + * Set the orientation of the separator to @p orient + * + * Possible values are VLine and HLine. + */ + void setOrientation(int orient); + + /** + * The recommended height (width) for a horizontal (vertical) separator. + **/ + virtual QSize sizeHint() const; + +protected: + virtual void drawFrame( QPainter * ); +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KSeparatorPrivate* d; +}; + + +#endif // __KSEPARATOR_H__ diff --git a/microkde/kdeui/ksqueezedtextlabel.cpp b/microkde/kdeui/ksqueezedtextlabel.cpp new file mode 100644 index 0000000..37fa29a --- a/dev/null +++ b/microkde/kdeui/ksqueezedtextlabel.cpp @@ -0,0 +1,107 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Ronny Standtke <Ronny.Standtke@gmx.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "ksqueezedtextlabel.h" +#include <qtooltip.h> + +KSqueezedTextLabel::KSqueezedTextLabel( const QString &text , QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed )); + fullText = text; + squeezeTextToLabel(); +} + +KSqueezedTextLabel::KSqueezedTextLabel( QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed )); +} + +void KSqueezedTextLabel::resizeEvent( QResizeEvent * ) { + squeezeTextToLabel(); +} + +QSize KSqueezedTextLabel::minimumSizeHint() const +{ + QSize sh = QLabel::minimumSizeHint(); + sh.setWidth(-1); + return sh; +} + +void KSqueezedTextLabel::setText( const QString &text ) { + fullText = text; + squeezeTextToLabel(); +} + +void KSqueezedTextLabel::squeezeTextToLabel() { + QFontMetrics fm(fontMetrics()); + int labelWidth = size().width(); + int textWidth = fm.width(fullText); + if (textWidth > labelWidth) { + // start with the dots only + QString squeezedText = "..."; + int squeezedWidth = fm.width(squeezedText); + + // estimate how many letters we can add to the dots on both sides + int letters = fullText.length() * (labelWidth - squeezedWidth) / textWidth / 2; + if (labelWidth < squeezedWidth) letters=1; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + + if (squeezedWidth < labelWidth) { + // we estimated too short + // add letters while text < label + do { + letters++; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + } while (squeezedWidth < labelWidth); + letters--; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + } else if (squeezedWidth > labelWidth) { + // we estimated too long + // remove letters while text > label + do { + letters--; + squeezedText = fullText.left(letters) + "..." + fullText.right(letters); + squeezedWidth = fm.width(squeezedText); + } while (letters && squeezedWidth > labelWidth); + } + + if (letters < 5) { + // too few letters added -> we give up squeezing + QLabel::setText(fullText); + } else { + QLabel::setText(squeezedText); + } + +//US QToolTip::remove( this ); +//US QToolTip::add( this, fullText ); + + } else { + QLabel::setText(fullText); + +//US QToolTip::remove( this ); +//US QToolTip::hide(); + + }; +} + +void KSqueezedTextLabel::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "ksqueezedtextlabel.moc" diff --git a/microkde/kdeui/ksqueezedtextlabel.h b/microkde/kdeui/ksqueezedtextlabel.h new file mode 100644 index 0000000..1634adc --- a/dev/null +++ b/microkde/kdeui/ksqueezedtextlabel.h @@ -0,0 +1,76 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Ronny Standtke <Ronny.Standtke@gmx.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KSQUEEZEDTEXTLABEL_H +#define KSQUEEZEDTEXTLABEL_H + +#include <qlabel.h> + +/** + * A label class that squeezes its text into the label + * + * If the text is too long to fit into the label it is divided into + * remaining left and right parts which are separated by three dots. + * + * Example: + * http://www.kde.org/documentation/index.html could be squeezed to + * http://www.kde...ion/index.html + + * @short A replacement for QLabel that squeezes its text + * @author Ronny Standtke <Ronny.Standtke@gmx.de> + * @version $Id$ + * + */ + +/* + * @ref QLabel + */ +class KSqueezedTextLabel : public QLabel { + Q_OBJECT + +public: + /** + * Default constructor. + */ + KSqueezedTextLabel( QWidget *parent, const char *name = 0 ); + KSqueezedTextLabel( const QString &text, QWidget *parent, const char *name = 0 ); + + virtual QSize minimumSizeHint() const; + +public slots: + void setText( const QString & ); + +protected: + /** + * used when widget is resized + */ + void resizeEvent( QResizeEvent * ); + /** + * does the dirty work + */ + void squeezeTextToLabel(); + QString fullText; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KSqueezedTextLabelPrivate; + KSqueezedTextLabelPrivate *d; +}; + +#endif // KSQUEEZEDTEXTLABEL_H diff --git a/microkde/kdeui/kstdaction.cpp b/microkde/kdeui/kstdaction.cpp new file mode 100644 index 0000000..cfd7b54 --- a/dev/null +++ b/microkde/kdeui/kstdaction.cpp @@ -0,0 +1,362 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000 Kurt Granroth <granroth@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kstdaction.h" + +#include <qtoolbutton.h> +#include <qwhatsthis.h> + +//US #include <kaboutdata.h> +#include <kaction.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> +//US #include <kstdaccel.h> +//US #include <kmainwindow.h> + +namespace KStdAction +{ + +struct KStdActionInfo +{ + StdAction id; +/*US KStdAccel::StdAccel idAccel;*/ + const char* psName; + const char* psLabel; + const char* psWhatsThis; + const char* psIconName; +}; + +const KStdActionInfo g_rgActionInfo[] = +{ + { New, /*USKStdAccel::New,*/ "file_new", I18N_NOOP("&New"), 0, "filenew" }, + { Open, /*USKStdAccel::Open,*/ "file_open", I18N_NOOP("&Open..."), 0, "fileopen" }, + { OpenRecent, /*USKStdAccel::AccelNone,*/ "file_open_recent", I18N_NOOP("Open &Recent"), 0, 0 }, + { Save, /*USKStdAccel::Save,*/ "file_save", I18N_NOOP("&Save"), 0, "filesave" }, + { SaveAs, /*USKStdAccel::AccelNone,*/ "file_save_as", I18N_NOOP("Save &As..."), 0, "filesaveas" }, + { Revert, /*USKStdAccel::AccelNone,*/ "file_revert", I18N_NOOP("Re&vert"), 0, "revert" }, + { Close, /*USKStdAccel::Close,*/ "file_close", I18N_NOOP("&Close"), 0, "fileclose" }, + { Print, /*USKStdAccel::Print,*/ "file_print", I18N_NOOP("&Print..."), 0, "fileprint" }, + { PrintPreview, /*USKStdAccel::AccelNone,*/ "file_print_preview", I18N_NOOP("Print Previe&w..."), 0, "filequickprint" }, + { Mail, /*USKStdAccel::AccelNone,*/ "file_mail", I18N_NOOP("&Mail..."), 0, "mail_send" }, + { Quit, /*USKStdAccel::Quit,*/ "file_quit", I18N_NOOP("&Exit"), 0, "exit" }, + + { Undo, /*USKStdAccel::Undo,*/ "edit_undo", I18N_NOOP("&Undo"), 0, "undo" }, + { Redo, /*USKStdAccel::Redo,*/ "edit_redo", I18N_NOOP("Re&do"), 0, "redo" }, + { Cut, /*USKStdAccel::Cut,*/ "edit_cut", I18N_NOOP("Cu&t"), 0, "editcut" }, + { Copy, /*USKStdAccel::Copy,*/ "edit_copy", I18N_NOOP("&Copy"), 0, "editcopy" }, + { Paste, /*USKStdAccel::Paste,*/ "edit_paste", I18N_NOOP("&Paste"), 0, "editpaste" }, + { SelectAll, /*USKStdAccel::SelectAll,*/ "edit_select_all", I18N_NOOP("Select &All"), 0, 0 }, + { Deselect, /*USKStdAccel::Deselect,*/ "edit_deselect", I18N_NOOP("Dese&lect"), 0, 0 }, + { Find, /*USKStdAccel::Find,*/ "edit_find", I18N_NOOP("&Find..."), 0, "find" }, + { FindNext, /*USKStdAccel::FindNext,*/ "edit_find_next", I18N_NOOP("Find &Next"), 0, "next" }, + // FIXME: rename edit_find_last to edit_find_prev for KDE 4 + { FindPrev, /*USKStdAccel::FindPrev,*/ "edit_find_last", I18N_NOOP("Find Pre&vious"), 0, "previous" }, + { Replace, /*USKStdAccel::Replace,*/ "edit_replace", I18N_NOOP("&Replace..."), 0, 0 }, + + { ActualSize, /*USKStdAccel::AccelNone,*/ "view_actual_size", I18N_NOOP("&Actual Size"), 0, 0 }, + { FitToPage, /*USKStdAccel::AccelNone,*/ "view_fit_to_page", I18N_NOOP("&Fit to Page"), 0, 0 }, + { FitToWidth, /*USKStdAccel::AccelNone,*/ "view_fit_to_width", I18N_NOOP("Fit to Page &Width"), 0, 0 }, + { FitToHeight, /*USKStdAccel::AccelNone,*/ "view_fit_to_height", I18N_NOOP("Fit to Page &Height"), 0, 0 }, + { ZoomIn, /*USKStdAccel::ZoomIn,*/ "view_zoom_in", I18N_NOOP("Zoom &In"), 0, "viewmag+" }, + { ZoomOut, /*USKStdAccel::ZoomOut,*/ "view_zoom_out", I18N_NOOP("Zoom &Out"), 0, "viewmag-" }, + { Zoom, /*USKStdAccel::AccelNone,*/ "view_zoom", I18N_NOOP("&Zoom..."), 0, "viewmag" }, + { Redisplay, /*USKStdAccel::AccelNone,*/ "view_redisplay", I18N_NOOP("&Redisplay"), 0, "reload" }, + + { Up, /*USKStdAccel::Up,*/ "go_up", I18N_NOOP("&Up"), 0, "up" }, + // The following three have special i18n() needs for sLabel + { Back, /*USKStdAccel::Back,*/ "go_back", 0, 0, "back" }, + { Forward, /*USKStdAccel::Forward,*/ "go_forward", 0, 0, "forward" }, + { Home, /*USKStdAccel::Home,*/ "go_home", 0, 0, "gohome" }, + { Prior, /*USKStdAccel::Prior,*/ "go_previous", I18N_NOOP("&Previous Page"), 0, "previous" }, + { Next, /*USKStdAccel::Next,*/ "go_next", I18N_NOOP("&Next Page"), 0, "next" }, + { Goto, /*USKStdAccel::AccelNone,*/ "go_goto", I18N_NOOP("&Go To..."), 0, 0 }, + { GotoPage, /*USKStdAccel::AccelNone,*/ "go_goto_page", I18N_NOOP("&Go to Page..."), 0, "goto" }, + { GotoLine, /*USKStdAccel::GotoLine,*/ "go_goto_line", I18N_NOOP("&Go to Line..."), 0, 0 }, + { FirstPage, /*USKStdAccel::Home,*/ "go_first", I18N_NOOP("&First Page"), 0, "top" }, + { LastPage, /*USKStdAccel::End,*/ "go_last", I18N_NOOP("&Last Page"), 0, "bottom" }, + + { AddBookmark, /*USKStdAccel::AddBookmark,*/ "bookmark_add", I18N_NOOP("&Add Bookmark"), 0, "bookmark_add" }, + { EditBookmarks, /*USKStdAccel::AccelNone,*/ "bookmark_edit", I18N_NOOP("&Edit Bookmarks"), 0, "bookmark" }, + + { Spelling, /*USKStdAccel::AccelNone,*/ "tools_spelling", I18N_NOOP("&Spelling..."), 0, "spellcheck" }, + + { ShowMenubar, /*USKStdAccel::ShowMenubar,*/ "options_show_menubar", I18N_NOOP("Show &Menubar"), 0, "showmenu" }, + { ShowToolbar, /*USKStdAccel::AccelNone,*/ "options_show_toolbar", I18N_NOOP("Show &Toolbar"), 0, 0 }, + { ShowStatusbar, /*USKStdAccel::AccelNone,*/ "options_show_statusbar", I18N_NOOP("Show St&atusbar"), 0, 0 }, + { SaveOptions, /*USKStdAccel::AccelNone,*/ "options_save_options", I18N_NOOP("&Save Settings"), 0, 0 }, + { KeyBindings, /*USKStdAccel::AccelNone,*/ "options_configure_keybinding", I18N_NOOP("Configure S&hortcuts..."), 0,"configure_shortcuts" }, + { Preferences, /*USKStdAccel::AccelNone,*/ "options_configure", I18N_NOOP("&Configure %1..."), 0, "configure" }, + { ConfigureToolbars, /*USKStdAccel::AccelNone,*/ "options_configure_toolbars", I18N_NOOP("Configure Tool&bars..."), 0,"configure_toolbars" }, + { ConfigureNotifications, /*USKStdAccel::AccelNone,*/ "options_configure_notifications", I18N_NOOP("Configure &Notifications..."), 0, "knotify" }, + + { Help, /*USKStdAccel::Help,*/ "help", 0, 0, "help" }, + { HelpContents, /*USKStdAccel::AccelNone,*/ "help_contents", I18N_NOOP("%1 &Handbook"), 0, "contents" }, + { WhatsThis, /*USKStdAccel::WhatsThis,*/ "help_whats_this", I18N_NOOP("What's &This?"), 0, "contexthelp" }, + { TipofDay, /*USKStdAccel::AccelNone,*/ "help_show_tip", I18N_NOOP("Tip of the &Day"), 0, "idea" }, + { ReportBug, /*USKStdAccel::AccelNone,*/ "help_report_bug", I18N_NOOP("&Report Bug..."), 0, 0 }, + { AboutApp, /*USKStdAccel::AccelNone,*/ "help_about_app", I18N_NOOP("&About %1"), 0, 0 }, + { AboutKDE, /*USKStdAccel::AccelNone,*/ "help_about_kde", I18N_NOOP("About &KDE"), 0,"about_kde" }, + { ActionNone, /*USKStdAccel::AccelNone,*/ 0, 0, 0, 0 } +}; + +static const KStdActionInfo* infoPtr( StdAction id ) +{ + for( uint i = 0; g_rgActionInfo[i].id != ActionNone; i++ ) { + if( g_rgActionInfo[i].id == id ) + return &g_rgActionInfo[i]; + } + return 0; +} + +QStringList stdNames() +{ + QStringList result; + + for( uint i = 0; g_rgActionInfo[i].id != ActionNone; i++ ) + if (g_rgActionInfo[i].psLabel) + result.append(i18n(g_rgActionInfo[i].psLabel)); + return result; +} + +KAction* create( StdAction id, const char *name, const QObject *recvr, const char *slot, KActionCollection* parent ) +{ + KAction* pAction = 0; + const KStdActionInfo* pInfo = infoPtr( id ); + kdDebug(125) << "KStdAction::create( " << id << "=" << (pInfo ? pInfo->psName : (const char*)0) << ", " << parent << ", " << name << " )" << endl; // ellis + if( pInfo ) { + QString sLabel, iconName = pInfo->psIconName; + switch( id ) { + case Back: sLabel = i18n("go back", "&Back"); +//US if (QApplication::reverseLayout() ) +//US iconName = "forward"; + break; + + case Forward: sLabel = i18n("go forward", "&Forward"); +//US if (QApplication::reverseLayout() ) +//US iconName = "back"; + break; + + case Home: sLabel = i18n("beginning (of line)", "&Home"); break; + case Help: sLabel = i18n("show help", "&Help"); break; +//US case AboutApp: iconName = kapp->miniIconName(); + case Preferences: + case HelpContents: + { +//US const KAboutData *aboutData = KGlobal::instance()->aboutData(); +//US QString appName = (aboutData) ? aboutData->programName() : QString::fromLatin1(qApp->name()); + QString appName = QString::fromLatin1(KGlobal::getAppName()); + sLabel = i18n(pInfo->psLabel).arg(appName); + } + break; + default: sLabel = i18n(pInfo->psLabel); + } + +/*US if (QApplication::reverseLayout()){ + if (id == Prior) iconName = "next"; + if (id == Next ) iconName = "previous"; + } +*/ +//US KShortcut cut = KStdAccel::shortcut(pInfo->idAccel); + KShortcut cut; + switch( id ) { + case OpenRecent: + pAction = new KRecentFilesAction( sLabel, cut, + recvr, slot, + parent, (name) ? name : pInfo->psName ); + break; + case ShowMenubar: + case ShowToolbar: + case ShowStatusbar: + KToggleAction *ret; + ret = new KToggleAction( sLabel, pInfo->psIconName, cut, + recvr, slot, + parent, (name) ? name : pInfo->psName ); + ret->setChecked( true ); + pAction = ret; + break; + default: + pAction = new KAction( sLabel, iconName, cut, + recvr, slot, + parent, (name) ? name : pInfo->psName ); + break; + } + } + return pAction; +} + +const char* name( StdAction id ) +{ + const KStdActionInfo* pInfo = infoPtr( id ); + return (pInfo) ? pInfo->psName : 0; +} + +KAction *openNew( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( New, name, recvr, slot, parent ); } +KAction *open( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Open, name, recvr, slot, parent ); } +KRecentFilesAction *openRecent( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return (KRecentFilesAction*) KStdAction::create( OpenRecent, name, recvr, slot, parent ); } +KAction *save( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Save, name, recvr, slot, parent ); } +KAction *saveAs( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( SaveAs, name, recvr, slot, parent ); } +KAction *revert( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Revert, name, recvr, slot, parent ); } +KAction *print( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Print, name, recvr, slot, parent ); } +KAction *printPreview( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( PrintPreview, name, recvr, slot, parent ); } +KAction *close( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Close, name, recvr, slot, parent ); } +KAction *mail( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Mail, name, recvr, slot, parent ); } +KAction *quit( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Quit, name, recvr, slot, parent ); } +KAction *undo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Undo, name, recvr, slot, parent ); } +KAction *redo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Redo, name, recvr, slot, parent ); } +KAction *cut( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Cut, name, recvr, slot, parent ); } +KAction *copy( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Copy, name, recvr, slot, parent ); } +KAction *paste( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Paste, name, recvr, slot, parent ); } +KAction *selectAll( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( SelectAll, name, recvr, slot, parent ); } +KAction *deselect( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Deselect, name, recvr, slot, parent ); } +KAction *find( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Find, name, recvr, slot, parent ); } +KAction *findNext( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FindNext, name, recvr, slot, parent ); } +KAction *findPrev( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FindPrev, name, recvr, slot, parent ); } +KAction *replace( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Replace, name, recvr, slot, parent ); } +KAction *actualSize( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ActualSize, name, recvr, slot, parent ); } +KAction *fitToPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FitToPage, name, recvr, slot, parent ); } +KAction *fitToWidth( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FitToWidth, name, recvr, slot, parent ); } +KAction *fitToHeight( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FitToHeight, name, recvr, slot, parent ); } +KAction *zoomIn( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ZoomIn, name, recvr, slot, parent ); } +KAction *zoomOut( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ZoomOut, name, recvr, slot, parent ); } +KAction *zoom( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Zoom, name, recvr, slot, parent ); } +KAction *redisplay( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Redisplay, name, recvr, slot, parent ); } +KAction *up( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Up, name, recvr, slot, parent ); } +KAction *back( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Back, name, recvr, slot, parent ); } +KAction *forward( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Forward, name, recvr, slot, parent ); } +KAction *home( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Home, name, recvr, slot, parent ); } +KAction *prior( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Prior, name, recvr, slot, parent ); } +KAction *next( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Next, name, recvr, slot, parent ); } +KAction *goTo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Goto, name, recvr, slot, parent ); } +KAction *gotoPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( GotoPage, name, recvr, slot, parent ); } +KAction *gotoLine( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( GotoLine, name, recvr, slot, parent ); } +KAction *firstPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( FirstPage, name, recvr, slot, parent ); } +KAction *lastPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( LastPage, name, recvr, slot, parent ); } +KAction *addBookmark( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( AddBookmark, name, recvr, slot, parent ); } +KAction *editBookmarks( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( EditBookmarks, name, recvr, slot, parent ); } +KAction *spelling( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Spelling, name, recvr, slot, parent ); } + +KToggleAction *showMenubar( const QObject *recvr, const char *slot, KActionCollection* parent, const char *_name ) +{ + KToggleAction *ret; + ret = new KToggleAction(i18n("Show &Menubar"), "showmenu", /*US KStdAccel::shortcut(KStdAccel::ShowMenubar)*/0, recvr, slot, + parent, _name ? _name : name(ShowMenubar)); + ret->setChecked(true); + return ret; +} + +KToggleAction *showToolbar( const QObject *recvr, const char *slot, KActionCollection* parent, const char *_name ) +{ + KToggleAction *ret; + ret = new KToggleAction(i18n("Show &Toolbar"), 0, recvr, slot, parent, + _name ? _name : name(ShowToolbar)); + ret->setChecked(true); + return ret; + +} + +KToggleToolBarAction *showToolbar( const char* toolBarName, KActionCollection* parent, const char *_name ) +{ + KToggleToolBarAction *ret; + ret = new KToggleToolBarAction(toolBarName, i18n("Show &Toolbar"), parent, + _name ? _name : name(ShowToolbar)); + return ret; +} + +KToggleAction *showStatusbar( const QObject *recvr, const char *slot, + KActionCollection* parent, const char *_name ) +{ + KToggleAction *ret; + ret = new KToggleAction(i18n("Show St&atusbar"), 0, recvr, slot, parent, + _name ? _name : name(ShowStatusbar)); + ret->setChecked(true); + return ret; +} + +KAction *saveOptions( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( SaveOptions, name, recvr, slot, parent ); } +KAction *keyBindings( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( KeyBindings, name, recvr, slot, parent ); } +KAction *preferences( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Preferences, name, recvr, slot, parent ); } +KAction *configureToolbars( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ConfigureToolbars, name, recvr, slot, parent ); } +KAction *configureNotifications( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ConfigureNotifications, name, recvr, slot, parent ); } +KAction *help( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( Help, name, recvr, slot, parent ); } +KAction *helpContents( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( HelpContents, name, recvr, slot, parent ); } +KAction *whatsThis( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( WhatsThis, name, recvr, slot, parent ); } +KAction *tipOfDay( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( TipofDay, name, recvr, slot, parent ); } +KAction *reportBug( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( ReportBug, name, recvr, slot, parent ); } +KAction *aboutApp( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( AboutApp, name, recvr, slot, parent ); } +KAction *aboutKDE( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name ) + { return KStdAction::create( AboutKDE, name, recvr, slot, parent ); } + +} diff --git a/microkde/kdeui/kstdaction.h b/microkde/kdeui/kstdaction.h new file mode 100644 index 0000000..bc712b3 --- a/dev/null +++ b/microkde/kdeui/kstdaction.h @@ -0,0 +1,568 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000 Kurt Granroth <granroth@kde.org> + Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KSTDACTION_H +#define KSTDACTION_H + +class QObject; +class KAction; +class KActionCollection; +class KRecentFilesAction; +class KToggleAction; +class KToggleToolBarAction; + +#include <qstringlist.h> + +/** + * Convenience methods to access all standard KDE actions. + * + * These actions should be used instead of hardcoding menubar and + * toolbar items. Using these actions helps your application easily + * conform to the KDE UI Style Guide + * @see http://developer.kde.org/documentation/standards/kde/style/basics/index.html . + * + * All of the documentation for @ref KAction holds for KStdAction + * also. When in doubt on how things work, check the @ref KAction + * documention first. + * + * @sect Simple Example: + * + * In general, using standard actions should be a drop in replacement + * for regular actions. For example, if you previously had: + * + * <PRE> + * KAction *newAct = new KAction(i18n("&New"), QIconSet(BarIcon("filenew")), + * KStdAccel::key(KStdAccel::New), this, + * SLOT(fileNew()), actionCollection()); + * </PRE> + * + * You could drop that and replace it with: + * + * <PRE> + * KAction *newAct = KStdAction::openNew(this, SLOT(fileNew()), + * actionCollection()); + * </PRE> + * + * @sect Non-standard Usages + * + * It is possible to use the standard actions in various + * non-recommended ways. Say, for instance, you wanted to have a + * standard action (with the associated correct text and icon and + * accelerator, etc) but you didn't want it to go in the standard + * place (this is not recommended, by the way). One way to do this is + * to simply not use the XML UI framework and plug it into wherever + * you want. If you do want to use the XML UI framework (good!), then + * it is still possible. + * + * Basically, the XML building code matches names in the XML code with + * the internal names of the actions. You can find out the internal + * names of each of the standard actions by using the @ref stdName + * action like so: @ref KStdAction::stdName(KStdAction::Cut) would return + * 'edit_cut'. The XML building code will match 'edit_cut' to the + * attribute in the global XML file and place your action there. + * + * However, you can change the internal name. In this example, just + * do something like: + * + * <PRE> + * (void)KStdAction::cut(this, SLOT(editCut()), actionCollection(), "my_cut"); + * </PRE> + * + * Now, in your local XML resource file (e.g., yourappui.rc), simply + * put 'my_cut' where you want it to go. + * + * Another non-standard usage concerns getting a pointer to an + * existing action if, say, you want to enable or disable the action. + * You could do it the recommended way and just grab a pointer when + * you instantiate it as in the the 'openNew' example above... or you + * could do it the hard way: + * + * <pre> + * KAction *cut = actionCollection()->action(KStdAction::stdName(KStdAction::Cut)); + * </pre> + * + * Another non-standard usage concerns instantiating the action in the + * first place. Usually, you would use the member functions as + * shown above (e.g., KStdAction::cut(this, SLOT, parent)). You + * may, however, do this using the enums provided. This author can't + * think of a reason why you would want to, but, hey, if you do, + * here's how: + * + * <pre> + * (void)KStdAction::action(KStdAction::New, this, SLOT(fileNew()), actionCollection()); + * (void)KStdAction::action(KStdAction::Cut, this, SLOT(editCut()), actionCollection()); + * </pre> + * + * @author Kurt Granroth <granroth@kde.org> + */ +namespace KStdAction +{ + /** + * The standard menubar and toolbar actions. + */ + enum StdAction { + ActionNone, + + // File Menu + New, Open, OpenRecent, Save, SaveAs, Revert, Close, + Print, PrintPreview, Mail, Quit, + + // Edit Menu + Undo, Redo, Cut, Copy, Paste, SelectAll, Deselect, Find, FindNext, FindPrev, + Replace, + + // View Menu + ActualSize, FitToPage, FitToWidth, FitToHeight, ZoomIn, ZoomOut, + Zoom, Redisplay, + + // Go Menu + Up, Back, Forward, Home, Prior, Next, Goto, GotoPage, GotoLine, + FirstPage, LastPage, + + // Bookmarks Menu + AddBookmark, EditBookmarks, + + // Tools Menu + Spelling, + + // Settings Menu + ShowMenubar, ShowToolbar, ShowStatusbar, SaveOptions, KeyBindings, + Preferences, ConfigureToolbars, + + // Help Menu + Help, HelpContents, WhatsThis, ReportBug, AboutApp, AboutKDE, + TipofDay, ///< @since 3.1 + + // Another settings menu item + ConfigureNotifications + }; + + /** + * Creates an action corresponding to the + * @ref KStdAction::StdAction enum. + */ + KAction* create( StdAction id, const char *name, + const QObject *recvr, const char *slot, + KActionCollection* parent ); + + inline KAction* create( StdAction id, + const QObject *recvr, const char *slot, + KActionCollection* parent ) + { return KStdAction::create( id, 0, recvr, slot, parent ); } + + /** + * @obsolete. Creates an action corresponding to the + * @ref KStdAction::StdAction enum. + */ + inline KAction *action(StdAction act_enum, + const QObject *recvr, const char *slot, + KActionCollection *parent, const char *name = 0L ) + { return KStdAction::create( act_enum, name, recvr, slot, parent ); } + + /** + * This will return the internal name of a given standard action. + */ + const char* name( StdAction id ); + + /// @obsolete. Use #name + inline const char* stdName(StdAction act_enum) { return name( act_enum ); } + + /** + * Returns a list of all standard names. Used by @ref KAccelManager + * to give those heigher weight. + * @since 3.1 + */ + QStringList stdNames(); + + /** + * Create a new document or window. + */ + KAction *openNew(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 ); + + /** + * Open an existing file. + */ + KAction *open(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 ); + + /** + * Open a recently used document. + * @param slot The SLOT to invoke when a URL is selected. + * Its signature is of the form slotURLSelected( const KURL & ). + */ + KRecentFilesAction *openRecent(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 ); + + /** + * Save the current document. + */ + KAction *save(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Save the current document under a different name. + */ + KAction *saveAs(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Revert the current document to the last saved version + * (essentially will undo all changes). + */ + KAction *revert(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Close the current document. + */ + KAction *close(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Print the current document. + */ + KAction *print(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Show a print preview of the current document. + */ + KAction *printPreview(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Mail this document. + */ + KAction *mail(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Quit the program. + */ + KAction *quit(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Undo the last operation. + */ + KAction *undo(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Redo the last operation. + */ + KAction *redo(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Cut selected area and store it in the clipboard. + */ + KAction *cut(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Copy the selected area into the clipboard. + */ + KAction *copy(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Paste the contents of clipboard at the current mouse or cursor + * position. + */ + KAction *paste(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Select all elements in the current document. + */ + KAction *selectAll(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Deselect any selected elements in the current document. + */ + KAction *deselect(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Initiate a 'find' request in the current document. + */ + KAction *find(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Find the next instance of a stored 'find'. + */ + KAction *findNext(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Find a previous instance of a stored 'find'. + */ + KAction *findPrev(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Find and replace matches. + */ + KAction *replace(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * View the document at its actual size. + */ + KAction *actualSize(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Fit the document view to the size of the current window. + */ + KAction *fitToPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Fit the document view to the width of the current window. + */ + KAction *fitToWidth(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Fit the document view to the height of the current window. + */ + KAction *fitToHeight(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Zoom in. + */ + KAction *zoomIn(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Zoom out. + */ + KAction *zoomOut(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Popup a zoom dialog. + */ + KAction *zoom(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Redisplay or redraw the document. + */ + KAction *redisplay(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Move up (web style menu). + */ + KAction *up(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Move back (web style menu). + */ + KAction *back(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Move forward (web style menu). + */ + KAction *forward(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Go to the "Home" position or document. + */ + KAction *home(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Scroll up one page. + */ + KAction *prior(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Scroll down one page. + */ + KAction *next(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Go to somewhere in general. + */ + KAction *goTo(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + + /** + * Go to a specific page (dialog). + */ + KAction *gotoPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Go to a specific line (dialog). + */ + KAction *gotoLine(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Jump to the first page. + */ + KAction *firstPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Jump to the last page. + */ + KAction *lastPage(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Add the current page to the bookmarks tree. + */ + KAction *addBookmark(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Edit the application bookmarks. + */ + KAction *editBookmarks(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Pop up the spell checker. + */ + KAction *spelling(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + + /** + * Show/Hide the menubar. + */ + KToggleAction *showMenubar(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * @obsolete. toolbar actions are created automatically now in the + * Settings menu. Don't use this anymore. + * See: @ref KMainWindow::createStandardStatusBarAction() + * Show/Hide the primary toolbar. + * @since 3.1 + */ + KToggleAction *showToolbar(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + /** + * @obsolete. toolbar actions are created automatically now in the + * Settings menu. Don't use this anymore. + * See: @ref KMainWindow::setStandardToolBarMenuEnabled(bool); + * Show/Hide the primary toolbar. + */ + KToggleToolBarAction *showToolbar(const char* toolBarName, + KActionCollection* parent, const char *name = 0 ); + + /** + * Show/Hide the statusbar. + */ + KToggleAction *showStatusbar(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the save options dialog. + */ + KAction *saveOptions(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the configure key bindings dialog. + */ + KAction *keyBindings(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the preferences/options dialog. + */ + KAction *preferences(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * The Customize Toolbar dialog. + */ + KAction *configureToolbars(const QObject *recvr, + const char *slot, + KActionCollection* parent, + const char *name = 0 ); + + /** + * The Configure Notifications dialo + * @since 3.1 + */ + KAction *configureNotifications(const QObject *recvr, + const char *slot, + KActionCollection *parent, + const char *name = 0); + + /** + * Display the help. + */ + KAction *help(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the help contents. + */ + KAction *helpContents(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Trigger the What's This cursor. + */ + KAction *whatsThis(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display "Tip of the Day" + * @since 3.1 + */ + KAction *tipOfDay(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Open up the Report Bug dialog. + */ + KAction *reportBug(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the application's About box. + */ + KAction *aboutApp(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); + + /** + * Display the About KDE dialog. + */ + KAction *aboutKDE(const QObject *recvr, const char *slot, + KActionCollection* parent, const char *name = 0 ); +} + +#endif // KSTDACTION_H diff --git a/microkde/kdeui/ktoolbar.cpp b/microkde/kdeui/ktoolbar.cpp new file mode 100644 index 0000000..92cb8d2 --- a/dev/null +++ b/microkde/kdeui/ktoolbar.cpp @@ -0,0 +1,2260 @@ +/* This file is part of the KDE libraries + Copyright + (C) 2000 Reginald Stadlbauer (reggie@kde.org) + (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 1999 Chris Schlaeger (cs@kde.org) + (C) 1999 Kurt Granroth (granroth@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifdef KDE_USE_FINAL +#undef Always +#include <qdockwindow.h> +#endif + + + +#include "ktoolbar.h" +#include "kmainwindow.h" + +#include <string.h> + +#include <qpainter.h> +#include <qtooltip.h> +#include <qdrawutil.h> +#include <qstring.h> +#include <qrect.h> +#include <qobjectlist.h> +#include <qtimer.h> +#include <qstyle.h> +#include <qapplication.h> + +//US #include <config.h> + +#include "klineedit.h" +#include "kseparator.h" +#include <klocale.h> +#include <kapplication.h> +#include <kaction.h> +#include <kstdaction.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kiconloader.h> +#include <kcombobox.h> +//US #include <kpopupmenu.h> +//US #include <kanimwidget.h> +//US #include <kipc.h> +//US #include <kwin.h> +#include <kdebug.h> +#include <qlayout.h> + +#include "ktoolbarbutton.h" + +//US +#include "kconfigbase.h" + +#include <qpopupmenu.h> +#include <qmainwindow.h> + +enum { + CONTEXT_TOP = 0, + CONTEXT_LEFT = 1, + CONTEXT_RIGHT = 2, + CONTEXT_BOTTOM = 3, + CONTEXT_FLOAT = 4, + CONTEXT_FLAT = 5, + CONTEXT_ICONS = 6, + CONTEXT_TEXT = 7, + CONTEXT_TEXTRIGHT = 8, + CONTEXT_TEXTUNDER = 9, + CONTEXT_ICONSIZES = 50 // starting point for the icon size list, put everything else before +}; + +class KToolBarPrivate +{ +public: + KToolBarPrivate() { + m_iconSize = 0; + m_iconText = KToolBar::IconOnly; + m_highlight = true; + m_transparent = true; + m_honorStyle = false; + + m_enableContext = true; + + m_xmlguiClient = 0; + m_configurePlugged = false; + +//US oldPos = Qt::DockUnmanaged; + oldPos = QMainWindow::Unmanaged; + + modified = m_isHorizontal = positioned = FALSE; + + HiddenDefault = false; + IconSizeDefault = 0; + IconTextDefault = "IconOnly"; + IndexDefault = -1; + NewLineDefault = false; + OffsetDefault = -1; + PositionDefault = "Top"; + idleButtons.setAutoDelete(true); + } + + int m_iconSize; + KToolBar::IconText m_iconText; + bool m_highlight : 1; + bool m_transparent : 1; + bool m_honorStyle : 1; + bool m_isHorizontal : 1; + bool m_enableContext : 1; + bool m_configurePlugged : 1; + bool modified : 1; + bool positioned : 1; + + QWidget *m_parent; + + QMainWindow::ToolBarDock oldPos; + + KXMLGUIClient *m_xmlguiClient; + + struct ToolBarInfo + { +//US ToolBarInfo() : index( 0 ), offset( -1 ), newline( FALSE ), dock( Qt::DockTop ) {} + ToolBarInfo() : index( 0 ), offset( -1 ), newline( FALSE ), dock( QMainWindow::Top ) {} +//US ToolBarInfo( Qt::Dock d, int i, bool n, int o ) : index( i ), offset( o ), newline( n ), dock( d ) {} + ToolBarInfo( QMainWindow::ToolBarDock d, int i, bool n, int o ) : index( i ), offset( o ), newline( n ), dock( d ) {} + int index, offset; + bool newline; +//US Qt::Dock dock; + QMainWindow::ToolBarDock dock; + }; + + ToolBarInfo toolBarInfo; + QValueList<int> iconSizes; + QTimer repaintTimer; + + // Default Values. + bool HiddenDefault; + int IconSizeDefault; + QString IconTextDefault; + int IndexDefault; + bool NewLineDefault; + int OffsetDefault; + QString PositionDefault; + + QPtrList<QWidget> idleButtons; +}; + +KToolBarSeparator::KToolBarSeparator(Orientation o , bool l, QToolBar *parent, + const char* name ) + :QFrame( parent, name ), line( l ) +{ + connect( parent, SIGNAL(orientationChanged(Orientation)), + this, SLOT(setOrientation(Orientation)) ); + setOrientation( o ); + setBackgroundMode( parent->backgroundMode() ); + setBackgroundOrigin( ParentOrigin ); +} + +void KToolBarSeparator::setOrientation( Orientation o ) +{ + orient = o; + if ( line ) { + if ( orientation() == Vertical ) + setFrameStyle( HLine + Sunken ); + else + setFrameStyle( VLine + Sunken ); + } else { + setFrameStyle( NoFrame ); + } +} + +void KToolBarSeparator::styleChange( QStyle& ) +{ + setOrientation( orient ); +} + +QSize KToolBarSeparator::sizeHint() const +{ + return orientation() == Vertical ? QSize( 0, 6 ) : QSize( 6, 0 ); +} + +QSizePolicy KToolBarSeparator::sizePolicy() const +{ + return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); +} + +KToolBar::KToolBar( QWidget *parent, const char *name, bool honorStyle, bool readConfig ) +#ifdef DESKTOP_VERSION + : QToolBar( QString::fromLatin1( name ), + parent && parent->inherits( "QMainWindow" ) ? static_cast<QMainWindow*>(parent) : 0, + parent, FALSE, + name ? name : "mainToolBar") +#else + : QPEToolBar( parent && parent->inherits( "QMainWindow" ) ? static_cast<QMainWindow*>(parent) : 0, + QString::fromLatin1( name )) + + +#endif +{ + init( readConfig, honorStyle ); +} + +KToolBar::KToolBar( QMainWindow *parentWindow, QMainWindow::ToolBarDock dock, bool newLine, const char *name, bool honorStyle, bool readConfig ) +#ifdef DESKTOP_VERSION + : QToolBar( QString::fromLatin1( name ), + parentWindow, dock, newLine, + name ? name : "mainToolBar") +#else + : QPEToolBar( parentWindow,QString::fromLatin1( name )) + + +#endif + +{ + init( readConfig, honorStyle ); +} + +KToolBar::KToolBar( QMainWindow *parentWindow, QWidget *dock, bool newLine, const char *name, bool honorStyle, bool readConfig ) +#ifdef DESKTOP_VERSION + : QToolBar( QString::fromLatin1( name ), + parentWindow, dock, newLine, + name ? name : "mainToolBar") +#else + : QPEToolBar( parentWindow,QString::fromLatin1( name )) + + +#endif + +{ + init( readConfig, honorStyle ); +} + +KToolBar::~KToolBar() +{ + inshutdownprocess = true; + emit toolbarDestroyed(); + delete d; +} + +void KToolBar::init( bool readConfig, bool honorStyle ) +{ + inshutdownprocess = false; + d = new KToolBarPrivate; + setFullSize( TRUE ); + d->m_honorStyle = honorStyle; + context = 0; + layoutTimer = new QTimer( this ); + connect( layoutTimer, SIGNAL( timeout() ), + this, SLOT( rebuildLayout() ) ); + connect( &(d->repaintTimer), SIGNAL( timeout() ), + this, SLOT( slotRepaint() ) ); +/*US + if ( kapp ) { // may be null when started inside designer + connect(kapp, SIGNAL(toolbarAppearanceChanged(int)), this, SLOT(slotAppearanceChanged())); + // request notification of changes in icon style + kapp->addKipcEventMask(KIPC::IconChanged); + connect(kapp, SIGNAL(iconChanged(int)), this, SLOT(slotIconChanged(int))); + } +*/ + // finally, read in our configurable settings + if ( readConfig ) + slotReadConfig(); + + if ( mainWindow() ) + connect( mainWindow(), SIGNAL( toolBarPositionChanged( QToolBar * ) ), + this, SLOT( toolBarPosChanged( QToolBar * ) ) ); + + // Hack to make sure we recalculate our size when we dock. +//US connect( this, SIGNAL(placeChanged(QDockWindow::Place)), SLOT(rebuildLayout()) ); +} + +int KToolBar::insertButton(const QString& icon, int id, bool enabled, + const QString& text, int index/*US, KInstance *_instance*/ ) +{ + KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text/*US, _instance*/ ); + + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QString& icon, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled, const QString& text, int index/*US, KInstance *_instance*/ ) +{ + KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text/*US, _instance*/); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + connect( button, signal, receiver, slot ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QPixmap& pixmap, int id, bool enabled, + const QString& text, int index ) +{ + KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + doConnections( button ); + return index; +} +#if 0 + bar->insertButton( icon, id_, SIGNAL( clicked() ), this, + SLOT( slotActivated() ), + d->isEnabled(), d->plainText(), index/*US, instance*/ ); +#endif + +int KToolBar::insertButton(const QPixmap& pixmap, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled, const QString& text, + int index ) +{ + KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + connect( button, signal, receiver, slot ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QString& icon, int id, QPopupMenu *popup, + bool enabled, const QString &text, int index ) +{ + KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text ); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + button->setPopup( popup ); + doConnections( button ); + return index; +} + + +int KToolBar::insertButton(const QPixmap& pixmap, int id, QPopupMenu *popup, + bool enabled, const QString &text, int index ) +{ + KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text ); + insertWidgetInternal( button, index, id ); + button->setEnabled( enabled ); + button->setPopup( popup ); + doConnections( button ); + return index; +} + + +int KToolBar::insertLined (const QString& text, int id, + const char *signal, + const QObject *receiver, const char *slot, + bool enabled , + const QString& toolTipText, + int size, int index ) +{ + KLineEdit *lined = new KLineEdit ( this, 0 ); + if ( !toolTipText.isEmpty() ) + QToolTip::add( lined, toolTipText ); + if ( size > 0 ) + lined->setMinimumWidth( size ); + insertWidgetInternal( lined, index, id ); + connect( lined, signal, receiver, slot ); + lined->setText(text); + lined->setEnabled( enabled ); + return index; +} + +int KToolBar::insertCombo (const QStringList &list, int id, bool writable, + const char *signal, const QObject *receiver, + const char *slot, bool enabled, + const QString& tooltiptext, + int size, int index, + QComboBox::Policy policy ) +{ +//US KComboBox *combo = new KComboBox ( writable, this ); + KComboBox *combo = new KComboBox ( this ); + combo->setEditable(writable); + + insertWidgetInternal( combo, index, id ); + combo->insertStringList (list); + combo->setInsertionPolicy(policy); + combo->setEnabled( enabled ); + if ( !tooltiptext.isEmpty() ) + QToolTip::add( combo, tooltiptext ); + if ( size > 0 ) + combo->setMinimumWidth( size ); + if (!tooltiptext.isNull()) + QToolTip::add( combo, tooltiptext ); + + if ( signal && receiver && slot ) + connect ( combo, signal, receiver, slot ); + return index; +} + + +int KToolBar::insertCombo (const QString& text, int id, bool writable, + const char *signal, QObject *receiver, + const char *slot, bool enabled, + const QString& tooltiptext, + int size, int index, + QComboBox::Policy policy ) +{ +//US KComboBox *combo = new KComboBox ( writable, this ); + KComboBox *combo = new KComboBox ( this ); + combo->setEditable(writable); + + insertWidgetInternal( combo, index, id ); + combo->insertItem (text); + combo->setInsertionPolicy(policy); + combo->setEnabled( enabled ); + if ( !tooltiptext.isEmpty() ) + QToolTip::add( combo, tooltiptext ); + if ( size > 0 ) + combo->setMinimumWidth( size ); + if (!tooltiptext.isNull()) + QToolTip::add( combo, tooltiptext ); + connect (combo, signal, receiver, slot); + return index; +} + +int KToolBar::insertSeparator(int index, int id) +{ + QWidget *w = new KToolBarSeparator( orientation(), FALSE, this, "tool bar separator" ); + insertWidgetInternal( w, index, id ); + return index; +} + +int KToolBar::insertLineSeparator(int index, int id) +{ + QWidget *w = new KToolBarSeparator( orientation(), TRUE, this, "tool bar separator" ); + insertWidgetInternal( w, index, id ); + return index; +} + + +int KToolBar::insertWidget(int id, int /*width*/, QWidget *widget, int index) +{ + // removeWidgetInternal( widget ); // in case we already have it ? + insertWidgetInternal( widget, index, id ); + return index; +} +/*US +int KToolBar::insertAnimatedWidget(int id, QObject *receiver, const char *slot, + const QString& icons, int index ) +{ + KAnimWidget *anim = new KAnimWidget( icons, d->m_iconSize, this ); + insertWidgetInternal( anim, index, id ); + + if ( receiver ) + connect( anim, SIGNAL(clicked()), receiver, slot); + + return index; +} + +KAnimWidget *KToolBar::animatedWidget( int id ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; + if ( (*it) && (*it)->inherits( "KAnimWidget" ) ) + return (KAnimWidget*)(*it); + QObjectList *l = queryList( "KAnimWidget" ); + if ( !l || !l->first() ) { + delete l; + return 0; + } + + for ( QObject *o = l->first(); o; o = l->next() ) { + if ( o->inherits( "KAnimWidget" ) ) + { + delete l; + return (KAnimWidget*)o; + } + } + + delete l; + return 0; +} +*/ + +void KToolBar::addConnection (int id, const char *signal, + const QObject *receiver, const char *slot) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; + if ( (*it) ) + connect( (*it), signal, receiver, slot ); +} + +void KToolBar::setItemEnabled( int id, bool enabled ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; + if ( (*it) ) + (*it)->setEnabled( enabled ); +} + + +void KToolBar::setButtonPixmap( int id, const QPixmap& _pixmap ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setPixmap( _pixmap ); +} + + +void KToolBar::setButtonIcon( int id, const QString& _icon ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setIcon( _icon ); +} + +void KToolBar::setButtonIconSet( int id, const QIconSet& iconset ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setIconSet( iconset ); +} + + +void KToolBar::setDelayedPopup (int id , QPopupMenu *_popup, bool toggle ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setDelayedPopup( _popup, toggle ); +} + + +void KToolBar::setAutoRepeat (int id, bool flag) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setAutoRepeat( flag ); +} + + +void KToolBar::setToggle (int id, bool flag ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->setToggle( flag ); +} + + +void KToolBar::toggleButton (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->toggle(); +} + + +void KToolBar::setButton (int id, bool flag) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if ( button ) + button->on( flag ); +} + + +bool KToolBar::isButtonOn (int id) const +{ + Id2WidgetMap::ConstIterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return false; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + return button ? button->isOn() : false; +} + + +void KToolBar::setLinedText (int id, const QString& text) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QLineEdit * lineEdit = dynamic_cast<QLineEdit *>( *it ); + QLineEdit * lineEdit = (QLineEdit *)( *it ); + if ( lineEdit ) + lineEdit->setText( text ); +} + + +QString KToolBar::getLinedText (int id) const +{ + Id2WidgetMap::ConstIterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return QString::null; +//US QLineEdit * lineEdit = dynamic_cast<QLineEdit *>( *it ); + QLineEdit * lineEdit = (QLineEdit *)( *it ); + return lineEdit ? lineEdit->text() : QString::null; +} + + +void KToolBar::insertComboItem (int id, const QString& text, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->insertItem( text, index ); +} + +void KToolBar::insertComboList (int id, const QStringList &list, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->insertStringList( list, index ); +} + + +void KToolBar::removeComboItem (int id, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->removeItem( index ); +} + + +void KToolBar::setCurrentComboItem (int id, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->setCurrentItem( index ); +} + + +void KToolBar::changeComboItem (int id, const QString& text, int index) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->changeItem( text, index ); +} + + +void KToolBar::clearCombo (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + if (comboBox) + comboBox->clear(); +} + + +QString KToolBar::getComboItem (int id, int index) const +{ + Id2WidgetMap::ConstIterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return QString::null; +//US QComboBox * comboBox = dynamic_cast<QComboBox *>( *it ); + QComboBox * comboBox = (QComboBox *)( *it ); + return comboBox ? comboBox->text( index ) : QString::null; +} + + +KComboBox * KToolBar::getCombo(int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; +//US return dynamic_cast<KComboBox *>( *it ); + return (KComboBox *)( *it ); +} + + +KLineEdit * KToolBar::getLined (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; +//US return dynamic_cast<KLineEdit *>( *it ); + return (KLineEdit *)( *it ); +} + + +KToolBarButton * KToolBar::getButton (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return 0; +//US return dynamic_cast<KToolBarButton *>( *it ); + return (KToolBarButton *)( *it ); +} + + +void KToolBar::alignItemRight (int id, bool right ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; + if ( rightAligned && !right && (*it) == rightAligned ) + rightAligned = 0; + if ( (*it) && right ) + rightAligned = (*it); +} + + +QWidget *KToolBar::getWidget (int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + return ( it == id2widget.end() ) ? 0 : (*it); +} + + +void KToolBar::setItemAutoSized (int id, bool yes ) +{ + QWidget *w = getWidget(id); + if ( w && yes ) + setStretchableWidget( w ); +} + + +void KToolBar::clear () +{ + QToolBar::clear(); + widget2id.clear(); + id2widget.clear(); +} + + +void KToolBar::removeItem(int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + { + kdDebug(220) << "KToolBar::removeItem item " << id << " not found" << endl; + return; + } + QWidget * w = (*it); + id2widget.remove( id ); + widget2id.remove( w ); + widgets.removeRef( w ); + delete w; +} + + +void KToolBar::removeItemDelayed(int id) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + { + kdDebug(220) << "KToolBar::removeItem item " << id << " not found" << endl; + return; + } + QWidget * w = (*it); + id2widget.remove( id ); + widget2id.remove( w ); + widgets.removeRef( w ); + + w->blockSignals(true); + d->idleButtons.append(w); + layoutTimer->start( 50, TRUE ); +} + + +void KToolBar::hideItem (int id) +{ + QWidget *w = getWidget(id); + if ( w ) + w->hide(); +} + + +void KToolBar::showItem (int id) +{ + QWidget *w = getWidget(id); + if ( w ) + w->show(); +} + + +int KToolBar::itemIndex (int id) +{ + QWidget *w = getWidget(id); + return w ? widgets.findRef(w) : -1; +} + + +void KToolBar::setFullSize(bool flag ) +{ + setHorizontalStretchable( flag ); + setVerticalStretchable( flag ); +} + + +bool KToolBar::fullSize() const +{ + return isHorizontalStretchable() || isVerticalStretchable(); +} + + +void KToolBar::enableMoving(bool flag ) +{ +//US setMovingEnabled(flag); + this->mainWindow()->setToolBarsMovable(flag); +} + + +void KToolBar::setBarPos (BarPosition bpos) +{ + if ( !mainWindow() ) + return; +//US mainWindow()->moveDockWindow( this, (Dock)bpos ); + mainWindow()->moveToolBar( this, (QMainWindow::ToolBarDock)bpos ); +} + + +KToolBar::BarPosition KToolBar::barPos() +{ + if ( !(QMainWindow*)mainWindow() ) + return KToolBar::Top; +//US Dock dock; + QMainWindow::ToolBarDock dock; + int dm1, dm2; + bool dm3; + ((QMainWindow*)mainWindow())->getLocation( (QToolBar*)this, dock, dm1, dm3, dm2 ); +//US if ( dock == DockUnmanaged ) { + if ( dock == QMainWindow::Unmanaged ) { + return (KToolBar::BarPosition)Top; + } + return (BarPosition)dock; +} + + +bool KToolBar::enable(BarStatus stat) +{ + bool mystat = isVisible(); + + if ( (stat == Toggle && mystat) || stat == Hide ) + hide(); + else + show(); + + return isVisible() == mystat; +} + + +void KToolBar::setMaxHeight ( int h ) +{ + setMaximumHeight( h ); +} + +int KToolBar::maxHeight() +{ + return maximumHeight(); +} + + +void KToolBar::setMaxWidth (int dw) +{ + setMaximumWidth( dw ); +} + + +int KToolBar::maxWidth() +{ + return maximumWidth(); +} + + +void KToolBar::setTitle (const QString& _title) +{ + setLabel( _title ); +} + + +void KToolBar::enableFloating (bool ) +{ +} + + +void KToolBar::setIconText(IconText it) +{ + setIconText( it, true ); +} + + +void KToolBar::setIconText(IconText icontext, bool update) +{ + bool doUpdate=false; + + if (icontext != d->m_iconText) { + d->m_iconText = icontext; + doUpdate=true; + } + + if (update == false) + return; + + if (doUpdate) + emit modechange(); // tell buttons what happened + + // ugly hack to force a QMainWindow::triggerLayout( TRUE ) + if ( mainWindow() ) { + QMainWindow *mw = mainWindow(); + mw->setUpdatesEnabled( FALSE ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setUpdatesEnabled( TRUE ); + } +} + + +KToolBar::IconText KToolBar::iconText() const +{ + return d->m_iconText; +} + + +void KToolBar::setIconSize(int size) +{ + setIconSize( size, true ); +} + +void KToolBar::setIconSize(int size, bool update) +{ + bool doUpdate=false; + + if ( size != d->m_iconSize ) { + d->m_iconSize = size; + doUpdate=true; + } + + if (update == false) + return; + + if (doUpdate) + emit modechange(); // tell buttons what happened + + // ugly hack to force a QMainWindow::triggerLayout( TRUE ) + if ( mainWindow() ) { + QMainWindow *mw = mainWindow(); + mw->setUpdatesEnabled( FALSE ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setToolBarsMovable( !mw->toolBarsMovable() ); + mw->setUpdatesEnabled( TRUE ); + } +} + + +int KToolBar::iconSize() const +{ +/*US + if ( !d->m_iconSize ) // default value? + { + if (!::qstrcmp(QObject::name(), "mainToolBar")) + return KGlobal::iconLoader()->currentSize(KIcon::MainToolbar); + else + return KGlobal::iconLoader()->currentSize(KIcon::Toolbar); + } + return d->m_iconSize; +*/ + int ret = 18; + if ( QApplication::desktop()->width() > 320 && QApplication::desktop()->width() < 650 ) + ret = 30; + return ret; +} + + +void KToolBar::setEnableContextMenu(bool enable ) +{ + d->m_enableContext = enable; +} + + +bool KToolBar::contextMenuEnabled() const +{ + return d->m_enableContext; +} + + +void KToolBar::setItemNoStyle(int id, bool no_style ) +{ + Id2WidgetMap::Iterator it = id2widget.find( id ); + if ( it == id2widget.end() ) + return; +//US KToolBarButton * button = dynamic_cast<KToolBarButton *>( *it ); + KToolBarButton * button = (KToolBarButton *)( *it ); + if (button) + button->setNoStyle( no_style ); +} + + +void KToolBar::setFlat (bool flag) +{ + if ( !mainWindow() ) + return; + if ( flag ) +//US mainWindow()->moveDockWindow( this, DockMinimized ); + mainWindow()->moveToolBar( this, QMainWindow::Minimized ); + else +//US mainWindow()->moveDockWindow( this, DockTop ); + mainWindow()->moveToolBar( this, QMainWindow::Top ); + // And remember to save the new look later +/*US + if ( mainWindow()->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>(mainWindow())->setSettingsDirty(); +*/ +} + + +int KToolBar::count() const +{ + return id2widget.count(); +} + + +void KToolBar::saveState() +{ +/*US + // first, try to save to the xml file + if ( d->m_xmlguiClient && !d->m_xmlguiClient->xmlFile().isEmpty() ) { + // go down one level to get to the right tags + QDomElement elem = d->m_xmlguiClient->domDocument().documentElement().toElement(); + elem = elem.firstChild().toElement(); + QString barname(!::qstrcmp(name(), "unnamed") ? "mainToolBar" : name()); + QDomElement current; + // now try to find our toolbar + d->modified = false; + for( ; !elem.isNull(); elem = elem.nextSibling().toElement() ) { + current = elem; + + if ( current.tagName().lower() != "toolbar" ) + continue; + + QString curname(current.attribute( "name" )); + + if ( curname == barname ) { + saveState( current ); + break; + } + } + // if we didn't make changes, then just return + if ( !d->modified ) + return; + + // now we load in the (non-merged) local file + QString local_xml(KXMLGUIFactory::readConfigFile(d->m_xmlguiClient->xmlFile(), true, d->m_xmlguiClient->instance())); + QDomDocument local; + local.setContent(local_xml); + + // make sure we don't append if this toolbar already exists locally + bool just_append = true; + elem = local.documentElement().toElement(); + KXMLGUIFactory::removeDOMComments( elem ); + elem = elem.firstChild().toElement(); + for( ; !elem.isNull(); elem = elem.nextSibling().toElement() ) { + if ( elem.tagName().lower() != "toolbar" ) + continue; + + QString curname(elem.attribute( "name" )); + + if ( curname == barname ) { + just_append = false; + local.documentElement().replaceChild( current, elem ); + break; + } + } + + if (just_append) + local.documentElement().appendChild( current ); + + KXMLGUIFactory::saveConfigFile(local, d->m_xmlguiClient->localXMLFile(), d->m_xmlguiClient->instance() ); + + return; + } +*/ + // if that didn't work, we save to the config file + KConfig *config = KGlobal::config(); + saveSettings(config, QString::null); + config->sync(); +} + +QString KToolBar::settingsGroup() +{ + QString configGroup; + if (!::qstrcmp(name(), "unnamed") || !::qstrcmp(name(), "mainToolBar")) + configGroup = "Toolbar style"; + else + configGroup = QString(name()) + " Toolbar style"; + if ( this->mainWindow() ) + { + configGroup.prepend(" "); + configGroup.prepend( this->mainWindow()->name() ); + } + return configGroup; +} + +void KToolBar::saveSettings(KConfig *config, const QString &_configGroup) +{ + QString configGroup = _configGroup; + if (configGroup.isEmpty()) + configGroup = settingsGroup(); + //kdDebug(220) << "KToolBar::saveSettings group=" << _configGroup << " -> " << configGroup << endl; + + QString position, icontext; + int index; + getAttributes( position, icontext, index ); + + //kdDebug(220) << "KToolBar::saveSettings " << name() << " newLine=" << newLine << endl; + + KConfigGroupSaver saver(config, configGroup); + + if ( position != d->PositionDefault ) + config->writeEntry("Position", position); + else + config->deleteEntry("Position"); + + if ( icontext != d->IconTextDefault ) + config->writeEntry("IconText", icontext); + else + config->deleteEntry("IconText"); + + if ( iconSize() != d->IconSizeDefault ) + config->writeEntry("IconSize", iconSize()); + else + config->deleteEntry("IconSize"); + + if ( isHidden() != d->HiddenDefault ) + config->writeEntry("Hidden", isHidden()); + else + config->deleteEntry("Hidden"); + + if ( index != d->IndexDefault ) + config->writeEntry( "Index", index ); + else + config->deleteEntry("Index"); +//US the older version of KDE (used on the Zaurus) has no Offset property +/* if ( offset() != d->OffsetDefault ) + config->writeEntry( "Offset", offset() ); + else +*/ + config->deleteEntry("Offset"); + +//US the older version of KDE (used on the Zaurus) has no NewLine property +/* + if ( newLine() != d->NewLineDefault ) + config->writeEntry( "NewLine", newLine() ); + else +*/ + config->deleteEntry("NewLine"); +} + +void KToolBar::setXMLGUIClient( KXMLGUIClient *client ) +{ + d->m_xmlguiClient = client; +} + +void KToolBar::setText( const QString & txt ) +{ +//US setLabel( txt + " ( " + kapp->caption() + " ) " ); + setLabel( txt + " ( " + KGlobal::getAppName() + " ) " ); +} + + +QString KToolBar::text() const +{ + return label(); +} + + +void KToolBar::doConnections( KToolBarButton *button ) +{ + connect(button, SIGNAL(clicked(int)), this, SIGNAL( clicked( int ) ) ); + connect(button, SIGNAL(doubleClicked(int)), this, SIGNAL( doubleClicked( int ) ) ); + connect(button, SIGNAL(released(int)), this, SIGNAL( released( int ) ) ); + connect(button, SIGNAL(pressed(int)), this, SIGNAL( pressed( int ) ) ); + connect(button, SIGNAL(toggled(int)), this, SIGNAL( toggled( int ) ) ); + connect(button, SIGNAL(highlighted(int, bool)), this, SIGNAL( highlighted( int, bool ) ) ); +} + +void KToolBar::mousePressEvent ( QMouseEvent *m ) +{ + if ( !mainWindow() ) + return; + QMainWindow *mw = mainWindow(); + if ( mw->toolBarsMovable() && d->m_enableContext ) { + if ( m->button() == RightButton ) { + int i = contextMenu()->exec( m->globalPos(), 0 ); + switch ( i ) { + case -1: + return; // popup cancelled + case CONTEXT_LEFT: +//US mw->moveDockWindow( this, DockLeft ); + mw->moveToolBar( this, QMainWindow::Left ); + break; + case CONTEXT_RIGHT: +//US mw->moveDockWindow( this, DockRight ); + mw->moveToolBar( this, QMainWindow::Right ); + break; + case CONTEXT_TOP: +//US mw->moveDockWindow( this, DockTop ); + mw->moveToolBar( this, QMainWindow::Top ); + break; + case CONTEXT_BOTTOM: +//US mw->moveDockWindow( this, DockBottom ); + mw->moveToolBar( this, QMainWindow::Bottom ); + break; + case CONTEXT_FLOAT: + break; + case CONTEXT_FLAT: +//US mw->moveDockWindow( this, DockMinimized ); + mw->moveToolBar( this, QMainWindow::Minimized ); + break; + case CONTEXT_ICONS: + setIconText( IconOnly ); + break; + case CONTEXT_TEXTRIGHT: + setIconText( IconTextRight ); + break; + case CONTEXT_TEXT: + setIconText( TextOnly ); + break; + case CONTEXT_TEXTUNDER: + setIconText( IconTextBottom ); + break; + default: + if ( i >= CONTEXT_ICONSIZES ) + setIconSize( i - CONTEXT_ICONSIZES ); + else + return; // assume this was an action handled elsewhere, no need for setSettingsDirty() + } +/*US + if ( mw->inherits("KMainWindow") ) + static_cast<KMainWindow *>(mw)->setSettingsDirty(); +*/ + } + } +} + + +void KToolBar::rebuildLayout() +{ + + for(QWidget *w=d->idleButtons.first(); w; w=d->idleButtons.next()) + w->blockSignals(false); + d->idleButtons.clear(); + + layoutTimer->stop(); + QApplication::sendPostedEvents( this, QEvent::ChildInserted ); + QBoxLayout *l = boxLayout(); + l->setMargin( 1 ); + // clear the old layout + QLayoutIterator it = l->iterator(); + + while ( it.current() ) { + it.deleteCurrent(); + } + for ( QWidget *w = widgets.first(); w; w = widgets.next() ) { + if ( w == rightAligned ) { + continue; + } + if ( w->inherits( "KToolBarSeparator" ) && + !( (KToolBarSeparator*)w )->showLine() ) { + l->addSpacing( 6 ); + w->hide(); + continue; + } + if ( w->inherits( "QPopupMenu" ) ) + continue; + l->addWidget( w ); + w->show(); + } + if ( rightAligned ) { + l->addStretch(); + l->addWidget( rightAligned ); + rightAligned->show(); + } + + if ( fullSize() ) { + // This code sucks. It makes the last combo in a toolbar VERY big (e.g. zoom combo in kword). + //if ( !stretchableWidget && widgets.last() && + // !widgets.last()->inherits( "QButton" ) && !widgets.last()->inherits( "KAnimWidget" ) ) + // setStretchableWidget( widgets.last() ); + if ( !rightAligned ) + l->addStretch(); + if ( stretchableWidget ) + l->setStretchFactor( stretchableWidget, 10 ); + } + l->invalidate(); + QApplication::postEvent( this, new QEvent( QEvent::LayoutHint ) ); + //#endif //DESKTOP_VERSION +} + +void KToolBar::childEvent( QChildEvent *e ) +{ + + if ( e->child()->isWidgetType() ) { + QWidget * w = (QWidget*)e->child(); + if ( e->type() == QEvent::ChildInserted ) { + if ( !e->child()->inherits( "QPopupMenu" ) && + ::qstrcmp( "qt_dockwidget_internal", e->child()->name() ) != 0 ) { + + // prevent items that have been explicitly inserted by insert*() from + // being inserted again + if ( !widget2id.contains( w ) ) + { + int dummy = -1; + insertWidgetInternal( w, dummy, -1 ); + } + } + } else { + removeWidgetInternal( w ); + } + if ( isVisibleTo( 0 ) ) + { + QBoxLayout *l = boxLayout(); + // QLayout *l = layout(); + + // clear the old layout so that we don't get unnecassery layout + // changes till we have rebuild the thing + QLayoutIterator it = l->iterator(); + while ( it.current() ) { + it.deleteCurrent(); + } + layoutTimer->start( 50, TRUE ); + } + } + QToolBar::childEvent( e ); +} + +void KToolBar::insertWidgetInternal( QWidget *w, int &index, int id ) +{ + // we can't have it in widgets, or something is really wrong + //widgets.removeRef( w ); + + connect( w, SIGNAL( destroyed() ), + this, SLOT( widgetDestroyed() ) ); + if ( index == -1 || index > (int)widgets.count() ) { + widgets.append( w ); + index = (int)widgets.count(); + } + else + widgets.insert( index, w ); + if ( id == -1 ) + id = id2widget.count(); + id2widget.insert( id, w ); + widget2id.insert( w, id ); +} + +void KToolBar::showEvent( QShowEvent *e ) +{ + QToolBar::showEvent( e ); + rebuildLayout(); +} + +void KToolBar::setStretchableWidget( QWidget *w ) +{ + QToolBar::setStretchableWidget( w ); + stretchableWidget = w; +} + +QSizePolicy KToolBar::sizePolicy() const +{ + if ( orientation() == Horizontal ) + return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + else + return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding ); +} + +QSize KToolBar::sizeHint() const +{ + return QToolBar::sizeHint(); +#if 0 + QWidget::polish(); + static int iii = 0; + ++iii; + qDebug("++++++++ KToolBar::sizeHint() %d ", iii ); + int margin = static_cast<QWidget*>(ncThis)->layout()->margin(); + switch( barPos() ) + { + case KToolBar::Top: + case KToolBar::Bottom: + for ( QWidget *w = widgets.first(); w; w =widgets.next() ) + { + if ( w->inherits( "KToolBarSeparator" ) && + !( static_cast<KToolBarSeparator*>(w)->showLine() ) ) + { + minSize += QSize(6, 0); + } + else + { + QSize sh = w->sizeHint(); + if (!sh.isValid()) + sh = w->minimumSize(); + minSize = minSize.expandedTo(QSize(0, sh.height())); + minSize += QSize(sh.width()+1, 0); + } + } +/*US + minSize += QSize(QApplication::style().pixelMetric( QStyle::PM_DockWindowHandleExtent ), 0); +*/ + minSize += QSize(margin*2, margin*2); + break; + + case KToolBar::Left: + case KToolBar::Right: + for ( QWidget *w = widgets.first(); w; w = widgets.next() ) + { + if ( w->inherits( "KToolBarSeparator" ) && + !( static_cast<KToolBarSeparator*>(w)->showLine() ) ) + { + minSize += QSize(0, 6); + } + else + { + QSize sh = w->sizeHint(); + if (!sh.isValid()) + sh = w->minimumSize(); + minSize = minSize.expandedTo(QSize(sh.width(), 0)); + minSize += QSize(0, sh.height()+1); + } + } +/*US + minSize += QSize(0, QApplication::style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); +*/ + minSize += QSize(margin*2, margin*2); + break; + + default: + minSize = QToolBar::sizeHint(); + break; + } + return minSize; +#endif +} + +QSize KToolBar::minimumSize() const +{ + return minimumSizeHint(); +} + +QSize KToolBar::minimumSizeHint() const +{ + return sizeHint(); +} + +bool KToolBar::highlight() const +{ + return d->m_highlight; +} + +void KToolBar::hide() +{ + QToolBar::hide(); +} + +void KToolBar::show() +{ + QToolBar::show(); +} + +void KToolBar::resizeEvent( QResizeEvent *e ) +{ + bool b = isUpdatesEnabled(); + setUpdatesEnabled( FALSE ); + QToolBar::resizeEvent( e ); + if (b) + d->repaintTimer.start( 100, true ); +} + +void KToolBar::slotIconChanged(int group) +{ + if ((group != KIcon::Toolbar) && (group != KIcon::MainToolbar)) + return; + if ((group == KIcon::MainToolbar) != !::qstrcmp(name(), "mainToolBar")) + return; + + emit modechange(); + if (isVisible()) + updateGeometry(); +} + +void KToolBar::slotReadConfig() +{ + //kdDebug(220) << "KToolBar::slotReadConfig" << endl; + // Read appearance settings (hmm, we used to do both here, + // but a well behaved application will call applyMainWindowSettings + // anyway, right ?) + applyAppearanceSettings(KGlobal::config(), QString::null ); +} + +void KToolBar::slotAppearanceChanged() +{ + // Read appearance settings from global file. + applyAppearanceSettings(KGlobal::config(), QString::null, true /* lose local settings */ ); + // And remember to save the new look later +/*US + if ( mainWindow() && mainWindow()->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>(mainWindow())->setSettingsDirty(); +*/ +} + +//static +bool KToolBar::highlightSetting() +{ + QString grpToolbar(QString::fromLatin1("Toolbar style")); + KConfigGroupSaver saver(KGlobal::config(), grpToolbar); + return KGlobal::config()->readBoolEntry(QString::fromLatin1("Highlighting"),true); +} + +//static +bool KToolBar::transparentSetting() +{ + QString grpToolbar(QString::fromLatin1("Toolbar style")); + KConfigGroupSaver saver(KGlobal::config(), grpToolbar); + return KGlobal::config()->readBoolEntry(QString::fromLatin1("TransparentMoving"),true); +} + +//static +KToolBar::IconText KToolBar::iconTextSetting() +{ + QString grpToolbar(QString::fromLatin1("Toolbar style")); + KConfigGroupSaver saver(KGlobal::config(), grpToolbar); + QString icontext = KGlobal::config()->readEntry(QString::fromLatin1("IconText"),QString::fromLatin1("IconOnly")); + if ( icontext == "IconTextRight" ) + return IconTextRight; + else if ( icontext == "IconTextBottom" ) + return IconTextBottom; + else if ( icontext == "TextOnly" ) + return TextOnly; + else + return IconOnly; +} + +void KToolBar::applyAppearanceSettings(KConfig *config, const QString &_configGroup, bool forceGlobal) +{ + QString configGroup = _configGroup.isEmpty() ? settingsGroup() : _configGroup; + //kdDebug(220) << "KToolBar::applyAppearanceSettings: configGroup=" << configGroup << endl; + // We have application-specific settings in the XML file, + // and nothing in the application's config file + // -> don't apply the global defaults, the XML ones are preferred + // See applySettings for a full explanation +/*US :we do not support xml files + if ( d->m_xmlguiClient && !d->m_xmlguiClient->xmlFile().isEmpty() && + !config->hasGroup(configGroup) ) + { + //kdDebug(220) << "skipping global defaults, using XML ones instead" << endl; + return; + } +*/ + if ( !config->hasGroup(configGroup) ) + { + //kdDebug(220) << "skipping global defaults, using XML ones instead" << endl; + return; + } + + + KConfig *gconfig = KGlobal::config(); +/*US + static const QString &attrIconText = KGlobal::staticQString("IconText"); + static const QString &attrHighlight = KGlobal::staticQString("Highlighting"); + static const QString &attrTrans = KGlobal::staticQString("TransparentMoving"); + static const QString &attrSize = KGlobal::staticQString("IconSize"); +*/ + // we actually do this in two steps. + // First, we read in the global styles [Toolbar style] (from the KControl module). + // Then, if the toolbar is NOT 'mainToolBar', we will also try to read in [barname Toolbar style] + bool highlight; + int transparent; + QString icontext; + int iconsize = 0; + + // this is the first iteration + QString grpToolbar(QString::fromLatin1("Toolbar style")); + { // start block for KConfigGroupSaver + KConfigGroupSaver saver(gconfig, grpToolbar); + + // first, get the generic settings +//US highlight = gconfig->readBoolEntry(attrHighlight, true); + highlight = gconfig->readBoolEntry("Highlighting", true); +//US transparent = gconfig->readBoolEntry(attrTrans, true); + transparent = gconfig->readBoolEntry("TransparentMoving", true); + + // we read in the IconText property *only* if we intend on actually + // honoring it + if (d->m_honorStyle) +//US d->IconTextDefault = gconfig->readEntry(attrIconText, d->IconTextDefault); + d->IconTextDefault = gconfig->readEntry("IconText", d->IconTextDefault); + else + d->IconTextDefault = "IconOnly"; + + // Use the default icon size for toolbar icons. +//US d->IconSizeDefault = gconfig->readNumEntry(attrSize, d->IconSizeDefault); + d->IconSizeDefault = gconfig->readNumEntry("IconSize", d->IconSizeDefault); + + if ( !forceGlobal && config->hasGroup(configGroup) ) + { + config->setGroup(configGroup); + + // first, get the generic settings +//US highlight = config->readBoolEntry(attrHighlight, highlight); + highlight = config->readBoolEntry("Highlighting", highlight); +//US transparent = config->readBoolEntry(attrTrans, transparent); + transparent = config->readBoolEntry("TransparentMoving", transparent); + // now we always read in the IconText property +//US icontext = config->readEntry(attrIconText, d->IconTextDefault); + icontext = config->readEntry("IconText", d->IconTextDefault); + + // now get the size +//US iconsize = config->readNumEntry(attrSize, d->IconSizeDefault); + iconsize = config->readNumEntry("IconSize", d->IconSizeDefault); + } + else + { + iconsize = d->IconSizeDefault; + icontext = d->IconTextDefault; + } + + // revert back to the old group + } // end block for KConfigGroupSaver + + bool doUpdate = false; + + IconText icon_text; + if ( icontext == "IconTextRight" ) + icon_text = IconTextRight; + else if ( icontext == "IconTextBottom" ) + icon_text = IconTextBottom; + else if ( icontext == "TextOnly" ) + icon_text = TextOnly; + else + icon_text = IconOnly; + + // check if the icon/text has changed + if (icon_text != d->m_iconText) { + //kdDebug(220) << "KToolBar::applyAppearanceSettings setIconText " << icon_text << endl; + setIconText(icon_text, false); + doUpdate = true; + } + + // ...and check if the icon size has changed + if (iconsize != d->m_iconSize) { + setIconSize(iconsize, false); + doUpdate = true; + } + + QMainWindow *mw = mainWindow(); + + // ...and if we should highlight + if ( highlight != d->m_highlight ) { + d->m_highlight = highlight; + doUpdate = true; + } + + // ...and if we should move transparently + if ( mw && transparent != (!mw->opaqueMoving()) ) { + mw->setOpaqueMoving( !transparent ); + } + + if (doUpdate) + emit modechange(); // tell buttons what happened + if (isVisible ()) + updateGeometry(); +} + +void KToolBar::applySettings(KConfig *config, const QString &_configGroup) +{ + //kdDebug(220) << "KToolBar::applySettings group=" << _configGroup << endl; + + QString configGroup = _configGroup.isEmpty() ? settingsGroup() : _configGroup; + + /* + Let's explain this a bit more in details. + The order in which we apply settings is : + Global config / <appnamerc> user settings if no XMLGUI is used + Global config / App-XML attributes / <appnamerc> user settings if XMLGUI is used + + So in the first case, we simply read everything from KConfig as below, + but in the second case we don't do anything here if there is no app-specific config, + and the XMLGUI uses the static methods of this class to get the global defaults. + + Global config doesn't include position (index, offset, newline and hidden/shown). + */ + + // First the appearance stuff - the one which has a global config + applyAppearanceSettings( config, _configGroup ); + + // ...and now the position stuff + if ( config->hasGroup(configGroup) ) + { + KConfigGroupSaver cgs(config, configGroup); +/*US + static const QString &attrPosition = KGlobal::staticQString("Position"); + static const QString &attrIndex = KGlobal::staticQString("Index"); + static const QString &attrOffset = KGlobal::staticQString("Offset"); + static const QString &attrNewLine = KGlobal::staticQString("NewLine"); + static const QString &attrHidden = KGlobal::staticQString("Hidden"); + + QString position = config->readEntry(attrPosition, d->PositionDefault); + int index = config->readNumEntry(attrIndex, d->IndexDefault); + int offset = config->readNumEntry(attrOffset, d->OffsetDefault); + bool newLine = config->readBoolEntry(attrNewLine, d->NewLineDefault); + bool hidden = config->readBoolEntry(attrHidden, d->HiddenDefault); +*/ + + QString position = config->readEntry("Position", d->PositionDefault); + int index = config->readNumEntry("Index", d->IndexDefault); + int offset = config->readNumEntry("Offset", d->OffsetDefault); + bool newLine = config->readBoolEntry("NewLine", d->NewLineDefault); + bool hidden = config->readBoolEntry("Hidden", d->HiddenDefault); + +/*US Dock pos(DockTop); + if ( position == "Top" ) + pos = DockTop; + else if ( position == "Bottom" ) + pos = DockBottom; + else if ( position == "Left" ) + pos = DockLeft; + else if ( position == "Right" ) + pos = DockRight; + else if ( position == "Floating" ) + pos = DockTornOff; + else if ( position == "Flat" ) + pos = DockMinimized; +*/ + QMainWindow::ToolBarDock pos(QMainWindow::Top); + if ( position == "Top" ) + pos = QMainWindow::Top; + else if ( position == "Bottom" ) + pos = QMainWindow::Bottom; + else if ( position == "Left" ) + pos = QMainWindow::Left; + else if ( position == "Right" ) + pos = QMainWindow::Right; + else if ( position == "Floating" ) + pos = QMainWindow::TornOff; + else if ( position == "Flat" ) + pos = QMainWindow::Minimized; + + //kdDebug(220) << "KToolBar::applySettings hidden=" << hidden << endl; + if (hidden) + hide(); + else + show(); + + if ( mainWindow() ) + { + QMainWindow *mw = mainWindow(); + + //kdDebug(220) << "KToolBar::applySettings updating ToolbarInfo" << endl; + d->toolBarInfo = KToolBarPrivate::ToolBarInfo( pos, index, newLine, offset ); + + // moveDockWindow calls QDockArea which does a reparent() on us with + // showIt = true, so we loose our visibility status + bool doHide = isHidden(); + +//US mw->moveDockWindow( this, pos, newLine, index, offset ); + mw->moveToolBar( this, pos, newLine, index, offset ); + + //kdDebug(220) << "KToolBar::applySettings " << name() << " moveDockWindow with pos=" << pos << " newLine=" << newLine << " idx=" << index << " offs=" << offset << endl; + if ( doHide ) + hide(); + } + if (isVisible ()) + updateGeometry(); + } +} + +bool KToolBar::event( QEvent *e ) +{ + if ( (e->type() == QEvent::LayoutHint) && isUpdatesEnabled() ) + d->repaintTimer.start( 100, true ); + + if (e->type() == QEvent::ChildInserted ) + { + // By pass QToolBar::event, + // it will show() the inserted child and we don't want to + // do that until we have rebuild the layout. + childEvent((QChildEvent *)e); + return true; + } + + return QToolBar::event( e ); +} + +void KToolBar::slotRepaint() +{ + setUpdatesEnabled( FALSE ); + // Send a resizeEvent to update the "toolbar extension arrow" + // (The button you get when your toolbar-items don't fit in + // the available space) + QResizeEvent ev(size(), size()); + resizeEvent(&ev); + //#ifdef DESKTOP_VERSION + QApplication::sendPostedEvents( this, QEvent::LayoutHint ); + //#endif //DESKTOP_VERSION + setUpdatesEnabled( TRUE ); + repaint( TRUE ); +} + +void KToolBar::toolBarPosChanged( QToolBar *tb ) +{ + if ( tb != this ) + return; +//US if ( d->oldPos == DockMinimized ) + if ( d->oldPos == QMainWindow::Minimized ) + rebuildLayout(); + d->oldPos = (QMainWindow::ToolBarDock)barPos(); +/*US + if ( mainWindow() && mainWindow()->inherits( "KMainWindow" ) ) + static_cast<KMainWindow *>(mainWindow())->setSettingsDirty(); +*/ +} + +/*US +void KToolBar::loadState( const QDomElement &element ) +{ + //kdDebug(220) << "KToolBar::loadState " << this << endl; + if ( !mainWindow() ) + return; + + { + QCString text = element.namedItem( "text" ).toElement().text().utf8(); + if ( text.isEmpty() ) + text = element.namedItem( "Text" ).toElement().text().utf8(); + if ( !text.isEmpty() ) + setText( i18n( text ) ); + } + + { + QCString attrFullWidth = element.attribute( "fullWidth" ).lower().latin1(); + if ( !attrFullWidth.isEmpty() ) + setFullSize( attrFullWidth == "true" ); + } + + Dock dock = DockTop; + { + QCString attrPosition = element.attribute( "position" ).lower().latin1(); + //kdDebug(220) << "KToolBar::loadState attrPosition=" << attrPosition << endl; + if ( !attrPosition.isEmpty() ) { + if ( attrPosition == "top" ) + dock = DockTop; + else if ( attrPosition == "left" ) + dock = DockLeft; + else if ( attrPosition == "right" ) + dock = DockRight; + else if ( attrPosition == "bottom" ) + dock = DockBottom; + else if ( attrPosition == "floating" ) + dock = DockTornOff; + else if ( attrPosition == "flat" ) + dock = DockMinimized; + } + } + + { + QCString attrIconText = element.attribute( "iconText" ).lower().latin1(); + if ( !attrIconText.isEmpty() ) { + //kdDebug(220) << "KToolBar::loadState attrIconText=" << attrIconText << endl; + if ( attrIconText == "icontextright" ) + setIconText( KToolBar::IconTextRight ); + else if ( attrIconText == "textonly" ) + setIconText( KToolBar::TextOnly ); + else if ( attrIconText == "icontextbottom" ) + setIconText( KToolBar::IconTextBottom ); + else if ( attrIconText == "icononly" ) + setIconText( KToolBar::IconOnly ); + } else + // Use global setting + setIconText( iconTextSetting() ); + } + + { + QString attrIconSize = element.attribute( "iconSize" ).lower(); + if ( !attrIconSize.isEmpty() ) + d->IconSizeDefault = attrIconSize.toInt(); + setIconSize( d->IconSizeDefault ); + } + + { + QString attrIndex = element.attribute( "index" ).lower(); + if ( !attrIndex.isEmpty() ) + d->IndexDefault = attrIndex.toInt(); + } + + { + QString attrOffset = element.attribute( "offset" ).lower(); + if ( !attrOffset.isEmpty() ) + d->OffsetDefault = attrOffset.toInt(); + } + + { + QString attrNewLine = element.attribute( "newline" ).lower(); + if ( !attrNewLine.isEmpty() ) + d->NewLineDefault = attrNewLine == "true"; + } + + { + QString attrHidden = element.attribute( "hidden" ).lower(); + if ( !attrHidden.isEmpty() ) + d->HiddenDefault = attrHidden == "true"; + } + + d->toolBarInfo = KToolBarPrivate::ToolBarInfo( dock, d->IndexDefault, d->NewLineDefault, d->OffsetDefault ); + mainWindow()->addDockWindow( this, dock, d->NewLineDefault ); +//US mainWindow()->moveDockWindow( this, dock, d->NewLineDefault, d->IndexDefault, d->OffsetDefault ); + mainWindow()->moveToolBar( this, dock, d->NewLineDefault, d->IndexDefault, d->OffsetDefault ); + + // Apply the highlight button setting + d->m_highlight = highlightSetting(); + + // Apply transparent-toolbar-moving setting (ok, this is global to the mainwindow, + // but we do it only if there are toolbars...) + if ( transparentSetting() != !mainWindow()->opaqueMoving() ) + mainWindow()->setOpaqueMoving( !transparentSetting() ); + + if ( d->HiddenDefault ) + hide(); + else + show(); + + getAttributes( d->PositionDefault, d->IconTextDefault, d->IndexDefault ); +} +*/ + +void KToolBar::getAttributes( QString &position, QString &icontext, int &index ) +{ + // get all of the stuff to save + switch ( barPos() ) { + case KToolBar::Flat: + position = "Flat"; + break; + case KToolBar::Bottom: + position = "Bottom"; + break; + case KToolBar::Left: + position = "Left"; + break; + case KToolBar::Right: + position = "Right"; + break; + case KToolBar::Floating: + position = "Floating"; + break; + case KToolBar::Top: + default: + position = "Top"; + break; + } + + if ( mainWindow() ) { + QMainWindow::ToolBarDock dock; + bool newLine; + int offset; + mainWindow()->getLocation( this, dock, index, newLine, offset ); + } + + switch (d->m_iconText) { + case KToolBar::IconTextRight: + icontext = "IconTextRight"; + break; + case KToolBar::IconTextBottom: + icontext = "IconTextBottom"; + break; + case KToolBar::TextOnly: + icontext = "TextOnly"; + break; + case KToolBar::IconOnly: + default: + icontext = "IconOnly"; + break; + } +} +/*US +void KToolBar::saveState( QDomElement ¤t ) +{ + QString position, icontext; + int index = -1; + getAttributes( position, icontext, index ); + + current.setAttribute( "noMerge", "1" ); + current.setAttribute( "position", position ); + current.setAttribute( "iconText", icontext ); + current.setAttribute( "index", index ); + current.setAttribute( "offset", offset() ); + current.setAttribute( "newline", newLine() ); + if ( isHidden() ) + current.setAttribute( "hidden", "true" ); + d->modified = true; +} +*/ + +void KToolBar::positionYourself( bool force ) +{ + if (force) + d->positioned = false; + + if ( d->positioned || !mainWindow() ) + { + //kdDebug(220) << "KToolBar::positionYourself d->positioned=true ALREADY DONE" << endl; + return; + } + // we can't test for ForceHide after moveDockWindow because QDockArea + // does a reparent() with showIt == true + bool doHide = isHidden(); + //kdDebug(220) << "positionYourself " << name() << " dock=" << d->toolBarInfo.dock << " newLine=" << d->toolBarInfo.newline << " offset=" << d->toolBarInfo.offset << endl; +/*US mainWindow()->moveDockWindow( this, d->toolBarInfo.dock, + d->toolBarInfo.newline, + d->toolBarInfo.index, + d->toolBarInfo.offset ); +*/ + mainWindow()->moveToolBar( this, d->toolBarInfo.dock, d->NewLineDefault, d->IndexDefault, d->OffsetDefault ); + + if ( doHide ) + hide(); + // This method can only have an effect once - unless force is set + d->positioned = TRUE; +} + +//US KPopupMenu *KToolBar::contextMenu() +QPopupMenu *KToolBar::contextMenu() +{ + if ( context ) + return context; + + // Construct our context popup menu. Name it qt_dockwidget_internal so it + // won't be deleted by QToolBar::clear(). +//US context = new KPopupMenu( this, "qt_dockwidget_internal" ); + context = new QPopupMenu( this, "qt_dockwidget_internal" ); +//US context->insertTitle(i18n("Toolbar Menu")); + +//US KPopupMenu *orient = new KPopupMenu( context, "orient" ); + QPopupMenu *orient = new QPopupMenu( context, "orient" ); + orient->insertItem( i18n("toolbar position string","Top"), CONTEXT_TOP ); + orient->insertItem( i18n("toolbar position string","Left"), CONTEXT_LEFT ); + orient->insertItem( i18n("toolbar position string","Right"), CONTEXT_RIGHT ); + orient->insertItem( i18n("toolbar position string","Bottom"), CONTEXT_BOTTOM ); + orient->insertSeparator(-1); + //orient->insertItem( i18n("toolbar position string","Floating"), CONTEXT_FLOAT ); + orient->insertItem( i18n("min toolbar", "Flat"), CONTEXT_FLAT ); + +//US KPopupMenu *mode = new KPopupMenu( context, "mode" ); + QPopupMenu *mode = new QPopupMenu( context, "mode" ); + mode->insertItem( i18n("Icons Only"), CONTEXT_ICONS ); + mode->insertItem( i18n("Text Only"), CONTEXT_TEXT ); + mode->insertItem( i18n("Text Alongside Icons"), CONTEXT_TEXTRIGHT ); + mode->insertItem( i18n("Text Under Icons"), CONTEXT_TEXTUNDER ); + +//US KPopupMenu *size = new KPopupMenu( context, "size" ); + QPopupMenu *size = new QPopupMenu( context, "size" ); + size->insertItem( i18n("Default"), CONTEXT_ICONSIZES ); + // Query the current theme for available sizes + QValueList<int> avSizes; +/*US + KIconTheme *theme = KGlobal::instance()->iconLoader()->theme(); + if (!::qstrcmp(QObject::name(), "mainToolBar")) + avSizes = theme->querySizes( KIcon::MainToolbar); + else + avSizes = theme->querySizes( KIcon::Toolbar); +*/ + avSizes << 16; + avSizes << 32; + + d->iconSizes = avSizes; + + QValueList<int>::Iterator it; + for (it=avSizes.begin(); it!=avSizes.end(); it++) { + QString text; + if ( *it < 19 ) + text = i18n("Small (%1x%2)").arg(*it).arg(*it); + else if (*it < 25) + text = i18n("Medium (%1x%2)").arg(*it).arg(*it); + else + text = i18n("Large (%1x%2)").arg(*it).arg(*it); + //we use the size as an id, with an offset + size->insertItem( text, CONTEXT_ICONSIZES + *it ); + } + + context->insertItem( i18n("Orientation"), orient ); + orient->setItemChecked(CONTEXT_TOP, true); + context->insertItem( i18n("Text Position"), mode ); + context->setItemChecked(CONTEXT_ICONS, true); + context->insertItem( i18n("Icon Size"), size ); + +/*US + if (mainWindow()->inherits("KMainWindow")) + { + if ( (static_cast<KMainWindow*>(mainWindow())->toolBarMenuAction()) && + (static_cast<KMainWindow*>(mainWindow())->hasMenuBar()) ) + + (static_cast<KMainWindow*>(mainWindow()))->toolBarMenuAction()->plug(context); + } +*/ + + connect( context, SIGNAL( aboutToShow() ), this, SLOT( slotContextAboutToShow() ) ); + return context; +} + +void KToolBar::slotContextAboutToShow() +{ + if (!d->m_configurePlugged) + { + // try to find "configure toolbars" action + + KXMLGUIClient *xmlGuiClient = d->m_xmlguiClient; + if ( !xmlGuiClient && mainWindow() && mainWindow()->inherits( "KMainWindow" ) ) + xmlGuiClient = (KXMLGUIClient *)mainWindow(); + if ( xmlGuiClient ) + { + KAction *configureAction = xmlGuiClient->actionCollection()->action(KStdAction::stdName(KStdAction::ConfigureToolbars)); + if ( configureAction ) + { + configureAction->plug(context); + d->m_configurePlugged = true; + } + } + } + + for(int i = CONTEXT_ICONS; i <= CONTEXT_TEXTUNDER; ++i) + context->setItemChecked(i, false); + + switch( d->m_iconText ) + { + case IconOnly: + default: + context->setItemChecked(CONTEXT_ICONS, true); + break; + case IconTextRight: + context->setItemChecked(CONTEXT_TEXTRIGHT, true); + break; + case TextOnly: + context->setItemChecked(CONTEXT_TEXT, true); + break; + case IconTextBottom: + context->setItemChecked(CONTEXT_TEXTUNDER, true); + break; + } + + QValueList<int>::ConstIterator iIt = d->iconSizes.begin(); + QValueList<int>::ConstIterator iEnd = d->iconSizes.end(); + for (; iIt != iEnd; ++iIt ) + context->setItemChecked( CONTEXT_ICONSIZES + *iIt, false ); + + context->setItemChecked( CONTEXT_ICONSIZES, false ); + + context->setItemChecked( CONTEXT_ICONSIZES + d->m_iconSize, true ); + + for ( int i = CONTEXT_TOP; i <= CONTEXT_FLAT; ++i ) + context->setItemChecked( i, false ); + + switch ( barPos() ) + { + case KToolBar::Flat: + context->setItemChecked( CONTEXT_FLAT, true ); + break; + case KToolBar::Bottom: + context->setItemChecked( CONTEXT_BOTTOM, true ); + break; + case KToolBar::Left: + context->setItemChecked( CONTEXT_LEFT, true ); + break; + case KToolBar::Right: + context->setItemChecked( CONTEXT_RIGHT, true ); + break; + case KToolBar::Floating: + context->setItemChecked( CONTEXT_FLOAT, true ); + break; + case KToolBar::Top: + context->setItemChecked( CONTEXT_TOP, true ); + break; + default: break; + } +} + +void KToolBar::widgetDestroyed() +{ + removeWidgetInternal( (QWidget*)sender() ); +} + +void KToolBar::removeWidgetInternal( QWidget * w ) +{ + if ( inshutdownprocess ) + return; + widgets.removeRef( w ); + QMap< QWidget*, int >::Iterator it = widget2id.find( w ); + if ( it == widget2id.end() ) + return; + id2widget.remove( *it ); + widget2id.remove( it ); +} + +void KToolBar::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "ktoolbar.moc" + diff --git a/microkde/kdeui/ktoolbar.h b/microkde/kdeui/ktoolbar.h new file mode 100644 index 0000000..2c061b5 --- a/dev/null +++ b/microkde/kdeui/ktoolbar.h @@ -0,0 +1,1107 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Reginald Stadlbauer (reggie@kde.org) + (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 1999, 2000 Kurt Granroth (granroth@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ + +#ifndef KTOOLBAR_H +#define KTOOLBAR_H + +#ifndef DESKTOP_VERSION +#define private public +#include <qtoolbar.h> +#undef private +#include <qpe/qpetoolbar.h> +#else +#include <qtoolbar.h> +#endif + + +#include <qmainwindow.h> +#include <qcombobox.h> +#include <qmap.h> +#include <qptrlist.h> +#include <kglobal.h> +#include <qguardedptr.h> +#include <qframe.h> +#include <qiconset.h> + +class QDomElement; +class QSize; +class QPixmap; +class QPopupMenu; +class QStringList; +class QDomDocument; +class QTimer; + +class KLineEdit; +class KToolBar; +class KToolBarButton; +class KToolBoxManager; +//US class KAnimWidget; +//US class KPopupMenu; +//US class KInstance; +class KComboBox; +class KXMLGUIClient; + +class KToolBarPrivate; + +class KToolBarSeparator : public QFrame +{ + Q_OBJECT +public: + KToolBarSeparator( Orientation, bool l, QToolBar *parent, const char* name=0 ); + + QSize sizeHint() const; + Orientation orientation() const { return orient; } + QSizePolicy sizePolicy() const; + bool showLine() const { return line; } +public slots: + void setOrientation( Orientation ); +protected: + void styleChange( QStyle& ); +private: + Orientation orient; + bool line; +}; + + + /** + * A KDE-style toolbar. + * + * KToolBar can be dragged around in and between different docks. + * + * A KToolBar can contain all sorts of widgets. + * + * KToolBar can be used as a standalone widget, but @ref KMainWindow + * provides easy factories and management of one or more toolbars. + * Once you have a KToolBar object, you can insert items into it with the + * insert... methods, or remove them with the @ref removeItem() method. This + * can be done at any time; the toolbar will be automatically updated. + * There are also many methods to set per-child properties like alignment + * and toggle behaviour. + * + * KToolBar uses a global config group to load toolbar settings on + * construction. It will reread this config group on a + * @ref KApplication::appearanceChanged() signal. + * + * @short Floatable toolbar with auto resize. + * @version $Id$ + * @author Reginald Stadlbauer <reggie@kde.org>, Stephan Kulow <coolo@kde.org>, Sven Radej <radej@kde.org>. + */ + +// strange things are happening ... so I have to use strange define methods ... +// porting KToolBar back to Qt2 really needs some strange hacks + +#ifndef DESKTOP_VERSION +#define QToolBar QPEToolBar +#endif + + class KToolBar : public QToolBar +{ + Q_OBJECT + + + Q_ENUMS( IconText BarPosition ) + + Q_PROPERTY( IconText iconText READ iconText WRITE setIconText ) + Q_PROPERTY( BarPosition barPos READ barPos WRITE setBarPos ) + Q_PROPERTY( bool fullSize READ fullSize WRITE setFullSize ) + Q_PROPERTY( int iconSize READ iconSize WRITE setIconSize ) + Q_PROPERTY( QString text READ text WRITE setText ) +#ifndef DESKTOP_VERSION +#undef QToolBar +#endif +public: + enum IconText{IconOnly = 0, IconTextRight, TextOnly, IconTextBottom}; + /** + * The state of the status bar. + * @deprecated + **/ + enum BarStatus{Toggle, Show, Hide}; + /** + * Possible bar positions. + **/ + enum BarPosition{ Unmanaged, Floating, Top, Bottom, Right, Left, Flat}; + + /** + * Constructor. + * This constructor is used by the XML-GUI. If you use it, you need + * to call QMainWindow::addToolBar to specify the position of the toolbar. + * So it's simpler to use the other constructor. + * + * The toolbar will read in various global config settings for + * things like icon size and text position, etc. However, some of + * the settings will be honored only if @ref #_honor_mode is set to + * true. All other toolbars will be IconOnly and use Medium icons. + * + * @param parent The standard toolbar parent (usually a + * @ref KMainWindow) + * @param name The standard internal name + * @param honor_style If true, then global settings for IconSize and IconText will be honored + * @param readConfig whether to apply the configuration (global and application-specific) + */ + KToolBar( QWidget *parent, const char *name = 0, bool honor_style = FALSE, bool readConfig = TRUE ); + + /** + * Constructor for non-XML-GUI applications. + * + * The toolbar will read in various global config settings for + * things like icon size and text position, etc. However, some of + * the settings will be honored only if @ref #_honor_mode is set to + * true. All other toolbars will be IconOnly and use Medium icons. + * + * @param parentWindow The window that should be the parent of this toolbar + * @param dock The position of the toolbar. Usually QMainWindow::Top. + * @param newLine If true, start a new line in the dock for this toolbar. + * @param name The standard internal name + * @param honor_style If true, then global settings for IconSize and IconText will be honored + * @param readConfig whether to apply the configuration (global and application-specific) + */ + KToolBar( QMainWindow *parentWindow, QMainWindow::ToolBarDock dock /*= QMainWindow::Top*/, bool newLine = false, + const char *name = 0, bool honor_style = FALSE, bool readConfig = TRUE ); + + /** + * Constructor for non-XML-GUI applications. + * + * The toolbar will read in various global config settings for + * things like icon size and text position, etc. However, some of + * the settings will be honored only if @ref #_honor_mode is set to + * true. All other toolbars will be IconOnly and use Medium icons. + * + * @param parentWindow The window that should be the parent of this toolbar + * @param dock Another widget than the mainwindow to dock toolbar to. + * @param newLine If true, start a new line in the dock for this toolbar. + * @param name The standard internal name + * @param honor_style If true, then global settings for IconSize and IconText will be honored + * @param readConfig whether to apply the configuration (global and application-specific) + */ + KToolBar( QMainWindow *parentWindow, QWidget *dock, bool newLine = false, + const char *name = 0, bool honor_style = FALSE, bool readConfig = TRUE ); + + virtual ~KToolBar(); + + /** + * Insert a button (a @ref KToolBarButton) with a pixmap. The + * pixmap is loaded by the button itself based on the global icon + * settings. + * + * You should connect to one or more signals in KToolBar: + * @ref clicked() , @ref pressed() , @ref released() , or + * @ref highlighted() and if the button is a toggle button + * (@ref setToggle() ) @ref toggled() . Those signals have @p id + * of a button that caused the signal. If you want to bind a popup + * to button, see @ref setButton(). + * + * @param icon The name of the icon to use as the active pixmap + * @param id The id of this button + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QString& icon, int id, bool enabled = true, + const QString& text = QString::null, int index=-1/*US , + KInstance *_instance = KGlobal::instance()*/); + + /** + * This is the same as above, but with specified signals and + * slots to which this button will be connected. + * + * You can add more signals with @ref addConnection(). + * + * @param icon The name of the icon to use as the active pixmap + * @param id The id of this button + * @param signal The signal to connect to + * @param receiver The slot's parent + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QString& icon, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled = true, const QString& text = QString::null, + int index=-1/*US, KInstance *_instance = KGlobal::instance()*/ ); + + /** + * Inserts a button (a @ref KToolBarButton) with the specified + * pixmap. This pixmap will be used as the "active" one and the + * disabled and default ones will be autogenerated. + * + * It is recommended that you use the insertButton function that + * allows you to specify the icon name rather then the pixmap + * itself. Specifying the icon name is much more flexible. + * + * You should connect to one or more signals in KToolBar: + * @ref clicked() , @ref pressed() , @ref released() , or + * @ref highlighted() and if the button is a toggle button + * (@ref setToggle() ) @ref toggled() . Those signals have @p id + * of a button that caused the signal. If you want to bind a popup + * to button, see @ref setButton(). + * + * @param pixmap The active pixmap + * @param id The id of this button + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QPixmap& pixmap, int id, bool enabled = true, + const QString& text = QString::null, int index=-1 ); + + /** + * This is the same as above, but with specified signals and + * slots to which this button will be connected. + * + * You can add more signals with @ref addConnection(). + * + * @param icon The name of the icon to use as the active pixmap + * @param id The id of this button + * @param signal The signal to connect to + * @param receiver The slot's parent + * @param enabled Enable or disable the button at startup + * @param text The tooltip or toolbar text (depending on state) + * @param index The position of the button. (-1 = at end). + * + * @return The item index. + */ + int insertButton(const QPixmap& pixmap, int id, const char *signal, + const QObject *receiver, const char *slot, + bool enabled = true, const QString& text = QString::null, + int index=-1 ); + + /** + * Inserts a button with popupmenu. + * + * Button will have small + * triangle. You have to connect to popup's signals. The + * signals @ref KButton::pressed(), @ref KButton::released(), + * @ref KButton::clicked() or @ref KButton::doubleClicked() are @p not + * emmited by + * this button (see @ref setDelayedPopup() for that). + * You can add custom popups which inherit @ref QPopupMenu to get popups + * with tables, drawings etc. Just don't fiddle with events there. + */ + int insertButton(const QString& icon, int id, QPopupMenu *popup, + bool enabled, const QString&_text, int index=-1); + + /** + * Inserts a button with popupmenu. + * + * Button will have small + * triangle. You have to connect to popup's signals. The + * signals @ref KButton::pressed(), @ref KButton::released(), + * @ref KButton::clicked() or @ref KButton::doubleClicked() are @p not + * emmited by + * this button (see @ref setDelayedPopup() for that). + * You can add custom popups which inherit @ref QPopupMenu to get popups + * with tables, drawings etc. Just don't fiddle with events there. + */ + int insertButton(const QPixmap& pixmap, int id, QPopupMenu *popup, + bool enabled, const QString&_text, int index=-1); + + /** + * Inserts a @ref KLineEdit. You have to specify signals and slots to + * which KLineEdit will be connected. KLineEdit has all slots QLineEdit + * has, plus signals @ref KLineEdit::completion and @ref KLineEdit::textRotation + * KLineEdit can be set to autoresize itself to full free width + * in toolbar, that is to last right aligned item. For that, + * toolbar must be set to full width (which it is by default). + * @see setFullWidth() + * @see setItemAutoSized() + * @see KLineEdit + * @return Item index. + */ + int insertLined (const QString& text, int id, + const char *signal, + const QObject *receiver, const char *slot, + bool enabled = true, + const QString& toolTipText = QString::null, + int size = 70, int index =-1); + + /** + * Inserts a @ref KComboBox with list. + * + * Can be writable, but cannot contain + * pixmaps. By default inserting policy is AtBottom, i.e. typed items + * are placed at the bottom of the list. Can be autosized. If the size + * argument is specified as -1, the width of the combobox is automatically + * computed. + * + * @see setFullWidth() + * @see setItemAutoSized() + * @see KComboBox + * @return Item index. + */ + int insertCombo (const QStringList &list, int id, bool writable, + const char *signal, const QObject *receiver, + const char *slot, bool enabled=true, + const QString& tooltiptext=QString::null, + int size=70, int index=-1, + QComboBox::Policy policy = QComboBox::AtBottom); + + /** + * Insert a @ref KComboBox with text. + * + * The rest is the same as above. + * @see setItemAutoSized() + * + * @see KComboBox + * @return Item index. + */ + int insertCombo (const QString& text, int id, bool writable, + const char *signal, QObject *recevier, + const char *slot, bool enabled=true, + const QString& tooltiptext=QString::null, + int size=70, int index=-1, + QComboBox::Policy policy = QComboBox::AtBottom); + + /** + * Inserts a separator into the toolbar with the given id. + * Returns the separator's index + */ + int insertSeparator( int index = -1, int id = -1 ); + + /** + * Inserts a line separator into the toolbar with the given id. + * Returns the separator's index + */ + int insertLineSeparator( int index = -1, int id = -1 ); + + /** + * Inserts a user-defined widget. The widget @p must have this + * toolbar as its parent. + * + * Widget must have a QWidget for base class. Widget can be + * autosized to full width. If you forget about it, you can get a + * pointer to this widget with @ref getWidget(). + * @see setItemAutoSized() + * @return Item index. + */ + int insertWidget(int id, int width, QWidget *_widget, int index=-1); + + /** + * Inserts an animated widget. A @ref KAnimWidget will be created + * internally using the icon name you provide. + * This will emit a signal (clicked()) whenever the + * animation widget is clicked. + * + * @see animatedWidget() + * + * @param id The id for this toolbar item + * @param receiver The parent of your slot + * @param slot The slot to receive the clicked() signal + * @param icons The name of the animation icon group to use + * @param index The item index + * + * @return The item index + */ +/*US + int insertAnimatedWidget(int id, QObject *receiver, const char *slot, + const QString& icons, int index = -1); +*/ + /** + * This will return a pointer to the given animated widget, if it + * exists. + * + * @see insertAnimatedWidget + * + * @param id The id for the widget you want to get a pointer to + * + * @return A pointer to the current animated widget or 0L + */ +//US KAnimWidget *animatedWidget( int id ); + + /** + * Adds connections to items. + * + * It is important that you + * know the @p id of particular item. Nothing happens if you forget @p id. + */ + void addConnection (int id, const char *signal, + const QObject *receiver, const char *slot); + /** + * Enables/disables item. + */ + void setItemEnabled( int id, bool enabled ); + + /** + * Sets the icon for a button. + * + * Can be used while button is visible. + */ + void setButtonIcon( int id, const QString& _icon ); + + /** + * Sets button pixmap. + * + * Can be used while button is visible. + */ + void setButtonPixmap( int id, const QPixmap& _pixmap ); + + /** + * Sets a button icon from a QIconSet. + * + * Can be used while button is visible. + */ + void setButtonIconSet( int id, const QIconSet& iconset ); + + /** + * Sets a delayed popup for a button. + * + * Delayed popup is what you see in + * Netscape Navigator's Previous and Next buttons: If you click them you + * go back + * or forth. If you press them long enough, you get a history-menu. + * This is exactly what we do here. + * + * You will insert normal a button with connection (or use signals from + * toolbar): + * <pre> + * bar->insertButton(icon, id, SIGNAL(clicked ()), this, + * SLOT (slotClick()), true, "click or wait for popup"); + * </pre> And then add a delayed popup: + * <pre> + * bar->setDelayedPopup (id, historyPopup); </pre> + * + * Don't add delayed popups to buttons which have normal popups. + * + * You may add popups which are derived from @ref QPopupMenu. You may + * add popups that are already in the menu bar or are submenus of + * other popups. + */ + void setDelayedPopup (int id , QPopupMenu *_popup, bool toggle = false); + + /** + * Turns a button into an autorepeat button. + * + * Toggle buttons, buttons with menus, or + * buttons with delayed menus cannot be made into autorepeat buttons. + * Moreover, you can and will receive + * only the signal clicked(), but not pressed() or released(). + * When the user presses this button, you will receive the signal clicked(), + * and if the button is still pressed after some time, + * you will receive more clicked() signals separated by regular + * intervals. Since this uses @ref QButton::setAutoRepeat() , + * I can't quantify 'some'. + */ + void setAutoRepeat (int id, bool flag=true); + + + /** + * Turns button into a toggle button if @p flag is true. + */ + void setToggle (int id, bool flag = true); + + /** + * Toggles a togglebutton. + * + * If the button is a toggle button (see @ref setToggle()) + * the button state will be toggled. This will also cause the toolbar to + * emit the signal @ref KButton::toggled() with parameter @p id. You must connect to + * this signal, or use @ref addConnection() to connect directly to the + * button signal @ref KButton::toggled(). + */ + void toggleButton (int id); + + /** + * Sets a toggle button state. + * + * If the button is a toggle button (see @ref setToggle()) + * this will set its state flag. This will also emit the signal + * @ref KButton::toggled(). + * + * @see setToggle() + */ + void setButton (int id, bool flag); + + /** + * @return @p true if button is on, @p false if button is off or if the + * button is not a toggle button. + * @see setToggle() + */ + bool isButtonOn (int id) const; + + /** + * Sets the text of a line editor. + * + * Cursor is set at end of text. + */ + void setLinedText (int id, const QString& text); + + /** + * Returns a line editor text. + */ + QString getLinedText (int id) const; + + /** + * Inserts @p text in combobox @p id at position @p index. + */ + void insertComboItem (int id, const QString& text, int index); + + /** + * Inserts @p list in combobox @p id at position @p index. + */ + void insertComboList (int id, const QStringList &list, int index); + + /** + * Removes item @p index from combobox @p id. + */ + void removeComboItem (int id, int index); + + /** + * Sets item @p index to be current item in combobox @p id. + */ + void setCurrentComboItem (int id, int index); + + /** + * Changes item @p index in combobox @p id to text. + * + * @p index = -1 refers current item (one displayed in the button). + */ + void changeComboItem (int id, const QString& text, int index=-1); + + /** + * Clears the combobox @p id. + * + * Does not delete it or hide it. + */ + void clearCombo (int id); + + /** + * Returns text of item @p index from combobox @p id. + * + * @p index = -1 refers to current item. + */ + + QString getComboItem (int id, int index=-1) const; + + /** + * Returns a pointer to the combobox. + * + * Example: + * <pre> + * KComboBox *combo = toolbar->getCombo(combo_id); + * </pre> + * That way you can get access to other public methods + * that @ref KComboBox provides. + */ + KComboBox * getCombo(int id); + + /** + * Returns a pointer to KToolBarLined. + * + * Example: + * <pre> + * KLineEdit * lined = toolbar->getKToolBarLined(lined_id); + * </pre> + * That way you can get access to other public methods + * that @ref KLineEdit provides. @ref KLineEdit is the same thing + * as @ref QLineEdit plus completion signals. + */ + KLineEdit * getLined (int id); + + /** + * Returns a pointer to KToolBarButton. + * + * Example: + * <pre> + * KToolBarButton * button = toolbar->getButton(button_id); + * </pre> + * That way you can get access to other public methods + * that @ref KToolBarButton provides. + * + * Using this method is not recommended. + */ + KToolBarButton * getButton (int id); + + /** + * Align item to the right. + * + * This works only if toolbar is set to full width. + * @see setFullWidth() + */ + void alignItemRight (int id, bool right = true); + + /** + * Returns a pointer to an inserted widget. + * + * Wrong ids are not tested. + * You can do with this whatever you want, + * except change its height (hardcoded). If you change its width + * you will probably have to call QToolBar::updateRects(true) + * @see QWidget + * @see updateRects() + * + * KDE4: make this const! + */ + QWidget *getWidget (int id); + + /** + * Set item autosized. + * + * This works only if the toolbar is set to full width. + * Only @p one item can be autosized, and it has to be + * the last left-aligned item. Items that come after this must be right + * aligned. Items that can be right aligned are Lineds, Frames, Widgets and + * Combos. An autosized item will resize itself whenever the toolbar geometry + * changes to the last right-aligned item (or to end of toolbar if there + * are no right-aligned items.) + * @see setFullWidth() + * @see alignItemRight() + */ + void setItemAutoSized (int id, bool yes = true); + + /** + * Remove all items. + * + * The toolbar is redrawn after it. + */ + void clear (); + + /** + * Remove item @p id. + * + * Item is deleted. Toolbar is redrawn after it. + */ + void removeItem (int id); + + /** + * Remove item @p id. + * + * Item is deleted when toolbar is redrawn. + */ + void removeItemDelayed (int id); + + /** + * Hide item. + */ + void hideItem (int id); + + /** + * Show item. + */ + void showItem (int id); + + /** + * Returns the index of the given item. + * + * KDE4: make this const! + */ + int itemIndex (int id); + + /** + * Set toolbar to full parent size (default). + * + * In full size mode the bar + * extends over the parent's full width or height. If the mode is disabled + * the toolbar tries to take as much space as it needs without wrapping, but + * it does not exceed the parent box. You can force a certain width or + * height with @ref setMaxWidth() or @ref setMaxHeight(). + * + * If you want to use right-aligned items or auto-sized items you must use + * full size mode. + */ + void setFullSize(bool flag = true); + + /** + * @return @p true if the full-size mode is enabled. Otherwise + * it returns @false. + */ + bool fullSize() const; + + /** + * @deprecated use setMovingEnabled(bool) instead. + * Enable or disable moving of toolbar. + */ + void enableMoving(bool flag = true); + + /** + * Set position of toolbar. + * @see BarPosition() + */ + void setBarPos (BarPosition bpos); + + /** + * Returns position of toolbar. + */ + BarPosition barPos(); + + /** + * @deprecated + * Show, hide, or toggle toolbar. + * + * This method is provided for compatibility only, + * please use show() and/or hide() instead. + * @see BarStatus + */ + bool enable(BarStatus stat); + + /** + * @deprecated + * Use setMaximumHeight() instead. + */ + void setMaxHeight (int h); // Set max height for vertical toolbars + + /** + * @deprecated + * Use maximumHeight() instead. + * Returns the value that was set with @ref setMaxHeight(). + */ + int maxHeight(); + + /** + * @deprecated + * Use setMaximumWidth() instead. + * Set maximal width of horizontal (top or bottom) toolbar. + */ + void setMaxWidth (int dw); + + /** + * @deprecated + * Use maximumWidth() instead. + * Returns the value that was set with @ref setMaxWidth(). + */ + int maxWidth(); + + /** + * Set title for toolbar when it floats. + * + * Titles are however not (yet) + * visible. You can't change toolbar's title while it's floating. + */ + void setTitle (const QString& _title); + + /** + * @deprecated + * Use enableMoving() instead. + */ + void enableFloating (bool arrrrrrgh); + + /** + * Set the kind of painting for buttons. + * + * Choose from: + * @li IconOnly (only icons), + * @li IconTextRight (icon and text, text is left from icons), + * @li TextOnly (only text), + * @li IconTextBottom (icons and text, text is under icons). + * @see IconText + * + */ + void setIconText(IconText it); + // Note: don't merge with the next one, it breaks Qt properties + + /** + * Similar to @ref setIconText(IconText it) but allows you to + * disable or enable updating. If @p update is false, then the + * buttons will not be updated. This is useful only if you know + * that you will be forcing an update later. + */ + void setIconText(IconText it, bool update); + + /** + * @return The current text style for buttons. + */ + IconText iconText() const; + + /** + * Set the icon size to load. Usually you should not call + * this, the icon size is taken care of by KIconLoader + * and globally configured. + * By default, the toolbar will load icons of size 32 for main + * toolbars and 22 for other toolbars + * @see KIconLoader. + * + * @param size The size to use + */ + void setIconSize(int size); + // Note: don't merge with the next one, it breaks Qt properties + + /** + * Same as @ref setIconText(int size) but allows you + * to disable the toolbar update. + * + * @param size The size to use + * @param update If true, then the toolbar will be updated after + * this + */ + void setIconSize(int size, bool update); + + /** + * @return The current icon size for buttons. + */ + int iconSize() const; + + /** + * This allows you to enable or disable the context menu. + * + * @param enable If false, then the context menu will be disabled + */ + void setEnableContextMenu(bool enable = true); + + /** + * Returns whether or not the context menu is disabled + * + * @return The context menu state + */ + bool contextMenuEnabled() const; + + /** + * This will inform a toolbar button to ignore certain style + * changes. Specifically, it will ignore IconText (always IconOnly) + * and will not allow image effects to apply. + * + * @param id The button to exclude from styles + * @param no_style If true, then it is excluded (default: true). + */ + void setItemNoStyle(int id, bool no_style = true); + + void setFlat (bool flag); + + /** + * @return the number of items in the toolbar + */ + int count() const; + + /** + * Instruct the toolbar to save it's current state to either the app + * config file or to the XML-GUI resource file (whichever has + * precedence). + */ + void saveState(); + + /** + * Save the toolbar settings to group @p configGroup in @p config. + */ + void saveSettings(KConfig *config, const QString &configGroup); + + /** + * Read the toolbar settings from group @p configGroup in @p config + * and apply them. + */ + void applySettings(KConfig *config, const QString &configGroup); + + /** + * Tell the toolbar what XML-GUI resource file it should use to save + * it's state. The state of the toolbar (position, size, etc) is + * saved in KConfig files if the application does not use XML-GUI.. + * but if the app does, then it's saved the XML file. This function + * allows this to happen. + * + * @param xmlfile The XML-GUI resource file to write to + * @param xml The DOM document for the XML-GUI building + */ + // void setXML(const QString& xmlfile, const QDomDocument& xml); + /* @internal */ + void setXMLGUIClient( KXMLGUIClient *client ); + + /** + * Assign a (translated) text to this toolbar. This is used + * for the tooltip on the handle, and when listing the toolbars. + */ + void setText( const QString & txt ); + + /** + * @return the toolbar's text. + */ + QString text() const; + + void setStretchableWidget( QWidget *w ); + QSizePolicy sizePolicy() const; + bool highlight() const; + QSize sizeHint() const; + QSize minimumSizeHint() const; + QSize minimumSize() const; + + void hide(); + void show(); + + void updateRects( bool = FALSE ) {} + +//US void loadState( const QDomElement &e ); +//US void saveState( QDomElement &e ); + + /** + * @internal + */ + void positionYourself( bool force = false); + +signals: + /** + * Emitted when button @p id is clicked. + */ + void clicked(int id); + + /** + * Emitted when button @p id is double-clicked. + * + * Note: you will always + * recive two @ref clicked() , @ref pressed() and @ref released() signals. + * There is no way to avoid it - at least no easy way. + * If you need to resolve this all you can do is set up timers + * which wait for @ref QApplication::doubleClickInterval() to expire. + * If in that time you don't get this signal, you may belive that + * button was only clicked and not double-clicked. + * And please note that butons with popup menus do not emit this signal, + * but those with delayed popup do. + */ + void doubleClicked (int id); + + /** + * Emitted when button @p id is pressed. + */ + void pressed(int); + + /** + * Emits when button @p id is released. + */ + void released(int); + + /** + * Emitted when a toggle button changes state. + * + * Emitted also if you change state + * with @ref setButton() or @ref toggleButton() + * If you make a button normal again, with + * setToggle(false), this signal won't + * be emitted. + */ + void toggled(int); + + /** + * This signal is emitted when item id gets highlighted/unhighlighted + * (i.e when mouse enters/exits). + * + * Note that this signal is emitted from + * all buttons (normal, disabled and toggle) even when there is no visible + * change in buttons (i.e., buttons do not raise when mouse enters). + * The parameter @p isHighlighted is @p true when mouse enters and @p false when + * mouse exits. + */ + void highlighted(int id, bool isHighlighted); + + /** + * This signal is emitted when item id gets highlighted/unhighlighted + * (i.e when mouse enters/exits). + * + * Note that this signal is emitted from + * all buttons (normal, disabled and toggle) even when there is no visible + * change in buttons (i.e., buttons do not raise when mouse enters). + */ + void highlighted(int id ); + + /** + * Emitted when toolbar changes position, or when + * an item is removed from toolbar. + * + * If you subclass @ref KMainWindow and reimplement + * @ref KMainWindow::resizeEvent() be sure to connect to + * this signal. Note: You can connect this signal to a slot that + * doesn't take parameter. + */ + void moved( BarPosition ); + + /** + * @internal + * This signal is emitted when toolbar detects changing of + * following parameters: + * highlighting, button-size, button-mode. This signal is + * internal, aimed to buttons. + */ + void modechange (); + + /** + * This signal is emitted when the toolbar is getting deleted, + * and before ~KToolbar finishes (so it's still time to remove + * widgets from the toolbar). + * Used by KWidgetAction. + * @since 3.2 + */ + void toolbarDestroyed(); + +public: + /** + * @return global setting for "Highlight buttons under mouse" + */ + static bool highlightSetting(); + + /** + * @return global setting for "Toolbars transparent when moving" + */ + static bool transparentSetting(); + + /** + * @return global setting for "Icon Text" + */ + static IconText iconTextSetting(); + +public slots: + virtual void setIconText( const QString &txt ) + { QToolBar::setIconText( txt ); } + +protected: + void mousePressEvent( QMouseEvent * ); + void childEvent( QChildEvent *e ); + void showEvent( QShowEvent *e ); + void resizeEvent( QResizeEvent *e ); + bool event( QEvent *e ); + void applyAppearanceSettings(KConfig *config, const QString &_configGroup, bool forceGlobal = false); + QString settingsGroup(); + +private slots: + void rebuildLayout(); + void slotReadConfig (); + void slotAppearanceChanged(); + void slotIconChanged(int); + void slotRepaint(); + void toolBarPosChanged( QToolBar *tb ); + void slotContextAboutToShow(); + void widgetDestroyed(); + +private: + void init( bool readConfig = true, bool honorStyle = false ); + void doConnections( KToolBarButton *button ); + void insertWidgetInternal( QWidget *w, int &index, int id ); + void removeWidgetInternal( QWidget *w ); + void getAttributes( QString &position, QString &icontext, int &index ); +//US KPopupMenu *contextMenu(); + QPopupMenu *contextMenu(); + + QMap<QWidget*, int > widget2id; + typedef QMap<int, QWidget* > Id2WidgetMap; + Id2WidgetMap id2widget; +//US KPopupMenu *context; + QPopupMenu *context; + QPtrList<QWidget> widgets; + QTimer *layoutTimer; + QGuardedPtr<QWidget> stretchableWidget, rightAligned; +protected: + virtual void virtual_hook( int id, void* data ); +private: + KToolBarPrivate *d; + bool inshutdownprocess; +}; + +#endif diff --git a/microkde/kdeui/ktoolbarbutton.cpp b/microkde/kdeui/ktoolbarbutton.cpp new file mode 100644 index 0000000..1d5d0e5 --- a/dev/null +++ b/microkde/kdeui/ktoolbarbutton.cpp @@ -0,0 +1,756 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 1999 Chris Schlaeger (cs@kde.org) + (C) 1999 Kurt Granroth (granroth@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//US #include <config.h> +#include <string.h> + +#include "ktoolbarbutton.h" +#include "ktoolbar.h" + +#include <qstyle.h> +#include <qimage.h> +#include <qtimer.h> +#include <qdrawutil.h> +#include <qtooltip.h> +#include <qbitmap.h> +#include <qpopupmenu.h> +#include <qcursor.h> +#include <qpainter.h> +#include <qlayout.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kglobalsettings.h> +//US #include <kiconeffect.h> +#include <kiconloader.h> + +// needed to get our instance +#include <kmainwindow.h> + +template class QIntDict<KToolBarButton>; + +class KToolBarButtonPrivate +{ +public: + KToolBarButtonPrivate() + { + m_noStyle = false; + m_isSeparator = false; + m_isRadio = false; + m_highlight = false; + m_isRaised = false; + m_isActive = false; + + m_iconName = QString::null; + m_iconText = KToolBar::IconOnly; + m_iconSize = 0; + +//US m_instance = KGlobal::instance(); + } + ~KToolBarButtonPrivate() + { + } + + int m_id; + bool m_noStyle: 1; + bool m_isSeparator: 1; + bool m_isRadio: 1; + bool m_highlight: 1; + bool m_isRaised: 1; + bool m_isActive: 1; + + QString m_iconName; + + KToolBar *m_parent; + KToolBar::IconText m_iconText; + int m_iconSize; + QSize size; + + QPoint m_mousePressPos; + +//US KInstance *m_instance; +}; + +// This will construct a separator +KToolBarButton::KToolBarButton( QWidget *_parent, const char *_name ) + : QToolButton( _parent , _name) +{ + d = new KToolBarButtonPrivate; + + resize(6,6); + hide(); + d->m_isSeparator = true; +} + +KToolBarButton::KToolBarButton( const QString& _icon, int _id, + QWidget *_parent, const char *_name, + const QString &_txt/*US, KInstance *_instance*/ ) + : QToolButton( _parent, _name ), d( 0 ) +{ + d = new KToolBarButtonPrivate; + + d->m_id = _id; + d->m_parent = (KToolBar*)_parent; + QToolButton::setTextLabel(_txt); +//US d->m_instance = _instance; + + setFocusPolicy( NoFocus ); + + // connect all of our slots and start trapping events + connect(d->m_parent, SIGNAL( modechange() ), + this, SLOT( modeChange() )); + + connect(this, SIGNAL( clicked() ), + this, SLOT( slotClicked() ) ); + connect(this, SIGNAL( pressed() ), + this, SLOT( slotPressed() ) ); + connect(this, SIGNAL( released() ), + this, SLOT( slotReleased() ) ); + installEventFilter(this); + + d->m_iconName = _icon; + + // do our initial setup + modeChange(); +} + +KToolBarButton::KToolBarButton( const QPixmap& pixmap, int _id, + QWidget *_parent, const char *name, + const QString& txt) + : QToolButton( _parent, name ), d( 0 ) +{ + d = new KToolBarButtonPrivate; + + d->m_id = _id; + d->m_parent = (KToolBar *) _parent; + QToolButton::setTextLabel(txt); + + setFocusPolicy( NoFocus ); + + // connect all of our slots and start trapping events + connect(d->m_parent, SIGNAL( modechange()), + this, SLOT(modeChange())); + + connect(this, SIGNAL( clicked() ), + this, SLOT( slotClicked() )); + connect(this, SIGNAL( pressed() ), + this, SLOT( slotPressed() )); + connect(this, SIGNAL( released() ), + this, SLOT( slotReleased() )); + installEventFilter(this); + + // set our pixmap and do our initial setup + setIconSet( QIconSet( pixmap )); + modeChange(); +} + +KToolBarButton::~KToolBarButton() +{ + delete d; d = 0; +} + +void KToolBarButton::modeChange() +{ + QSize mysize; + + // grab a few global variables for use in this function and others + d->m_highlight = d->m_parent->highlight(); + d->m_iconText = d->m_parent->iconText(); + + d->m_iconSize = d->m_parent->iconSize(); + if (!d->m_iconName.isNull()) + setIcon(d->m_iconName); + + // we'll start with the size of our pixmap + int pix_width = d->m_iconSize; + + if ( d->m_iconSize == 0 ) { + if (!strcmp(d->m_parent->name(), "mainToolBar")) +/*US + pix_width = IconSize( KIcon::MainToolbar ); + else + pix_width = IconSize( KIcon::Toolbar ); +*/ +//qDebug("KToolBarButton::modeChange make iconsize configurable"); + pix_width = 16; + } + int pix_height = pix_width; + + int text_height = 0; + int text_width = 0; + + QToolTip::remove(this); + if (d->m_iconText != KToolBar::IconOnly) + { + // okay, we have to deal with fonts. let's get our information now +/*US + QFont tmp_font = KGlobalSettings::toolBarFont(); + + // now parse out our font sizes from our chosen font + QFontMetrics fm(tmp_font); + + text_height = fm.lineSpacing(); + text_width = fm.width(textLabel()); +*/ +//qDebug("KToolBarButton::modeChange make textsize configurable"); + + // none of the other modes want tooltips + } + else + { + QToolTip::add(this, textLabel()); + } + + switch (d->m_iconText) + { + case KToolBar::IconOnly: + mysize = QSize(pix_width, pix_height); + break; + + case KToolBar::IconTextRight: + mysize = QSize(pix_width + text_width + 4, pix_height); + break; + + case KToolBar::TextOnly: + mysize = QSize(text_width + 4, text_height); + break; + + case KToolBar::IconTextBottom: + mysize = QSize((text_width + 4 > pix_width) ? text_width + 4 : pix_width, pix_height + text_height); + break; + + default: + break; + } +/*US + mysize = style().sizeFromContents(QStyle::CT_ToolButton, this, mysize). + expandedTo(QApplication::globalStrut()); +*/ + // make sure that this isn't taller then it is wide + if (mysize.height() > mysize.width()) + mysize.setWidth(mysize.height()); + + d->size = mysize; + setFixedSize(mysize); + updateGeometry(); +} + +void KToolBarButton::setTextLabel( const QString& text, bool tipToo) +{ + if (text.isNull()) + return; + + QString txt(text); + if (txt.right(3) == QString::fromLatin1("...")) + txt.truncate(txt.length() - 3); + + QToolButton::setTextLabel(txt, tipToo); + update(); +} + +void KToolBarButton::setText( const QString& text) +{ + setTextLabel(text, true); + modeChange(); +} + +void KToolBarButton::setIcon( const QString &icon ) +{ + d->m_iconName = icon; + d->m_iconSize = d->m_parent->iconSize(); + // QObject::name() return "const char *" instead of QString. + if (!strcmp(d->m_parent->name(), "mainToolBar")) +/*US QToolButton::setIconSet( d->m_instance->iconLoader()->loadIconSet( + d->m_iconName, KIcon::MainToolbar, d->m_iconSize )); +*/ + QToolButton::setIconSet( KGlobal::iconLoader()->loadIconSet(d->m_iconName )); + else +/*US QToolButton::setIconSet(d->m_instance->iconLoader()->loadIconSet( + d->m_iconName, KIcon::Toolbar, d->m_iconSize )); +*/ + QToolButton::setIconSet(KGlobal::iconLoader()->loadIconSet(d->m_iconName)); +} + +void KToolBarButton::setIconSet( const QIconSet &iconset ) +{ + QToolButton::setIconSet( iconset ); +} + +// remove? +void KToolBarButton::setPixmap( const QPixmap &pixmap ) +{ + if( pixmap.isNull()) // called by QToolButton + { + QToolButton::setPixmap( pixmap ); + return; + } + QIconSet set = iconSet(); + set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Active ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDefaultPixmap( const QPixmap &pixmap ) +{ + QIconSet set = iconSet(); + set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Normal ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDisabledPixmap( const QPixmap &pixmap ) +{ + QIconSet set = iconSet(); + set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Disabled ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDefaultIcon( const QString& icon ) +{ + QIconSet set = iconSet(); + QPixmap pm; + if (!strcmp(d->m_parent->name(), "mainToolBar")) + pm = /*US d->m_instance->iconLoader()*/KGlobal::iconLoader()->loadIcon( icon, KIcon::MainToolbar, + d->m_iconSize ); + else + pm = /*US d->m_instance->iconLoader()*/KGlobal::iconLoader()->loadIcon( icon, KIcon::Toolbar, + d->m_iconSize ); + set.setPixmap( pm, QIconSet::Automatic, QIconSet::Normal ); + QToolButton::setIconSet( set ); +} + +void KToolBarButton::setDisabledIcon( const QString& icon ) +{ + QIconSet set = iconSet(); + QPixmap pm; + if (!strcmp(d->m_parent->name(), "mainToolBar")) + pm = /*US d->m_instance->iconLoader()*/ KGlobal::iconLoader()->loadIcon( icon, KIcon::MainToolbar, + d->m_iconSize ); + else + pm = /*US d->m_instance->iconLoader()*/ KGlobal::iconLoader()->loadIcon( icon, KIcon::Toolbar, + d->m_iconSize ); + set.setPixmap( pm, QIconSet::Automatic, QIconSet::Disabled ); + QToolButton::setIconSet( set ); +} + +QPopupMenu *KToolBarButton::popup() +{ + // obsolete + // KDE4: remove me + return QToolButton::popup(); +} + +void KToolBarButton::setPopup(QPopupMenu *p, bool) +{ + QToolButton::setPopup(p); + QToolButton::setPopupDelay(1); +} + + +void KToolBarButton::setDelayedPopup (QPopupMenu *p, bool) +{ + QToolButton::setPopup(p); +//US QToolButton::setPopupDelay(QApplication::startDragTime()); +} + +void KToolBarButton::leaveEvent(QEvent *) +{ + if( d->m_isRaised || d->m_isActive ) + { + d->m_isRaised = false; + d->m_isActive = false; + repaint(false); + } + + emit highlighted(d->m_id, false); +} + +void KToolBarButton::enterEvent(QEvent *) +{ + if (d->m_highlight) + { + if (isEnabled()) + { + d->m_isActive = true; + if (!isToggleButton()) + d->m_isRaised = true; + } + else + { + d->m_isRaised = false; + d->m_isActive = false; + } + + repaint(false); + } + emit highlighted(d->m_id, true); +} + +bool KToolBarButton::eventFilter(QObject *o, QEvent *ev) +{ + if ((KToolBarButton *)o == this) + { + + // Popup the menu when the left mousebutton is pressed and the mouse + // is moved by a small distance. + if (QToolButton::popup()) + { + if (ev->type() == QEvent::MouseButtonPress) + { + QMouseEvent* mev = static_cast<QMouseEvent*>(ev); + d->m_mousePressPos = mev->pos(); + } + else if (ev->type() == QEvent::MouseMove) + { + QMouseEvent* mev = static_cast<QMouseEvent*>(ev); + if ((mev->pos() - d->m_mousePressPos).manhattanLength() +//US > KGlobalSettings::dndEventDelay()) + > 5 ) + { +//US openPopup(); + return true; + } + } + } + + if ((ev->type() == QEvent::MouseButtonPress || + ev->type() == QEvent::MouseButtonRelease || + ev->type() == QEvent::MouseButtonDblClick) && d->m_isRadio && isOn()) + return true; + + // From Kai-Uwe Sattler <kus@iti.CS.Uni-Magdeburg.De> + if (ev->type() == QEvent::MouseButtonDblClick) + { + emit doubleClicked(d->m_id); + return true; + } + } + + return QToolButton::eventFilter(o, ev); +} + +void KToolBarButton::drawButton( QPainter *_painter ) +{ +#ifdef DESKTOP_VERSION + QStyle::SFlags flags = QStyle::Style_Default; + QStyle::SCFlags active = QStyle::SC_None; + + if (isDown()) { + flags |= QStyle::Style_Down; + active |= QStyle::SC_ToolButton; + } + if (isEnabled()) flags |= QStyle::Style_Enabled; + if (isOn()) flags |= QStyle::Style_On; + if (isEnabled() && d->m_isRaised) flags |= QStyle::Style_Raised; + if (hasFocus()) flags |= QStyle::Style_HasFocus; + + // Draw a styled toolbutton + style().drawComplexControl(QStyle::CC_ToolButton, _painter, this, rect(), + colorGroup(), flags, QStyle::SC_ToolButton, active, QStyleOption()); + +#else + style().drawToolButton(_painter, rect().x(), rect().y(), rect().width(), rect().height(), colorGroup()); +#endif + int dx, dy; + QFont tmp_font(KGlobalSettings::toolBarFont()); + QFontMetrics fm(tmp_font); + QRect textRect; + int textFlags = 0; + + if (d->m_iconText == KToolBar::IconOnly) // icon only + { +/*US + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled, + isOn() ? QIconSet::On : QIconSet::Off ); +*/ + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled); + + if( !pixmap.isNull()) + { + dx = ( width() - pixmap.width() ) / 2; + dy = ( height() - pixmap.height() ) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + _painter->drawPixmap( dx, dy, pixmap ); + } + } + else if (d->m_iconText == KToolBar::IconTextRight) // icon and text (if any) + { +/*US + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled, + isOn() ? QIconSet::On : QIconSet::Off ); +*/ + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled); + + if( !pixmap.isNull()) + { + dx = 4; + dy = ( height() - pixmap.height() ) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + _painter->drawPixmap( dx, dy, pixmap ); + } + + if (!textLabel().isNull()) + { + textFlags = AlignVCenter|AlignLeft; + if (!pixmap.isNull()) + dx = 4 + pixmap.width() + 2; + else + dx = 4; + dy = 0; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + textRect = QRect(dx, dy, width()-dx, height()); + } + } + else if (d->m_iconText == KToolBar::TextOnly) + { + if (!textLabel().isNull()) + { + textFlags = AlignVCenter|AlignLeft; + dx = (width() - fm.width(textLabel())) / 2; + dy = (height() - fm.lineSpacing()) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + textRect = QRect( dx, dy, fm.width(textLabel()), fm.lineSpacing() ); + } + } + else if (d->m_iconText == KToolBar::IconTextBottom) + { +/*US + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled, + isOn() ? QIconSet::On : QIconSet::Off ); +*/ + QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic, + isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) : + QIconSet::Disabled); + + if( !pixmap.isNull()) + { + dx = (width() - pixmap.width()) / 2; + dy = (height() - fm.lineSpacing() - pixmap.height()) / 2; + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + _painter->drawPixmap( dx, dy, pixmap ); + } + + if (!textLabel().isNull()) + { + textFlags = AlignBottom|AlignHCenter; + dx = (width() - fm.width(textLabel())) / 2; + dy = height() - fm.lineSpacing() - 4; + + if ( isDown() /*US && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle*/ ) + { + ++dx; + ++dy; + } + textRect = QRect( dx, dy, fm.width(textLabel()), fm.lineSpacing() ); + } + } + + // Draw the text at the position given by textRect, and using textFlags + if (!textLabel().isNull() && !textRect.isNull()) + { + _painter->setFont(KGlobalSettings::toolBarFont()); + if (!isEnabled()) + _painter->setPen(palette().disabled().dark()); + else if(d->m_isRaised) + _painter->setPen(KGlobalSettings::toolBarHighlightColor()); + else + _painter->setPen( colorGroup().buttonText() ); + _painter->drawText(textRect, textFlags, textLabel()); + } + + if (QToolButton::popup()) + { +#ifdef DESKTOP_VERSION + QStyle::SFlags arrowFlags = QStyle::Style_Default; + + if (isDown()) arrowFlags |= QStyle::Style_Down; + if (isEnabled()) arrowFlags |= QStyle::Style_Enabled; + + style().drawPrimitive(QStyle::PE_ArrowDown, _painter, + QRect(width()-7, height()-7, 7, 7), colorGroup(), + arrowFlags, QStyleOption() ); +#else + style().drawArrow(_painter, Qt::DownArrow, isDown(), + width()-7, height()-7, 7, 7, colorGroup(), isEnabled() ); +#endif + + } +} + +void KToolBarButton::paletteChange(const QPalette &) +{ + if(!d->m_isSeparator) + { + modeChange(); + repaint(false); // no need to delete it first therefore only false + } +} + +void KToolBarButton::showMenu() +{ + // obsolete + // KDE4: remove me +} + +void KToolBarButton::slotDelayTimeout() +{ + // obsolete + // KDE4: remove me +} + +void KToolBarButton::slotClicked() +{ + emit clicked( d->m_id ); +} + +void KToolBarButton::slotPressed() +{ + emit pressed( d->m_id ); +} + +void KToolBarButton::slotReleased() +{ + emit released( d->m_id ); +} + +void KToolBarButton::slotToggled() +{ + emit toggled( d->m_id ); +} + +void KToolBarButton::setNoStyle(bool no_style) +{ + d->m_noStyle = no_style; + + modeChange(); + d->m_iconText = KToolBar::IconTextRight; + repaint(false); +} + +void KToolBarButton::setRadio (bool f) +{ + if ( d ) + d->m_isRadio = f; +} + +void KToolBarButton::on(bool flag) +{ + if(isToggleButton() == true) + setOn(flag); + else + { + setDown(flag); + leaveEvent((QEvent *) 0); + } + repaint(); +} + +void KToolBarButton::toggle() +{ + setOn(!isOn()); + repaint(); +} + +void KToolBarButton::setToggle(bool flag) +{ + setToggleButton(flag); + if (flag == true) + connect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled())); + else + disconnect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled())); +} + +QSize KToolBarButton::sizeHint() const +{ + return d->size; +} + +QSize KToolBarButton::minimumSizeHint() const +{ + return d->size; +} + +QSize KToolBarButton::minimumSize() const +{ + return d->size; +} + +bool KToolBarButton::isRaised() const +{ + return d->m_isRaised; +} + +bool KToolBarButton::isActive() const +{ + return d->m_isActive; +} + +int KToolBarButton::iconTextMode() const +{ + return static_cast<int>( d->m_iconText ); +} + +int KToolBarButton::id() const +{ + return d->m_id; +} + +// KToolBarButtonList +KToolBarButtonList::KToolBarButtonList() +{ + setAutoDelete(false); +} + +void KToolBarButton::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +//US #include "ktoolbarbutton.moc" diff --git a/microkde/kdeui/ktoolbarbutton.h b/microkde/kdeui/ktoolbarbutton.h new file mode 100644 index 0000000..9aaa13c --- a/dev/null +++ b/microkde/kdeui/ktoolbarbutton.h @@ -0,0 +1,313 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org) + (C) 1997, 1998 Sven Radej (radej@kde.org) + (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) + (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) + (C) 2000 Kurt Granroth (granroth@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// $Id$ +#ifndef _KTOOLBARBUTTON_H +#define _KTOOLBARBUTTON_H + +#include <qpixmap.h> +#include <qtoolbutton.h> +#include <qintdict.h> +#include <qstring.h> +#include <kglobal.h> + +class KToolBar; +class KToolBarButtonPrivate; +//USclass KInstance; +class QEvent; +class QPopupMenu; +class QPainter; + +/** + * A toolbar button. This is used internally by @ref KToolBar, use the + * KToolBar methods instead. + * @internal + */ +class KToolBarButton : public QToolButton +{ + Q_OBJECT + +public: + /** + * Construct a button with an icon loaded by the button itself. + * This will trust the button to load the correct icon with the + * correct size. + * + * @param icon Name of icon to load (may be absolute or relative) + * @param id Id of this button + * @param parent This button's parent + * @param name This button's internal name + * @param txt This button's text (in a tooltip or otherwise) + */ + KToolBarButton(const QString& icon, int id, QWidget *parent, + const char *name=0L, const QString &txt=QString::null/*US, + KInstance *_instance = KGlobal::instance()*/); + + /** + * Construct a button with an existing pixmap. It is not + * recommended that you use this as the internal icon loading code + * will almost always get it "right". + * + * @param icon Name of icon to load (may be absolute or relative) + * @param id Id of this button + * @param parent This button's parent + * @param name This button's internal name + * @param txt This button's text (in a tooltip or otherwise) + */ + KToolBarButton(const QPixmap& pixmap, int id, QWidget *parent, + const char *name=0L, const QString &txt=QString::null); + + /** + * Construct a separator button + * + * @param parent This button's parent + * @param name This button's internal name + */ + KToolBarButton(QWidget *parent=0L, const char *name=0L); + + /** + * Standard destructor + */ + ~KToolBarButton(); + QSize sizeHint() const; + QSize minimumSizeHint() const; + QSize minimumSize() const; + +#ifndef KDE_NO_COMPAT + /** + * @deprecated + * Set the pixmap directly for this button. This pixmap should be + * the active one... the dimmed and disabled pixmaps are constructed + * based on this one. However, don't use this function unless you + * are positive that you don't want to use @ref setIcon. + * + * @param pixmap The active pixmap + */ + // this one is from QButton, so #ifdef-ing it out doesn't break BC + virtual void setPixmap(const QPixmap &pixmap); + + /** + * @deprecated + * Force the button to use this pixmap as the default one rather + * then generating it using effects. + * + * @param pixmap The pixmap to use as the default (normal) one + */ + void setDefaultPixmap(const QPixmap& pixmap); + + /** + * @deprecated + * Force the button to use this pixmap when disabled one rather then + * generating it using effects. + * + * @param pixmap The pixmap to use when disabled + */ + void setDisabledPixmap(const QPixmap& pixmap); +#endif + + /** + * Set the text for this button. The text will be either used as a + * tooltip (IconOnly) or will be along side the icon + * + * @param text The button (or tooltip) text + */ + virtual void setText(const QString &text); + + /** + * Set the icon for this button. The icon will be loaded internally + * with the correct size. This function is preferred over @ref setIconSet + * + * @param icon The name of the icon + */ + virtual void setIcon(const QString &icon); + + /// @since 3.1 + virtual void setIcon( const QPixmap &pixmap ) + { QToolButton::setIcon( pixmap ); } + + /** + * Set the pixmaps for this toolbar button from a QIconSet. + * If you call this you don't need to call any of the other methods + * that set icons or pixmaps. + * @param iconset The iconset to use + */ + virtual void setIconSet( const QIconSet &iconset ); + +#ifndef KDE_NO_COMPAT + /** + * @deprecated + * Set the active icon for this button. The pixmap itself is loaded + * internally based on the icon size... .. the disabled and default + * pixmaps, however will only be constructed if @ref #generate is + * true. This function is preferred over @ref setPixmap + * + * @param icon The name of the active icon + * @param generate If true, then the other icons are automagically + * generated from this one + */ + void setIcon(const QString &icon, bool /*generate*/ ) { setIcon( icon ); } + + /** + * @deprecated + * Force the button to use this icon as the default one rather + * then generating it using effects. + * + * @param icon The icon to use as the default (normal) one + */ + void setDefaultIcon(const QString& icon); + + /** + * @deprecated + * Force the button to use this icon when disabled one rather then + * generating it using effects. + * + * @param icon The icon to use when disabled + */ + void setDisabledIcon(const QString& icon); +#endif + + /** + * Turn this button on or off + * + * @param flag true or false + */ + void on(bool flag = true); + + /** + * Toggle this button + */ + void toggle(); + + /** + * Turn this button into a toggle button or disable the toggle + * aspects of it. This does not toggle the button itself. + * Use @ref toggle() for that. + * + * @param toggle true or false + */ + void setToggle(bool toggle = true); + + /** + * Return a pointer to this button's popup menu (if it exists) + */ + QPopupMenu *popup(); + + /** + * Returns the button's id. + * @since 3.2 + */ + int id() const; + + /** + * Give this button a popup menu. There will not be a delay when + * you press the button. Use @ref setDelayedPopup if you want that + * behavior. + * + * @param p The new popup menu + */ + void setPopup (QPopupMenu *p, bool unused = false); + + /** + * Gives this button a delayed popup menu. + * + * This function allows you to add a delayed popup menu to the button. + * The popup menu is then only displayed when the button is pressed and + * held down for about half a second. + * + * @param p the new popup menu + */ + void setDelayedPopup(QPopupMenu *p, bool unused = false); + + /** + * Turn this button into a radio button + * + * @param f true or false + */ + void setRadio(bool f = true); + + /** + * Toolbar buttons naturally will assume the global styles + * concerning icons, icons sizes, etc. You can use this function to + * explicitely turn this off, if you like. + * + * @param no_style Will disable styles if true + */ + void setNoStyle(bool no_style = true); + +signals: + void clicked(int); + void doubleClicked(int); + void pressed(int); + void released(int); + void toggled(int); + void highlighted(int, bool); + +public slots: + /** + * This slot should be called whenever the toolbar mode has + * potentially changed. This includes such events as text changing, + * orientation changing, etc. + */ + void modeChange(); + virtual void setTextLabel(const QString&, bool tipToo); + +protected: + void paletteChange(const QPalette &); + void leaveEvent(QEvent *e); + void enterEvent(QEvent *e); + void drawButton(QPainter *p); + bool eventFilter (QObject *o, QEvent *e); + void showMenu(); + + /// @since 3.1 + bool isRaised() const; + /// @since 3.1 + bool isActive() const; + /// @since 3.1 + int iconTextMode() const; + +protected slots: + void slotClicked(); + void slotPressed(); + void slotReleased(); + void slotToggled(); + void slotDelayTimeout(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KToolBarButtonPrivate *d; +}; + +/** +* List of @ref KToolBarButton objects. +* @internal +* @version $Id$ +*/ +class KToolBarButtonList : public QIntDict<KToolBarButton> +{ +public: + KToolBarButtonList(); + ~KToolBarButtonList() {} +}; + +#endif diff --git a/microkde/kdeui/ktoolbarhandler.cpp b/microkde/kdeui/ktoolbarhandler.cpp new file mode 100644 index 0000000..7b97233 --- a/dev/null +++ b/microkde/kdeui/ktoolbarhandler.cpp @@ -0,0 +1,253 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "ktoolbarhandler.h" + +#include <qpopupmenu.h> +#include <kapplication.h> +#include <ktoolbar.h> +#include <kmainwindow.h> +#include <klocale.h> +#include <kaction.h> +#include <assert.h> + +namespace +{ + const char *actionListName = "show_menu_and_toolbar_actionlist"; + + const char *guiDescription = "" + "<!DOCTYPE kpartgui><kpartgui name=\"StandardToolBarMenuHandler\">" + "<MenuBar>" + " <Menu name=\"settings\">" + " <ActionList name=\"%1\" />" + " </Menu>" + "</MenuBar>" + "</kpartgui>"; + + const char *resourceFileName = "barhandler.rc"; + + class BarActionBuilder + { + public: + BarActionBuilder( KActionCollection *actionCollection, KMainWindow *mainWindow, QPtrList<KToolBar> &oldToolBarList ) + : m_actionCollection( actionCollection ), m_mainWindow( mainWindow ), m_needsRebuild( false ) + { +/*US + QPtrList<QDockWindow> dockWindows = m_mainWindow->dockWindows(); + QPtrListIterator<QDockWindow> dockWindowIt( dockWindows ); + for ( ; dockWindowIt.current(); ++dockWindowIt ) { + +//US KToolBar *toolBar = dynamic_cast<KToolBar *>( dockWindowIt.current() ); + KToolBar *toolBar = (KToolBar *)( dockWindowIt.current() ); + if ( !toolBar ) + continue; + + if ( oldToolBarList.findRef( toolBar ) == -1 ) + m_needsRebuild = true; + + m_toolBars.append( toolBar ); + } +*/ + if ( !m_needsRebuild ) + m_needsRebuild = ( oldToolBarList.count() != m_toolBars.count() ); + + } + + bool needsRebuild() const { return m_needsRebuild; } + + QPtrList<KAction> create() + { + if ( !m_needsRebuild ) + return QPtrList<KAction>(); + + QPtrListIterator<KToolBar> toolBarIt( m_toolBars ); + for ( ; toolBarIt.current(); ++toolBarIt ) + handleToolBar( toolBarIt.current() ); + + QPtrList<KAction> actions; + + if ( m_toolBarActions.count() == 0 ) + return actions; + + if ( m_toolBarActions.count() == 1 ) { + m_toolBarActions.getFirst()->setText( i18n( "Show Toolbar" ) ); + return m_toolBarActions; + } + + KActionMenu *menuAction = new KActionMenu( i18n( "Toolbars" ), m_actionCollection, "toolbars_submenu_action" ); + + QPtrListIterator<KAction> actionIt( m_toolBarActions ); + for ( ; actionIt.current(); ++actionIt ) + menuAction->insert( actionIt.current() ); + + actions.append( menuAction ); + return actions; + } + + const QPtrList<KToolBar> &toolBars() const { return m_toolBars; } + + private: + void handleToolBar( KToolBar *toolBar ) + { + KAction *action = new KToggleToolBarAction( toolBar, + i18n( "Show %1" ).arg( toolBar->label() ), + m_actionCollection, + toolBar->name() ); + + m_toolBarActions.append( action ); + } + + KActionCollection *m_actionCollection; + KMainWindow *m_mainWindow; + + QPtrList<KToolBar> m_toolBars; + QPtrList<KAction> m_toolBarActions; + + bool m_needsRebuild : 1; + }; +} + +using namespace KDEPrivate; + +ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, const char *name ) + : QObject( mainWindow, name ), KXMLGUIClient( mainWindow ) +{ + init( mainWindow ); +} + +ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name ) + : QObject( parent, name ), KXMLGUIClient( mainWindow ) +{ + init( mainWindow ); +} + +ToolBarHandler::~ToolBarHandler() +{ + m_actions.setAutoDelete( true ); + m_actions.clear(); +} + +KAction *ToolBarHandler::toolBarMenuAction() +{ + assert( m_actions.count() == 1 ); + return m_actions.getFirst(); +} + +void ToolBarHandler::setupActions() +{ +//US if ( !factory() || !m_mainWindow ) + if ( !m_mainWindow ) + return; + + BarActionBuilder builder( actionCollection(), m_mainWindow, m_toolBars ); + + if ( !builder.needsRebuild() ) + return; + + unplugActionList( actionListName ); + + m_actions.setAutoDelete( true ); + + m_actions.clear(); + m_actions.setAutoDelete( false ); + + m_actions = builder.create(); + + /* + for ( QPtrListIterator<KToolBar> toolBarIt( m_toolBars ); + toolBarIt.current(); ++toolBarIt ) + toolBarIt.current()->disconnect( this ); + */ + + m_toolBars = builder.toolBars(); + + /* + for ( QPtrListIterator<KToolBar> toolBarIt( m_toolBars ); + toolBarIt.current(); ++toolBarIt ) + connect( toolBarIt.current(), SIGNAL( destroyed() ), + this, SLOT( setupActions() ) ); + */ + +//US if (kapp && kapp->authorizeKAction("options_show_toolbar")) + plugActionList( actionListName, m_actions ); + + connectToActionContainers(); +} + +/*US +void ToolBarHandler::clientAdded( KXMLGUIClient *client ) +{ + if ( client == this ) + setupActions(); +} +*/ + +void ToolBarHandler::init( KMainWindow *mainWindow ) +{ + d = 0; + m_mainWindow = mainWindow; + +/*US + connect( m_mainWindow->guiFactory(), SIGNAL( clientAdded( KXMLGUIClient * ) ), + this, SLOT( clientAdded( KXMLGUIClient * ) ) ); +*/ + /* re-use an existing resource file if it exists. can happen if the user launches the + * toolbar editor */ + /* + setXMLFile( resourceFileName ); + */ +/*US + if ( domDocument().documentElement().isNull() ) { + + QString completeDescription = QString::fromLatin1( guiDescription ) + .arg( actionListName ); + + setXML( completeDescription, false*/ /*merge*/ /*); + } +*/ +} + +void ToolBarHandler::connectToActionContainers() +{ + QPtrListIterator<KAction> actionIt( m_actions ); + for ( ; actionIt.current(); ++actionIt ) + connectToActionContainer( actionIt.current() ); +} + +void ToolBarHandler::connectToActionContainer( KAction *action ) +{ + uint containerCount = action->containerCount(); + for ( uint i = 0; i < containerCount; ++i ) + connectToActionContainer( action->container( i ) ); +} + +void ToolBarHandler::connectToActionContainer( QWidget *container ) +{ +//US QPopupMenu *popupMenu = dynamic_cast<QPopupMenu *>( container ); + QPopupMenu *popupMenu = (QPopupMenu *)( container ); + if ( !popupMenu ) + return; + + connect( popupMenu, SIGNAL( aboutToShow() ), + this, SLOT( setupActions() ) ); +} + +//US #include "ktoolbarhandler.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/microkde/kdeui/ktoolbarhandler.h b/microkde/kdeui/ktoolbarhandler.h new file mode 100644 index 0000000..a1340ae --- a/dev/null +++ b/microkde/kdeui/ktoolbarhandler.h @@ -0,0 +1,70 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KBARHANDLER_H +#define KBARHANDLER_H + +#include <qobject.h> +#include <qguardedptr.h> +#include <qptrlist.h> +#include <kxmlguiclient.h> +#include <kaction.h> + +class KMainWindow; +class KToolBar; + +namespace KDEPrivate +{ + +/// @since 3.1 +class ToolBarHandler : public QObject, public KXMLGUIClient +{ + Q_OBJECT +public: + ToolBarHandler( KMainWindow *mainWindow, const char *name = 0 ); + ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name = 0 ); + virtual ~ToolBarHandler(); + + KAction *toolBarMenuAction(); + +public slots: + void setupActions(); + +private slots: +//US void clientAdded( KXMLGUIClient *client ); + +private: + void init( KMainWindow *mainWindow ); + void connectToActionContainers(); + void connectToActionContainer( KAction *action ); + void connectToActionContainer( QWidget *container ); + + struct Data; + Data *d; + + QGuardedPtr<KMainWindow> m_mainWindow; + QPtrList<KAction> m_actions; + QPtrList<KToolBar> m_toolBars; +}; + +} // namespace KDEPrivate + +#endif // KBARHANDLER_H + +/* vim: et sw=4 ts=4 + */ diff --git a/microkde/kdeui/kxmlguiclient.cpp b/microkde/kdeui/kxmlguiclient.cpp new file mode 100644 index 0000000..073e30b --- a/dev/null +++ b/microkde/kdeui/kxmlguiclient.cpp @@ -0,0 +1,958 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Simon Hausmann <hausmann@kde.org> + Copyright (C) 2000 Kurt Granroth <granroth@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kxmlguiclient.h" + +/*US +#include "kxmlguifactory.h" +#include "kxmlguibuilder.h" +*/ + +/*US +#include <qdir.h> +#include <qfile.h> +#include <qdom.h> +#include <qtextstream.h> +#include <qregexp.h> +*/ + +//US #include <kinstance.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <kaction.h> +#include <kapplication.h> + +#include <assert.h> + +class KXMLGUIClientPrivate +{ +public: + KXMLGUIClientPrivate() + { +//US m_instance = KGlobal::instance(); +//US m_factory = 0L; + m_parent = 0L; +//US m_builder = 0L; + m_actionCollection = 0; + } + ~KXMLGUIClientPrivate() + { + } + +//US KInstance *m_instance; + +//US QDomDocument m_doc; + KActionCollection *m_actionCollection; +//US QDomDocument m_buildDocument; +//US KXMLGUIFactory *m_factory; + KXMLGUIClient *m_parent; + //QPtrList<KXMLGUIClient> m_supers; + QPtrList<KXMLGUIClient> m_children; +//US KXMLGUIBuilder *m_builder; +//US QString m_xmlFile; +//US QString m_localXMLFile; +}; + +KXMLGUIClient::KXMLGUIClient() +{ + d = new KXMLGUIClientPrivate; +} + +KXMLGUIClient::KXMLGUIClient( KXMLGUIClient *parent ) +{ + d = new KXMLGUIClientPrivate; + parent->insertChildClient( this ); +} + +KXMLGUIClient::~KXMLGUIClient() +{ + if ( d->m_parent ) + d->m_parent->removeChildClient( this ); + + QPtrListIterator<KXMLGUIClient> it( d->m_children ); + for ( ; it.current(); ++it ) { + assert( it.current()->d->m_parent == this ); + it.current()->d->m_parent = 0; + } + + delete d->m_actionCollection; + delete d; +} + +KAction *KXMLGUIClient::action( const char *name ) const +{ + KAction* act = actionCollection()->action( name ); + if ( !act ) { + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) { + act = childIt.current()->actionCollection()->action( name ); + if ( act ) + break; + } + } + return act; +} + +KActionCollection *KXMLGUIClient::actionCollection() const +{ + if ( !d->m_actionCollection ) + d->m_actionCollection = new KActionCollection( 0, 0, + "KXMLGUILClient-KActionCollection" ); + return d->m_actionCollection; +} + +/*US +KAction *KXMLGUIClient::action( const QDomElement &element ) const +{ + static const QString &attrName = KGlobal::staticQString( "name" ); + return actionCollection()->action( element.attribute( attrName ).latin1() ); +} + +KInstance *KXMLGUIClient::instance() const +{ + return d->m_instance; +} + +QDomDocument KXMLGUIClient::domDocument() const +{ + return d->m_doc; +} + +QString KXMLGUIClient::xmlFile() const +{ + return d->m_xmlFile; +} + +QString KXMLGUIClient::localXMLFile() const +{ + if ( !d->m_localXMLFile.isEmpty() ) + return d->m_localXMLFile; + + if ( d->m_xmlFile[0] == '/' ) + return QString::null; // can't save anything here + + return locateLocal( "data", QString::fromLatin1( instance()->instanceName() + '/' ) + d->m_xmlFile ); +} + + +void KXMLGUIClient::reloadXML() +{ + QString file( xmlFile() ); + if ( !file.isEmpty() ) + setXMLFile( file ); +} + +void KXMLGUIClient::setInstance( KInstance *instance ) +{ + d->m_instance = instance; + actionCollection()->setInstance( instance ); + if ( d->m_builder ) + d->m_builder->setBuilderClient( this ); +} + +void KXMLGUIClient::setXMLFile( const QString& _file, bool merge, bool setXMLDoc ) +{ + // store our xml file name + if ( !_file.isNull() ) { + d->m_xmlFile = _file; + actionCollection()->setXMLFile( _file ); + } + + if ( !setXMLDoc ) + return; + + QString file = _file; + if ( file[0] != '/' ) + { + QString doc; + + QString filter = QString::fromLatin1( instance()->instanceName() + '/' ) + _file; + + QStringList allFiles = instance()->dirs()->findAllResources( "data", filter ) + instance()->dirs()->findAllResources( "data", _file ); + + file = findMostRecentXMLFile( allFiles, doc ); + + if ( file.isEmpty() ) + { + // this might or might not be an error. for the time being, + // let's treat this as if it isn't a problem and the user just + // wants the global standards file + setXML( QString::null, true ); + return; + } + else if ( !doc.isEmpty() ) + { + setXML( doc, merge ); + return; + } + } + + QString xml = KXMLGUIFactory::readConfigFile( file ); + setXML( xml, merge ); +} + +void KXMLGUIClient::setLocalXMLFile( const QString &file ) +{ + d->m_localXMLFile = file; +} + +void KXMLGUIClient::setXML( const QString &document, bool merge ) +{ + QDomDocument doc; + doc.setContent( document ); + setDOMDocument( doc, merge ); +} + +void KXMLGUIClient::setDOMDocument( const QDomDocument &document, bool merge ) +{ + if ( merge ) + { + QDomElement base = d->m_doc.documentElement(); + + QDomElement e = document.documentElement(); + KXMLGUIFactory::removeDOMComments( e ); + + // merge our original (global) xml with our new one + mergeXML(base, e, actionCollection()); + + // reassign our pointer as mergeXML might have done something + // strange to it + base = d->m_doc.documentElement(); + + // we want some sort of failsafe.. just in case + if ( base.isNull() ) + d->m_doc = document; + } + else + { + d->m_doc = document; + KXMLGUIFactory::removeDOMComments( d->m_doc ); + } + + setXMLGUIBuildDocument( QDomDocument() ); +} +*/ + +/*US +bool KXMLGUIClient::mergeXML( QDomElement &base, const QDomElement &additive, KActionCollection *actionCollection ) +{ + static const QString &tagAction = KGlobal::staticQString( "Action" ); + static const QString &tagMerge = KGlobal::staticQString( "Merge" ); + static const QString &tagSeparator = KGlobal::staticQString( "Separator" ); + static const QString &attrName = KGlobal::staticQString( "name" ); + static const QString &attrAppend = KGlobal::staticQString( "append" ); + static const QString &attrWeakSeparator = KGlobal::staticQString( "weakSeparator" ); + static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" ); + static const QString &tagText = KGlobal::staticQString( "text" ); + static const QString &attrAlreadyVisited = KGlobal::staticQString( "alreadyVisited" ); + static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" ); + static const QString &attrOne = KGlobal::staticQString( "1" ); + + // there is a possibility that we don't want to merge in the + // additive.. rather, we might want to *replace* the base with the + // additive. this can be for any container.. either at a file wide + // level or a simple container level. we look for the 'noMerge' + // tag, in any event and just replace the old with the new + if ( additive.attribute(attrNoMerge) == attrOne ) // ### use toInt() instead? (Simon) + { + base.parentNode().replaceChild(additive, base); + return true; + } + + QString tag; + + QDomElement e = base.firstChild().toElement(); + // iterate over all elements in the container (of the global DOM tree) + while ( !e.isNull() ) + { + tag = e.tagName(); + + // if there's an action tag in the global tree and the action is + // not implemented, then we remove the element + if ( tag == tagAction ) + { + QCString name = e.attribute( attrName ).utf8(); // WABA + if ( !actionCollection->action( name ) || + (kapp && !kapp->authorizeKAction(name))) + { + // remove this child as we aren't using it + QDomElement oldChild = e; + e = e.nextSibling().toElement(); + base.removeChild( oldChild ); + continue; + } + } + + // if there's a separator defined in the global tree, then add an + // attribute, specifying that this is a "weak" separator + else if ( tag == tagSeparator ) + { + e.setAttribute( attrWeakSeparator, (uint)1 ); + + // okay, hack time. if the last item was a weak separator OR + // this is the first item in a container, then we nuke the + // current one + QDomElement prev = e.previousSibling().toElement(); + if ( prev.isNull() || + ( prev.tagName() == tagSeparator && !prev.attribute( attrWeakSeparator ).isNull() ) || + ( prev.tagName() == tagText ) ) + { + // the previous element was a weak separator or didn't exist + QDomElement oldChild = e; + e = e.nextSibling().toElement(); + base.removeChild( oldChild ); + continue; + } + } + + // the MergeLocal tag lets us specify where non-standard elements + // of the local tree shall be merged in. After inserting the + // elements we delete this element + else if ( tag == tagMergeLocal ) + { + QDomElement currElement = e; + + // switch our iterator "e" to the next sibling, so that we don't + // process the local tree's inserted items! + e = e.nextSibling().toElement(); + + QDomElement it = additive.firstChild().toElement(); + while ( !it.isNull() ) + { + QDomElement newChild = it; + + it = it.nextSibling().toElement(); + + if ( newChild.tagName() == tagText ) + continue; + + if ( newChild.attribute( attrAlreadyVisited ) == attrOne ) + continue; + + QString itAppend( newChild.attribute( attrAppend ) ); + QString elemName( currElement.attribute( attrName ) ); + + if ( ( itAppend.isNull() && elemName.isEmpty() ) || + ( itAppend == elemName ) ) + { + // first, see if this new element matches a standard one in + // the global file. if it does, then we skip it as it will + // be merged in, later + QDomElement matchingElement = findMatchingElement( newChild, base ); + if ( matchingElement.isNull() || newChild.tagName() == tagSeparator ) + base.insertBefore( newChild, currElement ); + } + } + + base.removeChild( currElement ); + continue; + } + + // in this last case we check for a separator tag and, if not, we + // can be sure that its a container --> proceed with child nodes + // recursively and delete the just proceeded container item in + // case its empty (if the recursive call returns true) + else if ( tag != tagMerge ) + { + // handle the text tag + if ( tag == tagText ) + { + e = e.nextSibling().toElement(); + continue; + } + + QDomElement matchingElement = findMatchingElement( e, additive ); + + QDomElement currElement = e; + e = e.nextSibling().toElement(); + + if ( !matchingElement.isNull() ) + { + matchingElement.setAttribute( attrAlreadyVisited, (uint)1 ); + + if ( mergeXML( currElement, matchingElement, actionCollection ) ) + { + base.removeChild( currElement ); + continue; + } + + // Merge attributes + QDomNamedNodeMap attribs = matchingElement.attributes(); + for(uint i = 0; i < attribs.count(); i++) + { + QDomNode node = attribs.item(i); + currElement.setAttribute(node.nodeName(), node.nodeValue()); + } + + continue; + } + else + { + // this is an important case here! We reach this point if the + // "local" tree does not contain a container definition for + // this container. However we have to call mergeXML recursively + // and make it check if there are actions implemented for this + // container. *If* none, then we can remove this container now + if ( mergeXML( currElement, QDomElement(), actionCollection ) ) + base.removeChild( currElement ); + continue; + } + } + + //I think this can be removed ;-) + e = e.nextSibling().toElement(); + } + + //here we append all child elements which were not inserted + //previously via the LocalMerge tag + e = additive.firstChild().toElement(); + while ( !e.isNull() ) + { + QDomElement matchingElement = findMatchingElement( e, base ); + + if ( matchingElement.isNull() ) + { + QDomElement newChild = e; + e = e.nextSibling().toElement(); + base.appendChild( newChild ); + } + else + e = e.nextSibling().toElement(); + } + + // do one quick check to make sure that the last element was not + // a weak separator + QDomElement last = base.lastChild().toElement(); + if ( (last.tagName() == tagSeparator) && (!last.attribute( attrWeakSeparator ).isNull()) ) + { + base.removeChild( base.lastChild() ); + } + + // now we check if we are empty (in which case we return "true", to + // indicate the caller that it can delete "us" (the base element + // argument of "this" call) + bool deleteMe = true; + e = base.firstChild().toElement(); + for ( ; !e.isNull(); e = e.nextSibling().toElement() ) + { + tag = e.tagName(); + + if ( tag == tagAction ) + { + // if base contains an implemented action, then we must not get + // deleted (note that the actionCollection contains both, + // "global" and "local" actions + if ( actionCollection->action( e.attribute( attrName ).utf8() ) ) + { + deleteMe = false; + break; + } + } + else if ( tag == tagSeparator ) + { + // if we have a separator which has *not* the weak attribute + // set, then it must be owned by the "local" tree in which case + // we must not get deleted either + QString weakAttr = e.attribute( attrWeakSeparator ); + if ( weakAttr.isEmpty() || weakAttr.toInt() != 1 ) + { + deleteMe = false; + break; + } + } + + // in case of a merge tag we have unlimited lives, too ;-) + else if ( tag == tagMerge ) + { +// deleteMe = false; +// break; + continue; + } + + // a text tag is NOT enough to spare this container + else if ( tag == tagText ) + { + continue; + } + + // what's left are non-empty containers! *don't* delete us in this + // case (at this position we can be *sure* that the container is + // *not* empty, as the recursive call for it was in the first loop + // which deleted the element in case the call returned "true" + else + { + deleteMe = false; + break; + } + } + + return deleteMe; +} + +QDomElement KXMLGUIClient::findMatchingElement( const QDomElement &base, const QDomElement &additive ) +{ + static const QString &tagAction = KGlobal::staticQString( "Action" ); + static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" ); + static const QString &attrName = KGlobal::staticQString( "name" ); + + QDomElement e = additive.firstChild().toElement(); + for ( ; !e.isNull(); e = e.nextSibling().toElement() ) + { + // skip all action and merge tags as we will never use them + if ( ( e.tagName() == tagAction ) || ( e.tagName() == tagMergeLocal ) ) + { + continue; + } + + // now see if our tags are equivalent + if ( ( e.tagName() == base.tagName() ) && + ( e.attribute( attrName ) == base.attribute( attrName ) ) ) + { + return e; + } + } + + // nope, return a (now) null element + return e; +} + +void KXMLGUIClient::conserveMemory() +{ + d->m_doc = QDomDocument(); + d->m_buildDocument = QDomDocument(); +} + +void KXMLGUIClient::setXMLGUIBuildDocument( const QDomDocument &doc ) +{ + d->m_buildDocument = doc; +} + +QDomDocument KXMLGUIClient::xmlguiBuildDocument() const +{ + return d->m_buildDocument; +} +*/ + +/*US +void KXMLGUIClient::setFactory( KXMLGUIFactory *factory ) +{ + d->m_factory = factory; +} + +KXMLGUIFactory *KXMLGUIClient::factory() const +{ + return d->m_factory; +} +*/ +KXMLGUIClient *KXMLGUIClient::parentClient() const +{ + return d->m_parent; +} + +void KXMLGUIClient::insertChildClient( KXMLGUIClient *child ) +{ + if ( child->d->m_parent ) + child->d->m_parent->removeChildClient( child ); + d->m_children.append( child ); + child->d->m_parent = this; +} + +void KXMLGUIClient::removeChildClient( KXMLGUIClient *child ) +{ + assert( d->m_children.containsRef( child ) ); + d->m_children.removeRef( child ); + child->d->m_parent = 0; +} + +/*bool KXMLGUIClient::addSuperClient( KXMLGUIClient *super ) +{ + if ( d->m_supers.contains( super ) ) + return false; + d->m_supers.append( super ); + return true; +}*/ + +const QPtrList<KXMLGUIClient> *KXMLGUIClient::childClients() +{ + return &d->m_children; +} +/*US +void KXMLGUIClient::setClientBuilder( KXMLGUIBuilder *builder ) +{ + d->m_builder = builder; + if ( builder ) + builder->setBuilderInstance( instance() ); +} + +KXMLGUIBuilder *KXMLGUIClient::clientBuilder() const +{ + return d->m_builder; +} +*/ + +void KXMLGUIClient::plugActionList( const QString &name, const QPtrList<KAction> &actionList ) +{ +/*US + if ( !d->m_factory ) + return; + + d->m_factory->plugActionList( this, name, actionList ); +*/ +} + +void KXMLGUIClient::unplugActionList( const QString &name ) +{ +/*US + if ( !d->m_factory ) + return; + + d->m_factory->unplugActionList( this, name ); +*/ +} + +/*US +QString KXMLGUIClient::findMostRecentXMLFile( const QStringList &files, QString &doc ) +{ + + QValueList<DocStruct> allDocuments; + + QStringList::ConstIterator it = files.begin(); + QStringList::ConstIterator end = files.end(); + for (; it != end; ++it ) + { + //kdDebug() << "KXMLGUIClient::findMostRecentXMLFile " << *it << endl; + QString data = KXMLGUIFactory::readConfigFile( *it ); + DocStruct d; + d.file = *it; + d.data = data; + allDocuments.append( d ); + } + + QValueList<DocStruct>::Iterator best = allDocuments.end(); + uint bestVersion = 0; + + QValueList<DocStruct>::Iterator docIt = allDocuments.begin(); + QValueList<DocStruct>::Iterator docEnd = allDocuments.end(); + for (; docIt != docEnd; ++docIt ) + { + QString versionStr = findVersionNumber( (*docIt).data ); + if ( versionStr.isEmpty() ) + continue; + + bool ok = false; + uint version = versionStr.toUInt( &ok ); + if ( !ok ) + continue; + //kdDebug() << "FOUND VERSION " << version << endl; + + if ( version > bestVersion ) + { + best = docIt; + //kdDebug() << "best version is now " << version << endl; + bestVersion = version; + } + } + + if ( best != docEnd ) + { + if ( best != allDocuments.begin() ) + { + QValueList<DocStruct>::Iterator local = allDocuments.begin(); + + // load the local document and extract the action properties + QDomDocument document; + document.setContent( (*local).data ); + + ActionPropertiesMap properties = extractActionProperties( document ); + + // in case the document has a ActionProperties section + // we must not delete it but copy over the global doc + // to the local and insert the ActionProperties section + if ( !properties.isEmpty() ) + { + // now load the global one with the higher version number + // into memory + document.setContent( (*best).data ); + // and store the properties in there + storeActionProperties( document, properties ); + + (*local).data = document.toString(); + // make sure we pick up the new local doc, when we return later + best = local; + + // write out the new version of the local document + QFile f( (*local).file ); + if ( f.open( IO_WriteOnly ) ) + { + QCString utf8data = (*local).data.utf8(); + f.writeBlock( utf8data.data(), utf8data.length() ); + f.close(); + } + } + else + { + QString f = (*local).file; + QString backup = f + QString::fromLatin1( ".backup" ); + QDir dir; + dir.rename( f, backup ); + } + } + doc = (*best).data; + return (*best).file; + } + else if ( files.count() > 0 ) + { + //kdDebug() << "returning first one..." << endl; + doc = (*allDocuments.begin()).data; + return (*allDocuments.begin()).file; + } + + return QString::null; +} + + + +QString KXMLGUIClient::findVersionNumber( const QString &xml ) +{ + enum { ST_START, ST_AFTER_OPEN, ST_AFTER_GUI, + ST_EXPECT_VERSION, ST_VERSION_NUM} state = ST_START; + for (unsigned int pos = 0; pos < xml.length(); pos++) + { + switch (state) + { + case ST_START: + if (xml[pos] == '<') + state = ST_AFTER_OPEN; + break; + case ST_AFTER_OPEN: + { + //Jump to gui.. + int guipos = xml.find("gui", pos, false); + if (guipos == -1) + return QString::null; //Reject + + pos = guipos + 2; //Position at i, so we're moved ahead to the next character by the ++; + state = ST_AFTER_GUI; + break; + } + case ST_AFTER_GUI: + state = ST_EXPECT_VERSION; + break; + case ST_EXPECT_VERSION: + { + int verpos = xml.find("version=\"", pos, false ); + if (verpos == -1) + return QString::null; //Reject + + pos = verpos + 8; //v = 0, e = +1, r = +2, s = +3 , i = +4, o = +5, n = +6, = = +7, " = + 8 + state = ST_VERSION_NUM; + break; + } + case ST_VERSION_NUM: + { + unsigned int endpos; + for (endpos = pos; endpos < xml.length(); endpos++) + { + if (xml[endpos].unicode() >= '0' && xml[endpos].unicode() <= '9') + continue; //Number.. + if (xml[endpos].unicode() == '"') //End of parameter + break; + else //This shouldn't be here.. + { + endpos = xml.length(); + } + } + + if (endpos != pos && endpos < xml.length() ) + { + QString matchCandidate = xml.mid(pos, endpos - pos); //Don't include " ". + return matchCandidate; + } + + state = ST_EXPECT_VERSION; //Try to match a well-formed version.. + break; + } //case.. + } //switch + } //for + + return QString::null; +} + +KXMLGUIClient::ActionPropertiesMap KXMLGUIClient::extractActionProperties( const QDomDocument &doc ) +{ + ActionPropertiesMap properties; + + QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement(); + + if ( actionPropElement.isNull() ) + return properties; + + QDomNode n = actionPropElement.firstChild(); + for (; !n.isNull(); n = n.nextSibling() ) + { + QDomElement e = n.toElement(); + if ( e.isNull() ) + continue; + + if ( e.tagName().lower() != "action" ) + continue; + + QString actionName = e.attribute( "name" ); + + if ( actionName.isEmpty() ) + continue; + + QMap<QString, QMap<QString, QString> >::Iterator propIt = properties.find( actionName ); + if ( propIt == properties.end() ) + propIt = properties.insert( actionName, QMap<QString, QString>() ); + + QDomNamedNodeMap attributes = e.attributes(); + for ( uint i = 0; i < attributes.length(); ++i ) + { + QDomAttr attr = attributes.item( i ).toAttr(); + + if ( attr.isNull() ) + continue; + + QString name = attr.name(); + + if ( name == "name" || name.isEmpty() ) + continue; + + (*propIt)[ name ] = attr.value(); + } + + } + + return properties; +} + +void KXMLGUIClient::storeActionProperties( QDomDocument &doc, const ActionPropertiesMap &properties ) +{ + QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement(); + + if ( actionPropElement.isNull() ) + { + actionPropElement = doc.createElement( "ActionProperties" ); + doc.documentElement().appendChild( actionPropElement ); + } + + while ( !actionPropElement.firstChild().isNull() ) + actionPropElement.removeChild( actionPropElement.firstChild() ); + + ActionPropertiesMap::ConstIterator it = properties.begin(); + ActionPropertiesMap::ConstIterator end = properties.end(); + for (; it != end; ++it ) + { + QDomElement action = doc.createElement( "Action" ); + action.setAttribute( "name", it.key() ); + actionPropElement.appendChild( action ); + + QMap<QString, QString> attributes = (*it); + QMap<QString, QString>::ConstIterator attrIt = attributes.begin(); + QMap<QString, QString>::ConstIterator attrEnd = attributes.end(); + for (; attrIt != attrEnd; ++attrIt ) + action.setAttribute( attrIt.key(), attrIt.data() ); + } +} +*/ + +void KXMLGUIClient::addStateActionEnabled(const QString& state, + const QString& action) +{ + StateChange stateChange = getActionsToChangeForState(state); + + stateChange.actionsToEnable.append( action ); + //kdDebug() << "KXMLGUIClient::addStateActionEnabled( " << state << ", " << action << ")" << endl; + + m_actionsStateMap.replace( state, stateChange ); +} + + +void KXMLGUIClient::addStateActionDisabled(const QString& state, + const QString& action) +{ + StateChange stateChange = getActionsToChangeForState(state); + + stateChange.actionsToDisable.append( action ); + //kdDebug() << "KXMLGUIClient::addStateActionDisabled( " << state << ", " << action << ")" << endl; + + m_actionsStateMap.replace( state, stateChange ); +} + + +KXMLGUIClient::StateChange KXMLGUIClient::getActionsToChangeForState(const QString& state) +{ + return m_actionsStateMap[state]; +} + + +void KXMLGUIClient::stateChanged(const QString &newstate, KXMLGUIClient::ReverseStateChange reverse) +{ + StateChange stateChange = getActionsToChangeForState(newstate); + + bool setTrue = (reverse == StateNoReverse); + bool setFalse = !setTrue; + + // Enable actions which need to be enabled... + // + for ( QStringList::Iterator it = stateChange.actionsToEnable.begin(); + it != stateChange.actionsToEnable.end(); ++it ) { + + KAction *action = actionCollection()->action((*it).latin1()); + if (action) action->setEnabled(setTrue); + } + + // and disable actions which need to be disabled... + // + for ( QStringList::Iterator it = stateChange.actionsToDisable.begin(); + it != stateChange.actionsToDisable.end(); ++it ) { + + KAction *action = actionCollection()->action((*it).latin1()); + if (action) action->setEnabled(setFalse); + } + +} +/*US +void KXMLGUIClient::beginXMLPlug( QWidget *w ) +{ + actionCollection()->beginXMLPlug( w ); + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) + childIt.current()->actionCollection()->beginXMLPlug( w ); +} + +void KXMLGUIClient::endXMLPlug() +{ + actionCollection()->endXMLPlug(); + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) + childIt.current()->actionCollection()->endXMLPlug(); +} + +void KXMLGUIClient::prepareXMLUnplug( QWidget * ) +{ + actionCollection()->prepareXMLUnplug(); + QPtrListIterator<KXMLGUIClient> childIt( d->m_children ); + for (; childIt.current(); ++childIt ) + childIt.current()->actionCollection()->prepareXMLUnplug(); +} +*/ +void KXMLGUIClient::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } diff --git a/microkde/kdeui/kxmlguiclient.h b/microkde/kdeui/kxmlguiclient.h new file mode 100644 index 0000000..cd74c8e --- a/dev/null +++ b/microkde/kdeui/kxmlguiclient.h @@ -0,0 +1,361 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Simon Hausmann <hausmann@kde.org> + Copyright (C) 2000 Kurt Granroth <granroth@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef _KXMLGUICLIENT_H +#define _KXMLGUICLIENT_H + + +//US #include <qdom.h> +#include <qptrlist.h> +#include <qmap.h> +#include <qstringlist.h> + +class QWidget; +class KAction; +class KActionCollection; +class KInstance; + +class KXMLGUIClientPrivate; +class KXMLGUIFactory; +class KXMLGUIBuilder; + +/** + * + * A KXMLGUIClient can be used with @ref KXMLGUIFactory to create a + * GUI from actions and an XML document, and can be dynamically merged + * with other KXMLGUIClients. + */ +class KXMLGUIClient +{ + friend class KEditToolbarWidget; // for setXMLFile(3 args) +public: + /** + * Constructs a KXMLGUIClient which can be used with a + * @ref KXMLGUIFactory to create a GUI from actions and an XML document, and + * which can be dynamically merged with other KXMLGUIClients. + */ + KXMLGUIClient(); + + /** + * Constructs a KXMLGUIClient which can be used with a @ref KXMLGUIFactory + * to create a GUI from actions and an XML document, + * and which can be dynamically merged with other KXMLGUIClients. + * + * This constructor takes an additional @p parent argument, which makes + * the client a child client of the parent. + * + * Child clients are automatically added to the GUI if the parent is added. + * + */ + KXMLGUIClient( KXMLGUIClient *parent ); + + /** + * Destructs the KXMLGUIClient. + */ + virtual ~KXMLGUIClient(); + + /** + * Retrieves an action of the client by name. If not found, it looks in its child clients. + * This method is provided for convenience, as it uses @ref #actionCollection() + * to get the action object. + */ + KAction* action( const char* name ) const; + + /** + * Retrieves an action for a given @ref QDomElement. The default + * implementation uses the "name" attribute to query the action + * object via the other action() method. + */ +//US virtual KAction *action( const QDomElement &element ) const; + + /** + * Retrieves the entire action collection for the GUI client + */ + virtual KActionCollection* actionCollection() const; + + /** + * @return The instance (@ref KInstance) for this part. + */ +//US virtual KInstance *instance() const; + + /** + * @return The parsed XML in a @ref QDomDocument, set by @ref + * setXMLFile() or @ref setXML(). + * This document describes the layout of the GUI. + */ +//US virtual QDomDocument domDocument() const; + + /** + * This will return the name of the XML file as set by @ref #setXMLFile(). + * If @ref #setXML() is used directly, then this will return NULL. + * + * The filename that this returns is obvious for components as each + * component has exactly one XML file. In non-components, however, + * there are usually two: the global file and the local file. This + * function doesn't really care about that, though. It will always + * return the last XML file set. This, in almost all cases, will + * be the local XML file. + * + * @return The name of the XML file or QString::null + */ +//US virtual QString xmlFile() const; + +//US virtual QString localXMLFile() const; + + /** + * @internal + */ +//US void setXMLGUIBuildDocument( const QDomDocument &doc ); + /** + * @internal + */ +//US QDomDocument xmlguiBuildDocument() const; + + /** + * This method is called by the @ref KXMLGUIFactory as soon as the client + * is added to the KXMLGUIFactory's GUI. + */ +//US void setFactory( KXMLGUIFactory *factory ); + /** + * Retrieves a pointer to the @ref KXMLGUIFactory this client is + * associated with (will return 0L if the client's GUI has not been built + * by a KXMLGUIFactory. + */ +//US KXMLGUIFactory *factory() const; + + /** + * KXMLGUIClients can form a simple child/parent object tree. This + * method returns a pointer to the parent client or 0L if it has no + * parent client assigned. + */ + KXMLGUIClient *parentClient() const; + + /** + * Use this method to make a client a child client of another client. + * Usually you don't need to call this method, as it is called + * automatically when using the second constructor, which takes a + * arent argument. + */ + void insertChildClient( KXMLGUIClient *child ); + + /** + * Removes the given @p child from the client's children list. + */ + void removeChildClient( KXMLGUIClient *child ); + + /** + * Retrieves a list of all child clients. + */ + const QPtrList<KXMLGUIClient> *childClients(); + + /** + * A client can have an own @ref KXMLGUIBuilder. + * Use this method to assign your builder instance to the client (so that the + * @ref KXMLGUIFactory can use it when building the client's GUI) + * + * Client specific guibuilders are useful if you want to create + * custom container widgets for your GUI. + */ +//US void setClientBuilder( KXMLGUIBuilder *builder ); + + /** + * Retrieves the client's GUI builder or 0L if no client specific + * builder has been assigned via @ref #setClientBuilder() + */ +//US KXMLGUIBuilder *clientBuilder() const; + + /** + * Forces this client to re-read its XML resource file. This is + * intended to be used when you know that the resource file has + * changed and you will soon be rebuilding the GUI. It has no + * useful effect with non-KParts GUIs, so don't bother using it + * unless your app is component based. + */ +//US void reloadXML(); + + /** + * ActionLists are a way for XMLGUI to support dynamic lists of + * actions. E.g. if you are writing a file manager, and there is a + * menu file whose contents depend on the mimetype of the file that + * is selected, then you can achieve this using ActionLists. It + * works as follows: + * In your xxxui.rc file ( the one that you set in @ref setXMLFile() + * ), you put an <ActionList name="xxx"> tag. E.g. + * \verbatim + * <kpartgui name="xxx_part" version="1"> + * <MenuBar> + * <Menu name="file"> + * ... <!-- some useful actions--> + * <ActionList name="xxx_file_actionlist" /> + * ... <!-- even more useful actions--> + * </Menu> + * ... + * </MenuBar> + * </kpartgui> + * \endverbatim + * + * This tag will get expanded to a list of actions. In the example + * above ( a file manager with a dynamic file menu ), you would call + * \code + * QPtrList<KAction> file_actions; + * for( ... ) + * if( ... ) + * file_actions.append( cool_action ); + * unplugActionList( "xxx_file_actionlist" ); + * plugActionList( "xxx_file_actionlist", file_actions ); + * \endcode + * every time a file is selected, unselected or ... + * + * \note You should not call createGUI() after calling this + * function. In fact, that would remove the newly added + * actionlists again... + * \note Forgetting to call unplugActionList() before + * plugActionList() would leave the previous actions in the + * menu too.. + */ + void plugActionList( const QString &name, const QPtrList<KAction> &actionList ); + + /** + * The complement of \ref plugActionList() ... + */ + void unplugActionList( const QString &name ); + +//US static QString findMostRecentXMLFile( const QStringList &files, QString &doc ); + + void addStateActionEnabled(const QString& state, const QString& action); + + void addStateActionDisabled(const QString& state, const QString& action); + + enum ReverseStateChange { StateNoReverse, StateReverse }; + struct StateChange + { + QStringList actionsToEnable; + QStringList actionsToDisable; + }; + + StateChange getActionsToChangeForState(const QString& state); + + /// @since 3.1 +//US void beginXMLPlug( QWidget * ); + /// @since 3.1 +//US void endXMLPlug(); + /// @since 3.1 +//US void prepareXMLUnplug( QWidget * ); + +protected: + /** + * Returns true if client was added to super client list. + * Returns false if client was already in list. + */ + //bool addSuperClient( KXMLGUIClient * ); + + /** + * Sets the instance (@ref KInstance) for this part. + * + * Call this first in the inherited class constructor. + * (At least before @ref setXMLFile().) + */ +//US virtual void setInstance( KInstance *instance ); + + /** + * Sets the name of the rc file containing the XML for the part. + * + * Call this in the Part-inherited class constructor. + * + * @param file Either an absolute path for the file, or simply the + * filename, which will then be assumed to be installed + * in the "data" resource, under a directory named like + * the instance. + * @param setXML Specify whether to call setXML. Default is true. + * and the DOM document at once. + **/ +//US virtual void setXMLFile( const QString& file, bool merge = false, bool setXMLDoc = true ); + +//US virtual void setLocalXMLFile( const QString &file ); + + /** + * Sets the XML for the part. + * + * Call this in the Part-inherited class constructor if you + * don't call @ref setXMLFile(). + **/ +//US virtual void setXML( const QString &document, bool merge = false ); + + /** + * Sets the Document for the part, describing the layout of the GUI. + * + * Call this in the Part-inherited class constructor if you don't call + * @ref setXMLFile or @ref setXML . + */ +//US virtual void setDOMDocument( const QDomDocument &document, bool merge = false ); + + /** + * This function will attempt to give up some memory after the GUI + * is built. It should never be used in apps where the GUI may be + * rebuilt at some later time (components, for instance). + */ +//US virtual void conserveMemory(); + + /** + * Actions can collectively be assigned a "State". To accomplish this + * the respective actions are tagged as <enable> or <disable> in + * a <State> </State> group of the XMLfile. During program execution the + * programmer can call stateChanged() to set actions to a defined state. + * + * @param newstate Name of a State in the XMLfile. + * @param reverse If the flag reverse is set to StateReverse, the State is reversed. + * (actions to be enabled will be disabled and action to be disabled will be enabled) + * Default is reverse=false. + */ + virtual void stateChanged(const QString &newstate, ReverseStateChange reverse = StateNoReverse); + + // Use this one for KDE 4.0 + //virtual void stateChanged(const QString &newstate, bool reverse = false); + +private: +/*US + struct DocStruct + { + QString file; + QString data; + }; + + bool mergeXML( QDomElement &base, const QDomElement &additive, + KActionCollection *actionCollection ); + + QDomElement findMatchingElement( const QDomElement &base, + const QDomElement &additive ); +*/ + typedef QMap<QString, QMap<QString, QString> > ActionPropertiesMap; + +//US static ActionPropertiesMap extractActionProperties( const QDomDocument &doc ); + +//US static void storeActionProperties( QDomDocument &doc, const ActionPropertiesMap &properties ); + +//US static QString findVersionNumber( const QString &_xml ); + + // Actions to enable/disable on a state change + QMap<QString,StateChange> m_actionsStateMap; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KXMLGUIClientPrivate *d; +}; + +#endif diff --git a/microkde/kdialog.cpp b/microkde/kdialog.cpp new file mode 100644 index 0000000..3d62cdd --- a/dev/null +++ b/microkde/kdialog.cpp @@ -0,0 +1,17 @@ + +#include <kdialog.h> +#include <qapp.h> + + +KDialog::KDialog( QWidget *parent, const char *name, bool modal ) : + QDialog( parent, name, modal ) +{ + ; + +} + +int KDialog::spacingHint() { return 3; } +int KDialog::marginHint() { return 3; } + +int KDialog::spacingHintSmall() { if (QApplication::desktop()->width() < 700 ) return 1;else return 3; } +int KDialog::marginHintSmall() { if (QApplication::desktop()->width() < 700 ) return 1;else return 3; } diff --git a/microkde/kdialog.h b/microkde/kdialog.h new file mode 100644 index 0000000..703d268 --- a/dev/null +++ b/microkde/kdialog.h @@ -0,0 +1,18 @@ +#ifndef MINIKDE_KDIALOG_H +#define MINIKDE_KDIALOG_H + +#include <qdialog.h> + +class KDialog : public QDialog +{ + Q_OBJECT + public: + KDialog( QWidget *parent=0, const char *name=0, bool modal=true ); + + static int spacingHint(); + static int marginHint(); + static int spacingHintSmall(); + static int marginHintSmall(); +}; + +#endif diff --git a/microkde/kdialogbase.cpp b/microkde/kdialogbase.cpp new file mode 100644 index 0000000..2ea2053 --- a/dev/null +++ b/microkde/kdialogbase.cpp @@ -0,0 +1,278 @@ +#include <qtabwidget.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qframe.h> + + +#include "klocale.h" +#include "kdebug.h" + +#include "kdialogbase.h" + +KDialogBase::KDialogBase() +{ +} + +KDialogBase::KDialogBase( QWidget *parent, const char *name, bool modal, + const QString &caption, + int buttonMask, ButtonCode defaultButton, + bool separator, + const QString &user1, + const QString &user2, + const QString &user3) : + KDialog( parent, name, modal ) +{ + init( caption, buttonMask, user1, user2 ); + if (findButton( defaultButton ) ) + (findButton( defaultButton ) )->setFocus(); + +} + +KDialogBase::KDialogBase( int dialogFace, const QString &caption, + int buttonMask, ButtonCode defaultButton, + QWidget *parent, const char *name, bool modal, + bool separator, + const QString &user1, + const QString &user2, + const QString &user3) : + KDialog( parent, name, modal ) +{ + init( caption, buttonMask, user1, user2 ); + if (findButton( defaultButton ) ) + (findButton( defaultButton ) )->setFocus(); + +} + +KDialogBase::~KDialogBase() +{ +} + +void KDialogBase::init( const QString &caption, int buttonMask, + const QString &user1 ,const QString &user2 ) +{ + mMainWidget = 0; + mTabWidget = 0; + mPlainPage = 0; + mTopLayout = 0; + if ( !caption.isEmpty() ) { + setCaption( caption ); + } + + if ( buttonMask & User1 ) { + mUser1Button = new QPushButton( user1, this ); + connect( mUser1Button, SIGNAL( clicked() ), SLOT( slotUser1() ) ); + } else { + mUser1Button = 0; + } + if ( buttonMask & User2 ) { + mUser2Button = new QPushButton( user2, this ); + connect( mUser2Button, SIGNAL( clicked() ), SLOT( slotUser2() ) ); + } else { + mUser2Button = 0; + } + + if ( buttonMask & Ok ) { + mOkButton = new QPushButton( i18n("Ok"), this ); + connect( mOkButton, SIGNAL( clicked() ), SLOT( slotOk() ) ); + } else { + mOkButton = 0; + } + + if ( buttonMask & Apply ) { + mApplyButton = new QPushButton( i18n("Apply"), this ); + connect( mApplyButton, SIGNAL( clicked() ), SLOT( slotApply() ) ); + } else { + mApplyButton = 0; + } + + if ( buttonMask & Cancel ) { + mCancelButton = new QPushButton( i18n("Cancel"), this ); + connect( mCancelButton, SIGNAL( clicked() ), SLOT( slotCancel() ) ); + } else { + mCancelButton = 0; + } + + if ( buttonMask & Close ) { + mCloseButton = new QPushButton( i18n("Close"), this ); + connect( mCloseButton, SIGNAL( clicked() ), SLOT( slotClose() ) ); + } else { + mCloseButton = 0; + } +} + +QTabWidget *KDialogBase::tabWidget() +{ + if ( !mTabWidget ) { + mTabWidget = new QTabWidget( this ); + setMainWidget( mTabWidget ); + } + return mTabWidget; +} + +void KDialogBase::hideButtons() +{ + if ( mUser1Button ) mUser1Button->hide() ; + if ( mUser2Button ) mUser2Button->hide() ; + if ( mOkButton ) mOkButton->hide() ; + if ( mApplyButton ) mApplyButton->hide() ; + if ( mCancelButton ) mCancelButton->hide() ; + if ( mCloseButton ) mCloseButton->hide() ; + +} +void KDialogBase::initLayout() +{ + + delete mTopLayout; + mTopLayout = new QVBoxLayout( this ); + mTopLayout->setMargin( marginHint() ); + mTopLayout->setSpacing( spacingHint() ); + + mTopLayout->addWidget( mMainWidget ); + + QBoxLayout *buttonLayout = new QHBoxLayout; + mTopLayout->addLayout( buttonLayout ); + + if ( mUser1Button ) buttonLayout->addWidget( mUser1Button ); + if ( mUser2Button ) buttonLayout->addWidget( mUser2Button ); + if ( mOkButton ) buttonLayout->addWidget( mOkButton ); + if ( mApplyButton ) buttonLayout->addWidget( mApplyButton ); + if ( mCancelButton ) buttonLayout->addWidget( mCancelButton ); + if ( mCloseButton ) buttonLayout->addWidget( mCloseButton ); +} + +QFrame *KDialogBase::addPage( const QString &name ) +{ +// kdDebug() << "KDialogBase::addPage(): " << name << endl; + QFrame *frame = new QFrame( tabWidget() ); + tabWidget()->addTab( frame, name ); + return frame; +} + +QFrame *KDialogBase::addPage( const QString &name, int, const QPixmap & ) +{ + return addPage( name ); +} + + +void KDialogBase::setMainWidget( QWidget *widget ) +{ + kdDebug() << "KDialogBase::setMainWidget()" << endl; + + mMainWidget = widget; + initLayout(); +} + +void KDialogBase::setButtonText( ButtonCode id, const QString &text ) +{ + QPushButton *button = findButton( id ); + if ( button ) { + button->setText( text ); + } +} + +void KDialogBase::enableButton( ButtonCode id, bool state ) +{ + QPushButton *button = findButton( id ); + if ( button ) { + button->setEnabled( state ); + } +} + +QPushButton *KDialogBase::findButton( ButtonCode id ) +{ + QPushButton *button = 0; + switch ( id ) { + case Ok: + button = mOkButton; + break; + case Apply: + button = mApplyButton; + break; + case User1: + button = mUser1Button; + break; + case User2: + button = mUser2Button; + break; + case Cancel: + button = mCancelButton; + break; + case Close: + button = mCloseButton; + break; + default: + break; + } + return button; +} + +void KDialogBase::enableButtonOK( bool state ) +{ + enableButton( Ok, state ); +} + +void KDialogBase::enableButtonApply( bool state ) +{ + enableButton( Apply, state ); +} + +void KDialogBase::showButton( ButtonCode id, bool show ) +{ + QPushButton *button = findButton( id ); + if ( button ) { + if ( show ) button->show(); + else button->hide(); + } +} + +int KDialogBase::pageIndex( QWidget *widget ) const +{ + return 0; +} + + +bool KDialogBase::showPage( int index ) +{ + tabWidget()->setCurrentPage( index );return false; +} + +QFrame *KDialogBase::plainPage() +{ + if ( !mPlainPage ) { + mPlainPage = new QFrame( this ); + setMainWidget( mPlainPage ); + } + return mPlainPage; +} + +void KDialogBase::slotOk() +{ + emit okClicked(); + accept(); +} + +void KDialogBase::slotApply() +{ + emit applyClicked(); +} + +void KDialogBase::slotCancel() +{ + emit cancelClicked(); + reject(); +} + +void KDialogBase::slotClose() +{ + emit closeClicked(); + reject(); +} + +void KDialogBase::slotUser1() +{ + emit user1Clicked(); +} +void KDialogBase::slotUser2() +{ + emit user2Clicked(); +} diff --git a/microkde/kdialogbase.h b/microkde/kdialogbase.h new file mode 100644 index 0000000..199d2fa --- a/dev/null +++ b/microkde/kdialogbase.h @@ -0,0 +1,139 @@ +#ifndef MINIKDE_KDIALOGBASE_H +#define MINIKDE_KDIALOGBASE_H + +#include <qframe.h> + +#include "kdialog.h" + +class QPushButton; +class QLayout; +class QTabWidget; +class QBoxLayout; + +class KDialogBase : public KDialog +{ + Q_OBJECT + public: + enum ButtonCode + { + Help = 0x00000001, + Default = 0x00000002, + Ok = 0x00000004, + Apply = 0x00000008, + Try = 0x00000010, + Cancel = 0x00000020, + Close = 0x00000040, + User1 = 0x00000080, + User2 = 0x00000100, + User3 = 0x00000200, + No = 0x00000080, + Yes = 0x00000100, + Details = 0x00000400, + Filler = 0x40000000, + Stretch = 0x80000000 + }; + + enum DialogType + { + TreeList, + Tabbed, + Plain, + Swallow, + IconList + }; + + KDialogBase(); + KDialogBase( QWidget *parent=0, const char *name=0, bool modal=true, + const QString &caption=QString::null, + int buttonMask=Ok|Apply|Cancel, ButtonCode defaultButton=Ok, + bool separator=false, + const QString &user1=QString::null, + const QString &user2=QString::null, + const QString &user3=QString::null); + KDialogBase( int dialogFace, const QString &caption, + int buttonMask, ButtonCode defaultButton, + QWidget *parent=0, const char *name=0, bool modal=true, + bool separator=false, + const QString &user1=QString::null, + const QString &user2=QString::null, + const QString &user3=QString::null); + virtual ~KDialogBase(); + + QFrame *addPage( const QString & ); + QFrame *addPage( const QString &, int, const QPixmap & ); + + void setMainWidget( QWidget *widget ); + + void setButtonText( ButtonCode id, const QString &text ); + + void enableButton( ButtonCode id, bool state ); + void enableButtonOK( bool state ); + void enableButtonApply( bool state ); + + void showButton( ButtonCode, bool show ); + + int pageIndex( QWidget *widget ) const; + + bool showPage( int index ); + void hideButtons(); + + QFrame *plainPage(); + + signals: + void user1Clicked(); + void user2Clicked(); + /** + * The Apply button was pressed. This signal is only emitted if + * @ref slotApply() is not replaced. + */ + void applyClicked(); + + /** + * The OK button was pressed. This signal is only emitted if + * @ref slotOk() is not replaced. + */ + void okClicked(); + + /** + * The Cancel button was pressed. This signal is only emitted if + * @ref slotCancel() is not replaced. + */ + void cancelClicked(); + + /** + * The Close button was pressed. This signal is only emitted if + * @ref slotClose() is not replaced. + */ + void closeClicked(); + + protected slots: + virtual void slotOk(); + virtual void slotApply(); + virtual void slotCancel(); + virtual void slotClose(); + virtual void slotUser1(); + virtual void slotUser2(); + + protected: + QPushButton *findButton( ButtonCode ); + + private: + QTabWidget *tabWidget(); + void init( const QString &caption, int buttonMask, + const QString &user1=QString::null, const QString &user2=QString::null ); + void initLayout(); + + QWidget *mMainWidget; + QTabWidget *mTabWidget; + QFrame *mPlainPage; + QBoxLayout *mTopLayout; + + QPushButton *mUser1Button; + QPushButton *mUser2Button; + QPushButton *mCloseButton; + QPushButton *mOkButton; + QPushButton *mApplyButton; + QPushButton *mCancelButton; +}; + +#endif diff --git a/microkde/kdirwatch.h b/microkde/kdirwatch.h new file mode 100644 index 0000000..22b4dec --- a/dev/null +++ b/microkde/kdirwatch.h @@ -0,0 +1,14 @@ +#ifndef MICROKDE_KDIRWATCH_H +#define MICROKDE_KDIRWATCH_H + +#include <qobject.h> + +class KDirWatch : public QObject +{ + public: + KDirWatch() {} + + void addDir( const QString & ) {} +}; + +#endif diff --git a/microkde/keditlistbox.cpp b/microkde/keditlistbox.cpp new file mode 100644 index 0000000..55b7784 --- a/dev/null +++ b/microkde/keditlistbox.cpp @@ -0,0 +1,389 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org> + 2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qstringlist.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qgroupbox.h> +#include <qlistbox.h> +#include <qwhatsthis.h> +#include <qlabel.h> + +#include <kcombobox.h> +#include <kdebug.h> +#include <kdialog.h> +#include <klineedit.h> +#include <klocale.h> +#include <kapplication.h> +#include <knotifyclient.h> + +#include "keditlistbox.h" + +#include <assert.h> + +class KEditListBoxPrivate +{ +public: + bool m_checkAtEntering; + int buttons; +}; + +KEditListBox::KEditListBox(QWidget *parent, const char *name, + bool checkAtEntering, int buttons ) + :QGroupBox(parent, name ) +{ + init( checkAtEntering, buttons ); +} + +KEditListBox::KEditListBox(const QString& title, QWidget *parent, + const char *name, bool checkAtEntering, int buttons) + :QGroupBox(title, parent, name ) +{ + init( checkAtEntering, buttons ); +} + +KEditListBox::KEditListBox(const QString& title, const CustomEditor& custom, + QWidget *parent, const char *name, + bool checkAtEntering, int buttons) + :QGroupBox(title, parent, name ) +{ + m_lineEdit = custom.lineEdit(); + init( checkAtEntering, buttons, custom.representationWidget() ); +} + +KEditListBox::~KEditListBox() +{ + delete d; + d=0; +} + +void KEditListBox::init( bool checkAtEntering, int buttons, + QWidget *representationWidget ) +{ + d=new KEditListBoxPrivate; + d->m_checkAtEntering=checkAtEntering; + d->buttons = buttons; + + int lostButtons = 0; + if ( (buttons & Add) == 0 ) + lostButtons++; + if ( (buttons & Remove) == 0 ) + lostButtons++; + if ( (buttons & UpDown) == 0 ) + lostButtons += 2; + + + servNewButton = servRemoveButton = servUpButton = servDownButton = 0L; + setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding)); + + QWidget * gb = this; + QGridLayout * grid = new QGridLayout(gb, 7 - lostButtons, 2, + KDialog::marginHint(), + KDialog::spacingHint()); + grid->addRowSpacing(0, fontMetrics().lineSpacing()); + for ( int i = 1; i < 7 - lostButtons; i++ ) + grid->setRowStretch(i, 1); + + grid->setMargin(15); + + if ( representationWidget ) + representationWidget->reparent( gb, QPoint(0,0) ); + else + m_lineEdit=new KLineEdit(gb); + + m_listBox = new QListBox(gb); + + QWidget *editingWidget = representationWidget ? + representationWidget : m_lineEdit; + grid->addMultiCellWidget(editingWidget,1,1,0,1); + grid->addMultiCellWidget(m_listBox, 2, 6 - lostButtons, 0, 0); + int row = 2; + if ( buttons & Add ) { + servNewButton = new QPushButton(i18n("&Add"), gb); + servNewButton->setEnabled(false); + connect(servNewButton, SIGNAL(clicked()), SLOT(addItem())); + + grid->addWidget(servNewButton, row++, 1); + } + + if ( buttons & Remove ) { + servRemoveButton = new QPushButton(i18n("&Remove"), gb); + servRemoveButton->setEnabled(false); + connect(servRemoveButton, SIGNAL(clicked()), SLOT(removeItem())); + + grid->addWidget(servRemoveButton, row++, 1); + } + + if ( buttons & UpDown ) { + servUpButton = new QPushButton(i18n("Move &Up"), gb); + servUpButton->setEnabled(false); + connect(servUpButton, SIGNAL(clicked()), SLOT(moveItemUp())); + + servDownButton = new QPushButton(i18n("Move &Down"), gb); + servDownButton->setEnabled(false); + connect(servDownButton, SIGNAL(clicked()), SLOT(moveItemDown())); + + grid->addWidget(servUpButton, row++, 1); + grid->addWidget(servDownButton, row++, 1); + } + + connect(m_lineEdit,SIGNAL(textChanged(const QString&)),this,SLOT(typedSomething(const QString&))); + m_lineEdit->setTrapReturnKey(true); + connect(m_lineEdit,SIGNAL(returnPressed()),this,SLOT(addItem())); + connect(m_listBox, SIGNAL(highlighted(int)), SLOT(enableMoveButtons(int))); + + // maybe supplied lineedit has some text already + typedSomething( m_lineEdit->text() ); +} + +void KEditListBox::typedSomething(const QString& text) +{ + if(currentItem() >= 0) { + if(currentText() != m_lineEdit->text()) + { + // IMHO changeItem() shouldn't do anything with the value + // of currentItem() ... like changing it or emitting signals ... + // but TT disagree with me on this one (it's been that way since ages ... grrr) + bool block = m_listBox->signalsBlocked(); + m_listBox->blockSignals( true ); + m_listBox->changeItem(text, currentItem()); + m_listBox->blockSignals( block ); + emit changed(); + } + } + + if ( !servNewButton ) + return; + + if (!d->m_checkAtEntering) + servNewButton->setEnabled(!text.isEmpty()); + else + { + if (text.isEmpty()) + { + servNewButton->setEnabled(false); + } + else + { + bool enable = (m_listBox->findItem( text ) == 0L); + servNewButton->setEnabled( enable ); + } + } +} + +void KEditListBox::moveItemUp() +{ + if (!m_listBox->isEnabled()) + { + KNotifyClient::beep(); + return; + } + + unsigned int selIndex = m_listBox->currentItem(); + if (selIndex == 0) + { + KNotifyClient::beep(); + return; + } + + QListBoxItem *selItem = m_listBox->item(selIndex); + m_listBox->takeItem(selItem); + m_listBox->insertItem(selItem, selIndex-1); + m_listBox->setCurrentItem(selIndex - 1); + + emit changed(); +} + +void KEditListBox::moveItemDown() +{ + if (!m_listBox->isEnabled()) + { + KNotifyClient::beep(); + return; + } + + unsigned int selIndex = m_listBox->currentItem(); + if (selIndex == m_listBox->count() - 1) + { + KNotifyClient::beep(); + return; + } + + QListBoxItem *selItem = m_listBox->item(selIndex); + m_listBox->takeItem(selItem); + m_listBox->insertItem(selItem, selIndex+1); + m_listBox->setCurrentItem(selIndex + 1); + + emit changed(); +} + +void KEditListBox::addItem() +{ + // when m_checkAtEntering is true, the add-button is disabled, but this + // slot can still be called through Key_Return/Key_Enter. So we guard + // against this. + if ( !servNewButton || !servNewButton->isEnabled() ) + return; + + const QString& currentTextLE=m_lineEdit->text(); + bool alreadyInList(false); + //if we didn't check for dupes at the inserting we have to do it now + if (!d->m_checkAtEntering) + { + // first check current item instead of dumb iterating the entire list + if ( m_listBox->currentText() == currentTextLE ) + alreadyInList = true; + else + { + alreadyInList =(m_listBox->findItem(currentTextLE) != 0); + } + } + + if ( servNewButton ) + servNewButton->setEnabled(false); + + bool block = m_lineEdit->signalsBlocked(); + m_lineEdit->blockSignals(true); + m_lineEdit->clear(); + m_lineEdit->blockSignals(block); + + m_listBox->setSelected(currentItem(), false); + + if (!alreadyInList) + { + block = m_listBox->signalsBlocked(); + m_listBox->blockSignals( true ); + m_listBox->insertItem(currentTextLE); + m_listBox->blockSignals( block ); + emit changed(); + } +} + +int KEditListBox::currentItem() const +{ + int nr = m_listBox->currentItem(); + if(nr >= 0 && !m_listBox->item(nr)->selected()) return -1; + return nr; +} + +void KEditListBox::removeItem() +{ + int selected = m_listBox->currentItem(); + + if ( selected >= 0 ) + { + m_listBox->removeItem( selected ); + if ( count() > 0 ) + m_listBox->setSelected( QMIN( selected, count() - 1 ), true ); + + emit changed(); + } + + if ( servRemoveButton && m_listBox->currentItem() == -1 ) + servRemoveButton->setEnabled(false); +} + +void KEditListBox::enableMoveButtons(int index) +{ + // Update the lineEdit when we select a different line. + if(currentText() != m_lineEdit->text()) + m_lineEdit->setText(currentText()); + + bool moveEnabled = servUpButton && servDownButton; + + if (moveEnabled ) + { + if (m_listBox->count() <= 1) + { + servUpButton->setEnabled(false); + servDownButton->setEnabled(false); + } + else if ((uint) index == (m_listBox->count() - 1)) + { + servUpButton->setEnabled(true); + servDownButton->setEnabled(false); + } + else if (index == 0) + { + servUpButton->setEnabled(false); + servDownButton->setEnabled(true); + } + else + { + servUpButton->setEnabled(true); + servDownButton->setEnabled(true); + } + } + + if ( servRemoveButton ) + servRemoveButton->setEnabled(true); +} + +void KEditListBox::clear() +{ + m_lineEdit->clear(); + m_listBox->clear(); + emit changed(); +} + +void KEditListBox::insertStringList(const QStringList& list, int index) +{ + m_listBox->insertStringList(list,index); +} + +void KEditListBox::insertStrList(const QStrList* list, int index) +{ + m_listBox->insertStrList(list,index); +} + +void KEditListBox::insertStrList(const QStrList& list, int index) +{ + m_listBox->insertStrList(list,index); +} + +void KEditListBox::insertStrList(const char ** list, int numStrings, int index) +{ + m_listBox->insertStrList(list,numStrings,index); +} + +QStringList KEditListBox::items() const +{ + QStringList list; + for ( uint i = 0; i < m_listBox->count(); i++ ) + list.append( m_listBox->text( i )); + + return list; +} + +void KEditListBox::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +KEditListBox::CustomEditor::CustomEditor( KComboBox *combo ) +{ + m_representationWidget = combo; + m_lineEdit = static_cast<KLineEdit*>( combo->lineEdit() ); + assert( m_lineEdit ); +} + diff --git a/microkde/keditlistbox.h b/microkde/keditlistbox.h new file mode 100644 index 0000000..130d933 --- a/dev/null +++ b/microkde/keditlistbox.h @@ -0,0 +1,226 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KEDITLISTBOX_H +#define KEDITLISTBOX_H + +#include <qgroupbox.h> +#include <qlistbox.h> + +class KLineEdit; +class KComboBox; +class QPushButton; + +class KEditListBoxPrivate; +/** + * An editable listbox + * + * This class provides a editable listbox ;-), this means + * a listbox which is accompanied by a line edit to enter new + * items into the listbox and pushbuttons to add and remove + * items from the listbox and two buttons to move items up and down. + */ +class KEditListBox : public QGroupBox +{ + Q_OBJECT + +public: + /// @since 3.1 + class CustomEditor + { + public: + CustomEditor() + : m_representationWidget( 0L ), + m_lineEdit( 0L ) {} + CustomEditor( QWidget *repWidget, KLineEdit *edit ) + : m_representationWidget( repWidget ), + m_lineEdit( edit ) {} + CustomEditor( KComboBox *combo ); + + void setRepresentationWidget( QWidget *repWidget ) { + m_representationWidget = repWidget; + } + void setLineEdit( KLineEdit *edit ) { + m_lineEdit = edit; + } + + virtual QWidget *representationWidget() const { + return m_representationWidget; + } + virtual KLineEdit *lineEdit() const { + return m_lineEdit; + } + + protected: + QWidget *m_representationWidget; + KLineEdit *m_lineEdit; + }; + + public: + + /** + * Enumeration of the buttons, the listbox offers. Specify them in the + * constructor in the buttons parameter. + */ + enum Button { Add = 1, Remove = 2, UpDown = 4, All = Add|Remove|UpDown }; + + /** + * Create an editable listbox. + * + * If @p checkAtEntering is true, after every character you type + * in the line edit KEditListBox will enable or disable + * the Add-button, depending whether the current content of the + * line edit is already in the listbox. Maybe this can become a + * performance hit with large lists on slow machines. + * If @p checkAtEntering is false, + * it will be checked if you press the Add-button. It is not + * possible to enter items twice into the listbox. + */ + KEditListBox(QWidget *parent = 0, const char *name = 0, + bool checkAtEntering=false, int buttons = All ); + /** + * Create an editable listbox. + * + * The same as the other constructor, additionally it takes + * @title, which will be the title of the frame around the listbox. + */ + KEditListBox(const QString& title, QWidget *parent = 0, + const char *name = 0, bool checkAtEntering=false, + int buttons = All ); + + /** + * Another constructor, which allows to use a custom editing widget + * instead of the standard KLineEdit widget. E.g. you can use a + * @ref KURLRequester or a @ref KComboBox as input widget. The custom + * editor must consist of a lineedit and optionally another widget that + * is used as representation. A KComboBox or a KURLRequester have a + * KLineEdit as child-widget for example, so the KComboBox is used as + * the representation widget. + * + * @see KURLRequester::customEditor() + * @since 3.1 + */ + KEditListBox( const QString& title, + const CustomEditor &customEditor, + QWidget *parent = 0, const char *name = 0, + bool checkAtEntering = false, int buttons = All ); + + virtual ~KEditListBox(); + + /** + * Return a pointer to the embedded QListBox. + */ + QListBox* listBox() const { return m_listBox; } + /** + * Return a pointer to the embedded QLineEdit. + */ + KLineEdit* lineEdit() const { return m_lineEdit; } + /** + * Return a pointer to the Add button + */ + QPushButton* addButton() const { return servNewButton; } + /** + * Return a pointer to the Remove button + */ + QPushButton* removeButton() const { return servRemoveButton; } + /** + * Return a pointer to the Up button + */ + QPushButton* upButton() const { return servUpButton; } + /** + * Return a pointer to the Down button + */ + QPushButton* downButton() const { return servDownButton; } + + /** + * See @ref QListBox::count() + */ + int count() const { return int(m_listBox->count()); } + /** + * See @ref QListBox::insertStringList() + */ + void insertStringList(const QStringList& list, int index=-1); + /** + * See @ref QListBox::insertStringList() + */ + void insertStrList(const QStrList* list, int index=-1); + /** + * See @ref QListBox::insertStrList() + */ + void insertStrList(const QStrList& list, int index=-1); + /** + * See @ref QListBox::insertStrList() + */ + void insertStrList(const char ** list, int numStrings=-1, int index=-1); + /** + * See @ref QListBox::insertItem() + */ + void insertItem(const QString& text, int index=-1) {m_listBox->insertItem(text,index);} + /** + * Clears both the listbox and the line edit. + */ + void clear(); + /** + * See @ref QListBox::text() + */ + QString text(int index) const { return m_listBox->text(index); } + /** + * See @ref QListBox::currentItem() + */ + int currentItem() const; + /** + * See @ref QListBox::currentText() + */ + QString currentText() const { return m_listBox->currentText(); } + + /** + * @returns a stringlist of all items in the listbox + */ + QStringList items() const; + + signals: + void changed(); + + protected slots: + //the names should be self-explaining + void moveItemUp(); + void moveItemDown(); + void addItem(); + void removeItem(); + void enableMoveButtons(int index); + void typedSomething(const QString& text); + + private: + QListBox *m_listBox; + QPushButton *servUpButton, *servDownButton; + QPushButton *servNewButton, *servRemoveButton; + KLineEdit *m_lineEdit; + + //this is called in both ctors, to avoid code duplication + void init( bool checkAtEntering, int buttons, + QWidget *representationWidget = 0L ); + + protected: + virtual void virtual_hook( int id, void* data ); + private: + //our lovely private d-pointer + KEditListBoxPrivate *d; +}; + +#endif diff --git a/microkde/kemailsettings.cpp b/microkde/kemailsettings.cpp new file mode 100644 index 0000000..9a9ad84 --- a/dev/null +++ b/microkde/kemailsettings.cpp @@ -0,0 +1,6 @@ +#include "kemailsettings.h" + +QString KEMailSettings::getSetting(KEMailSettings::Setting s) +{ + return QString::null; +} diff --git a/microkde/kemailsettings.h b/microkde/kemailsettings.h new file mode 100644 index 0000000..cf43f17 --- a/dev/null +++ b/microkde/kemailsettings.h @@ -0,0 +1,32 @@ +#ifndef MINIKDE_KEMAILSETTINGS_H +#define MINIKDE_KEMAILSETTINGS_H + +#include <qstring.h> + +class KEMailSettings +{ + public: + enum Setting { + ClientProgram, + ClientTerminal, + RealName, + EmailAddress, + ReplyToAddress, + Organization, + OutServer, + OutServerLogin, + OutServerPass, + OutServerType, + OutServerCommand, + OutServerTLS, + InServer, + InServerLogin, + InServerPass, + InServerType, + InServerMBXType, + InServerTLS + }; + QString getSetting(KEMailSettings::Setting s); +}; + +#endif diff --git a/microkde/kfiledialog.cpp b/microkde/kfiledialog.cpp new file mode 100644 index 0000000..977499e --- a/dev/null +++ b/microkde/kfiledialog.cpp @@ -0,0 +1,74 @@ +#include <kfiledialog.h> +#include <qdialog.h> +#include <qlayout.h> +#include <qdir.h> +#include <qfileinfo.h> +#include <qapplication.h> + +#ifndef DESKTOP_VERSION +//US orig#include <ofileselector.h> +#include <ofileselector_p.h> +QString KFileDialog::getSaveFileName( const QString & fn, + const QString & cap , QWidget * par ) +{ + QString retfile = ""; + QDialog dia ( par, "input-dialog", true ); + QVBoxLayout lay( &dia ); + lay.setMargin(7); + lay.setSpacing(7); + dia.setCaption( cap ); + QString file = fn; + if ( file.isEmpty() ) + file = QDir::homeDirPath()+"/*"; + QFileInfo fi ( file ); + OFileSelector o ( &dia,OFileSelector::FileSelector, OFileSelector::Save, fi.dirPath(true), fi.fileName() ); + lay.addWidget( &o); + // o.setNewVisible( true ); + // o.setNameVisible( true ); + dia.showMaximized(); + int res = dia.exec(); + if ( res ) + retfile = o.selectedName(); + return retfile; +} + +QString KFileDialog::getOpenFileName( const QString & fn, + const QString & cap, QWidget * par ) +{ + QString retfile = ""; + QDialog dia ( par, "input-dialog", true ); + // QLineEdit lab ( &dia ); + QVBoxLayout lay( &dia ); + lay.setMargin(7); + lay.setSpacing(7); + dia.setCaption( cap ); + QString file = fn; + if ( file.isEmpty() ) + file = QDir::homeDirPath()+"/*";; + QFileInfo fi ( file ); + OFileSelector o ( &dia,OFileSelector::FileSelector, OFileSelector::Open, fi.dirPath(true), fi.fileName() ); + lay.addWidget( &o); + dia.showMaximized(); + int res = dia.exec(); + if ( res ) + retfile = o.selectedName(); + return retfile; +} + +#else + +#include <qfiledialog.h> + +QString KFileDialog::getSaveFileName( const QString & fn, + const QString & cap , QWidget * par ) +{ + return QFileDialog::getSaveFileName( fn, QString::null, par, "openfile", cap ); +} +QString KFileDialog::getOpenFileName( const QString & fn, + const QString & cap, QWidget * par ) +{ + + return QFileDialog::getOpenFileName( fn, QString::null, par, "openfile", cap ); +} +#endif + diff --git a/microkde/kfiledialog.h b/microkde/kfiledialog.h new file mode 100644 index 0000000..0825872 --- a/dev/null +++ b/microkde/kfiledialog.h @@ -0,0 +1,20 @@ +#ifndef MICROKDE_KFILEDIALOG_H +#define MICROKDE_KFILEDIALOG_H + +#include <qstring.h> +#include <qwidget.h> + +class KFileDialog +{ + public: + + static QString getSaveFileName( const QString &, + const QString &, QWidget * ); + + + static QString getOpenFileName( const QString &, + const QString &, QWidget * ); + +}; + +#endif diff --git a/microkde/kfontdialog.cpp b/microkde/kfontdialog.cpp new file mode 100644 index 0000000..174123c --- a/dev/null +++ b/microkde/kfontdialog.cpp @@ -0,0 +1,32 @@ +#include "kfontdialog.h" +#ifndef DESKTOP_VERSION +#include "ofontselector.h" +#else +#include <qfontdialog.h> +#endif +#include <qdialog.h> +#include <qlayout.h> +#include <qpushbutton.h> +QFont KFontDialog::getFont( const QFont & f, bool & ok ) +{ +#ifndef DESKTOP_VERSION + QDialog d( 0, "fd", true );; + OFontSelector s ( true, &d, "fontsel"); + QVBoxLayout l ( &d ); + l.addWidget( &s ); + s.setSelectedFont ( f ); + QPushButton b ( "OK", &d ); + l.addWidget( &b ); + qDebug("size %d ", f.bold()); + QObject::connect( &b, SIGNAL( clicked () ), &d, SLOT ( accept () ) ); + d.show(); + ok = false; + if ( d.exec () ) { + ok = true; + return s.selectedFont ( ); + } + return f; +#else + return QFontDialog::getFont ( &ok, f, 0, "fontdialog" ); +#endif +} diff --git a/microkde/kfontdialog.h b/microkde/kfontdialog.h new file mode 100644 index 0000000..f2ac6ac --- a/dev/null +++ b/microkde/kfontdialog.h @@ -0,0 +1,15 @@ +#ifndef MINIKDE_KFONTDIALOG_H +#define MINIKDE_KFONTDIALOG_H + +#include <qfont.h> +#include <qdialog.h> + +class KFontDialog +{ + public: + enum { Accepted }; + + static QFont getFont( const QFont & f, bool & ok); +}; + +#endif diff --git a/microkde/kglobal.cpp b/microkde/kglobal.cpp new file mode 100644 index 0000000..0aba952 --- a/dev/null +++ b/microkde/kglobal.cpp @@ -0,0 +1,166 @@ +#include "kglobal.h" +#include <qkeycode.h> +#include <qapplication.h> + +KLocale *KGlobal::mLocale = 0; +KConfig *KGlobal::mConfig = 0; +KIconLoader *KGlobal::mIconLoader = 0; +KStandardDirs *KGlobal::mDirs = 0; + +QString KGlobal::mAppName = "godot"; + +KLocale *KGlobal::locale() +{ + if ( !mLocale ) { + ASSERT(mAppName); + + mLocale = new KLocale();//mAppName); + } + + return mLocale; +} + +//US +void KGlobal::setLocale(KLocale *kg) +{ + mLocale = kg; +} + +KConfig *KGlobal::config() +{ + if ( !mConfig ) { + mConfig = new KConfig( KStandardDirs::appDir() + mAppName + "rc" ); + } + + return mConfig; +} + +KGlobal::Size KGlobal::getDesktopSize() +{ +#ifdef DESKTOP_VERSION + return KGlobal::Desktop; +#else + if ( QApplication::desktop()->width() < 480 ) + return KGlobal::Small; + else + return KGlobal::Medium; +#endif +} + +KGlobal::Orientation KGlobal::getOrientation() +{ + if (QApplication::desktop()->width() > QApplication::desktop()->height()) + return KGlobal::Landscape; + else + return KGlobal::Portrait; +} + +int KGlobal::getDesktopWidth() +{ + return QApplication::desktop()->width(); +} + +int KGlobal::getDesktopHeight() +{ + return QApplication::desktop()->height(); +} + + +KIconLoader *KGlobal::iconLoader() +{ + if ( !mIconLoader ) { + mIconLoader = new KIconLoader(); + } + + return mIconLoader; +} + +KStandardDirs *KGlobal::dirs() +{ + if ( !mDirs ) { + mDirs = new KStandardDirs(); + } + + return mDirs; +} + +void KGlobal::setAppName( const QString &appName ) +{ + mAppName = appName; +} + +//US +QString KGlobal::getAppName() +{ + return mAppName; +} +QString KGlobal::formatMessage ( QString mess, int maxlen ) +{ + //int maxlen = 80; + int start = 0; + int end = mess.length(); + QString retVal = ""; + int nl, space; + while ( (end - start) > maxlen ) { + nl = mess.find( "\n", start ); + if ( nl > 0 && nl < start + maxlen ) { + nl += 1; + retVal += mess.mid( start, nl - start); + start = nl; + } else { + space = mess.findRev( " ", start + maxlen ); + if ( space < start ) { + retVal += mess.mid( start, maxlen) +"\n"; + start += maxlen ; + } else { + retVal += mess.mid( start, space - start ) +"\n"; + start = space+ 1; + } + } + } + retVal += mess.mid( start, end - start ); + return retVal; +} +int KGlobal::knumkeykonv( int k ) +{ + int key; +switch( k ) { + case Qt::Key_Q : + key = Qt::Key_1; + break; + case Qt::Key_W : + key = Qt::Key_2; + break; + case Qt::Key_E : + key = Qt::Key_3; + break; + case Qt::Key_R : + key = Qt::Key_4; + break; + case Qt::Key_T : + key = Qt::Key_5; + break; + case Qt::Key_Z : + key = Qt::Key_6; + break; + case Qt::Key_Y : + key = Qt::Key_6; + break; + case Qt::Key_U : + key = Qt::Key_7; + break; + case Qt::Key_I : + key = Qt::Key_8; + break; + case Qt::Key_O : + key = Qt::Key_9; + break; + case Qt::Key_P : + key = Qt::Key_0; + break; + default: + key = k; + break; + } // switch + return key; +} diff --git a/microkde/kglobal.h b/microkde/kglobal.h new file mode 100644 index 0000000..1e03bea --- a/dev/null +++ b/microkde/kglobal.h @@ -0,0 +1,68 @@ +#ifndef MINIKDE_KGLOBAL_H +#define MINIKDE_KGLOBAL_H + +#include "klocale.h" +#include "kconfig.h" +#include "kiconloader.h" +#include <kstandarddirs.h> +#include <qevent.h> +class KStandardDirs; +class KGlobal { + public: + static KLocale *locale(); + static KConfig *config(); + static KIconLoader *iconLoader(); + static KStandardDirs *dirs(); + static int knumkeykonv( int ); + + static void setAppName( const QString & ); + static QString formatMessage( QString mess, int maxlen ) ; + +//US begin: added the following methods for convenience + static QString getAppName(); + static void setLocale(KLocale *); + + enum Orientation { Portrait, Landscape }; + enum Size { Small, Medium, Desktop }; + + static int getDesktopWidth(); + static int getDesktopHeight(); + static KGlobal::Size getDesktopSize(); + static KGlobal::Orientation getOrientation(); + + + private: + static KLocale *mLocale; + static KConfig *mConfig; + static KIconLoader *mIconLoader; + static KStandardDirs *mDirs; + + static QString mAppName; +}; + + +/** @ref KGlobal + * A typesafe function to find the minimum of the two arguments. + */ +#define KMIN(a,b) kMin(a,b) +/** @ref KGlobal + * A typesafe function to find the maximum of the two arguments. + */ +#define KMAX(a,b) kMax(a,b) +/** @ref KGlobal + * A typesafe function to determine the absolute value of the argument. + */ +#define KABS(a) kAbs(a) + + +template<class T> +inline const T& kMin (const T& a, const T& b) { return a < b ? a : b; } + +template<class T> +inline const T& kMax (const T& a, const T& b) { return b < a ? a : b; } + +template<class T> +inline T kAbs (const T& a) { return a < 0 ? -a : a; } + + +#endif diff --git a/microkde/kglobalsettings.cpp b/microkde/kglobalsettings.cpp new file mode 100644 index 0000000..2fff8fc --- a/dev/null +++ b/microkde/kglobalsettings.cpp @@ -0,0 +1,41 @@ +#include "kglobalsettings.h" +#include "kconfig.h" +#include "kglobal.h" +#include "kconfigbase.h" + +#include <qapplication.h> + +QFont KGlobalSettings::generalFont() +{ + int size = 12; + if (QApplication::desktop()->width() < 480 ) + size = 10; + return QFont("helvetica",size); +} +QFont KGlobalSettings::toolBarFont() +{ + return QFont("helevetica",12); +} + +QColor KGlobalSettings::toolBarHighlightColor() +{ + return QColor("black"); +} + +QRect KGlobalSettings::desktopGeometry( QWidget * ) +{ + return QApplication::desktop()->rect(); +} + + /** + * Returns whether KDE runs in single (default) or double click + * mode. + * see http://developer.kde.org/documentation/standards/kde/style/mouse/index.html + * @return true if single click mode, or false if double click mode. + **/ +bool KGlobalSettings::singleClick() +{ + KConfig *c = KGlobal::config(); + KConfigGroupSaver cgs( c, "KDE" ); + return c->readBoolEntry("SingleClick", KDE_DEFAULT_SINGLECLICK); +} diff --git a/microkde/kglobalsettings.h b/microkde/kglobalsettings.h new file mode 100644 index 0000000..7df8012 --- a/dev/null +++ b/microkde/kglobalsettings.h @@ -0,0 +1,30 @@ +#ifndef MICROKDE_KGLOBALSETTINGS_H +#define MICROKDE_KGLOBALSETTINGS_H + +#include <qfont.h> +#include <qrect.h> + + +#define KDE_DEFAULT_SINGLECLICK true + + +class KGlobalSettings +{ + public: + static QFont generalFont(); + static QFont toolBarFont(); + + static QColor toolBarHighlightColor(); + static QRect desktopGeometry( QWidget * ); + + /** + * Returns whether KDE runs in single (default) or double click + * mode. + * see http://developer.kde.org/documentation/standards/kde/style/mouse/index.html + * @return true if single click mode, or false if double click mode. + **/ + static bool singleClick(); + +}; + +#endif diff --git a/microkde/kiconloader.cpp b/microkde/kiconloader.cpp new file mode 100644 index 0000000..4842d71 --- a/dev/null +++ b/microkde/kiconloader.cpp @@ -0,0 +1,140 @@ + +#include "kiconloader.h" +#include "kglobal.h" + +#ifndef DESKTOP_VERSION_OEGEL +#include <qdir.h> +QPixmap KIconLoader::loadIcon( const QString& name, KIcon::Group, int, + int, QString *, bool ) const +{ + QPixmap pix; + QString file; + file = iconPath() + name+".png"; + pix.load ( file ); + // qDebug("KIconLoader::loadIcon %s -----------", file.latin1()); + return pix; +} +QIconSet KIconLoader::loadIconSet( const QString& name) const +{ + QPixmap pixmapLoader; + QString file; + file = iconPath() + name+".png"; + pixmapLoader.load( file ); + //qDebug("KIconLoader::loadIconSet: %s ************", file.latin1() ); + QIconSet is ( pixmapLoader ); + return is; +} + +QPixmap BarIcon( const QString &name ) +{ + QPixmap pix; + pix.load ( KGlobal::iconLoader()->iconPath() + name +".png" ); + return pix; +} + +QPixmap DesktopIcon( const QString &name, int ) +{ + QPixmap pix; + pix.load ( KGlobal::iconLoader()->iconPath() + name +".png" ); + return pix; + +} + +QPixmap SmallIcon( const QString &name ) +{ + QPixmap pixmapLoader; + QString file; + file =KGlobal::iconLoader()->iconPath() + name +".png"; + pixmapLoader.load( file ); + return pixmapLoader; + +} + +QPixmap SmallIconSet( const QString &name ) +{ + QPixmap pixmapLoader; + QString file; + file =KGlobal::iconLoader()->iconPath() + name +".png"; + pixmapLoader.load( file ); + return pixmapLoader; +} + + +#else + +#include <qpe/resource.h> +#include <kglobal.h> +QPixmap KIconLoader::loadIcon( const QString& name, KIcon::Group, int, + int, QString *, bool ) const +{ + QString px = this->iconPath() + "/" + name; + + QPixmap p = Resource::loadPixmap( px ); + QPixmap* pPtr = &p; + if (pPtr == 0) + qDebug("KIconLoader::loadIcon: %s not found", px.latin1()); + + return p; +} + +QIconSet KIconLoader::loadIconSet( const QString& name) const +{ + QString px = this->iconPath() + "/" + name; + + QIconSet is ;//= Resource::loadIconSet( px ); + QIconSet* isPtr = 0;//LR&is; + if (isPtr == 0) + qDebug("KIconLoader::loadIconSet: %s not foun", px.latin1()); + + return is; +} + +QPixmap BarIcon( const QString &name ) +{ + QPixmap p = KGlobal::iconLoader()->loadIcon(name, KIcon::Desktop); + return p; +} + +QPixmap DesktopIcon( const QString &name, int ) +{ + QPixmap p = KGlobal::iconLoader()->loadIcon(name, KIcon::Desktop); + return p; +} + +QPixmap SmallIcon( const QString &name ) +{ + QPixmap p = KGlobal::iconLoader()->loadIcon(name, KIcon::Desktop); + return p; +} + +QPixmap SmallIconSet( const QString &name ) +{ + QPixmap p = KGlobal::iconLoader()->loadIcon(name, KIcon::Desktop); + return p; +} + +#endif + +//US +QString KIconLoader::setIconPath( const QString &iconpath) +{ + QString _old = mIconpath; + mIconpath = iconpath; + + return _old; +} +QString KIconLoader::iconPath( const QString & name, int ) const +{ + return mIconpath + name + ".png"; +} + +QString KIconLoader::iconPath( /*US const QString &, int */) const +{ + // LR we set the path at startup + // if (KGlobal::getDesktopSize() == KGlobal::Small) + //return mIconpath + "/icons16"; + + //Fall back to the defaultpath + return mIconpath; +} + diff --git a/microkde/kiconloader.h b/microkde/kiconloader.h new file mode 100644 index 0000000..68fec4e --- a/dev/null +++ b/microkde/kiconloader.h @@ -0,0 +1,52 @@ +#ifndef MINIKDE_KICONLOADER_H +#define MINIKDE_KICONLOADER_H + +#include <qpixmap.h> +#include <qstring.h> +//US +#include <qiconset.h> + +class KIcon +{ + public: + enum Group { NoGroup=-1, Desktop=0, Toolbar, MainToolbar, Small, + Panel, LastGroup, User }; + enum StdSizes { SizeSmall=16, SizeMedium=32, SizeLarge=48 }; + enum States { DefaultState, ActiveState, DisabledState, LastState }; +}; + +class KIconLoader +{ + public: + KIconLoader() + : mIconpath(0) {} + + KIconLoader( const QString &iconpath ) + : mIconpath(iconpath) {} + +//US QPixmap loadIcon( const QString &name, int ); + + QPixmap loadIcon(const QString& name, KIcon::Group group, int size=0, + int state=KIcon::DefaultState, QString *path_store=0, + bool canReturnNull=false) const; + +//US + QString setIconPath( const QString &); + QString iconPath( /*US const QString &, int */) const; + QString iconPath( const QString &, int ) const; + QIconSet loadIconSet( const QString &name) const; + +//US to make this class usable for different applications, we have to add a iconpathvariable + private: + QString mIconpath; +}; + +QPixmap BarIcon(const QString& name); + +QPixmap DesktopIcon(const QString& name, int); + +QPixmap SmallIcon(const QString& name); + +QPixmap SmallIconSet( const QString &name ); + +#endif diff --git a/microkde/kio/job.h b/microkde/kio/job.h new file mode 100644 index 0000000..21c56b0 --- a/dev/null +++ b/microkde/kio/job.h @@ -0,0 +1,12 @@ +#ifndef MINIKDE_KIO_JOB_H +#define MINIKDE_KIO_JOB_H + +namespace KIO { + +class Job +{ +}; + +} + +#endif diff --git a/microkde/kio/kfile/kurlrequester.cpp b/microkde/kio/kfile/kurlrequester.cpp new file mode 100644 index 0000000..6d39308 --- a/dev/null +++ b/microkde/kio/kfile/kurlrequester.cpp @@ -0,0 +1,406 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org> + + library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#include <sys/stat.h> +#ifdef _WIN32_ + +#else +#include <unistd.h> +#endif +#include <qstring.h> +//US #include <qtooltip.h> + +#include <qpushbutton.h> + +//US #include <kaccel.h> +//US #include <kcombobox.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kfiledialog.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +//US #include <kurlcompletion.h> +//US #include <kurldrag.h> +//US #include <kprotocolinfo.h> + + +#include "kurlrequester.h" + + +class KURLDragPushButton : public QPushButton +{ +public: + KURLDragPushButton( QWidget *parent, const char *name=0 ) + : QPushButton( parent, name ) { +//US setDragEnabled( true ); + } + ~KURLDragPushButton() {} + + void setURL( const KURL& url ) { + m_urls.clear(); + m_urls.append( url ); + } + + /* not needed so far + void setURLs( const KURL::List& urls ) { + m_urls = urls; + } + const KURL::List& urls() const { return m_urls; } + */ + +protected: +/*US + virtual QDragObject *dragObject() { + if ( m_urls.isEmpty() ) + return 0L; + + QDragObject *drag = KURLDrag::newDrag( m_urls, this, "url drag" ); + return drag; + } +*/ +private: + KURL::List m_urls; + +}; + + +/* +************************************************************************* +*/ + +class KURLRequester::KURLRequesterPrivate +{ +public: + KURLRequesterPrivate() { + edit = 0L; +//US combo = 0L; +//US fileDialogMode = KFile::File | KFile::ExistingOnly | KFile::LocalOnly; + } + + void setText( const QString& text ) { +/*US + if ( combo ) + { + if (combo->editable()) + { + combo->setEditText( text ); + } + else + { + combo->insertItem( text ); + combo->setCurrentItem( combo->count()-1 ); + } + } + else +*/ + { + edit->setText( text ); + } + } + + void connectSignals( QObject *receiver ) { + QObject *sender; +/*US if ( combo ) + sender = combo; + else +*/ + sender = edit; + + connect( sender, SIGNAL( textChanged( const QString& )), + receiver, SIGNAL( textChanged( const QString& ))); + connect( sender, SIGNAL( returnPressed() ), + receiver, SIGNAL( returnPressed() )); +//US connect( sender, SIGNAL( returnPressed( const QString& ) ), +//US receiver, SIGNAL( returnPressed( const QString& ) )); + } +/*US + void setCompletionObject( KCompletion *comp ) { + if ( combo ) + combo->setCompletionObject( comp ); + else + edit->setCompletionObject( comp ); + } +*/ + /** + * replaces ~user or $FOO, if necessary + */ + QString url() { + QString txt = /*US combo ? combo->currentText() : */ edit->text(); +/*US KURLCompletion *comp; + if ( combo ) + comp = dynamic_cast<KURLCompletion*>(combo->completionObject()); + else + comp = dynamic_cast<KURLCompletion*>(edit->completionObject()); + + if ( comp ) + return comp->replacedPath( txt ); + else +*/ + return txt; + } + + KLineEdit *edit; +//US KComboBox *combo; + int fileDialogMode; + QString fileDialogFilter; +}; + + +/*US +KURLRequester::KURLRequester( QWidget *editWidget, QWidget *parent, + const char *name ) + : QHBox( parent, name ) +{ + d = new KURLRequesterPrivate; + + // must have this as parent + editWidget->reparent( this, 0, QPoint(0,0) ); +//US d->edit = dynamic_cast<KLineEdit*>( editWidget ); + d->edit = (KLineEdit*)( editWidget ); +//US d->combo = dynamic_cast<KComboBox*>( editWidget ); + + init(); +} +*/ + +KURLRequester::KURLRequester( QWidget *parent, const char *name ) + : QHBox( parent, name ) +{ + d = new KURLRequesterPrivate; + init(); +} + + +KURLRequester::KURLRequester( const QString& url, QWidget *parent, + const char *name ) + : QHBox( parent, name ) +{ + d = new KURLRequesterPrivate; + init(); + setURL( url ); +} + + +KURLRequester::~KURLRequester() +{ +//US delete myCompletion; + delete myFileDialog; + delete d; +} + + +void KURLRequester::init() +{ + myFileDialog = 0L; + myShowLocalProt = false; + + if (/*US !d->combo && */ !d->edit ) + d->edit = new KLineEdit( this, "KURLRequester::KLineEdit" ); + + myButton = new KURLDragPushButton( this, "kfile button"); + QIconSet iconSet = SmallIconSet("fileopen"); + QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); + myButton->setIconSet( iconSet ); + myButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); +//US QToolTip::add(myButton, i18n("Open file dialog")); + + connect( myButton, SIGNAL( pressed() ), SLOT( slotUpdateURL() )); + + setSpacing( KDialog::spacingHint() ); + + QWidget *widget = /*US d->combo ? (QWidget*) d->combo : */ (QWidget*) d->edit; + setFocusProxy( widget ); + + d->connectSignals( this ); + connect( myButton, SIGNAL( clicked() ), this, SLOT( slotOpenDialog() )); +/*US + myCompletion = new KURLCompletion(); + d->setCompletionObject( myCompletion ); + + KAccel *accel = new KAccel( this ); + accel->insert( KStdAccel::Open, this, SLOT( slotOpenDialog() )); + accel->readSettings(); +*/ +} + + +void KURLRequester::setURL( const QString& url ) +{ + bool hasLocalPrefix = (url.startsWith("file:")); + + if ( !myShowLocalProt && hasLocalPrefix ) + d->setText( url.mid( 5, url.length()-5 )); + else + d->setText( url ); +} + +void KURLRequester::setCaption( const QString& caption ) +{ +//US fileDialog()->setCaption( caption ); +//US QWidget::setCaption( caption ); +} + +QString KURLRequester::url() const +{ + return d->url(); +} + + +void KURLRequester::slotOpenDialog() +{ + emit openFileDialog( this ); + +//US use our special KFIleDialog instead + KURL u( url() ); + //QString fn = u.url(); + QString fn = d->edit->text(); + fn = KFileDialog::getSaveFileName( fn, "Save backup filename", this ); + + if ( fn == "" ) + return; + + setURL( fn ); + emit urlSelected( d->url() ); +/*US + KFileDialog *dlg = fileDialog(); + if ( !d->url().isEmpty() ) { + KURL u( url() ); + // If we won't be able to list it (e.g. http), then don't try :) + if ( KProtocolInfo::supportsListing( u.protocol() ) ) + dlg->setSelection( u.url() ); + } + + if ( dlg->exec() == QDialog::Accepted ) + { + setURL( dlg->selectedURL().prettyURL() ); + emit urlSelected( d->url() ); + } +*/ + +} + +void KURLRequester::setMode(unsigned int mode) +{ +/*US + Q_ASSERT( (mode & KFile::Files) == 0 ); + d->fileDialogMode = mode; + if ( (mode & KFile::Directory) && !(mode & KFile::File) ) + myCompletion->setMode( KURLCompletion::DirCompletion ); + + if (myFileDialog) + myFileDialog->setMode( d->fileDialogMode ); +*/ +} + +void KURLRequester::setFilter(const QString &filter) +{ +/*US + d->fileDialogFilter = filter; + if (myFileDialog) + myFileDialog->setFilter( d->fileDialogFilter ); +*/ +} + +KFileDialog * KURLRequester::fileDialog() const +{ +/*US + if ( !myFileDialog ) { + QWidget *p = parentWidget(); + myFileDialog = new KFileDialog( QString::null, QString::null, p, + "file dialog", true ); + + myFileDialog->setMode( d->fileDialogMode ); + myFileDialog->setFilter( d->fileDialogFilter ); + } + + return myFileDialog; +*/ + return 0; +} + + +void KURLRequester::setShowLocalProtocol( bool b ) +{ + if ( myShowLocalProt == b ) + return; + + myShowLocalProt = b; + setURL( url() ); +} + +void KURLRequester::clear() +{ + d->setText( QString::null ); +} + +KLineEdit * KURLRequester::lineEdit() const +{ + return d->edit; +} +/*US +KComboBox * KURLRequester::comboBox() const +{ + return d->combo; +} +*/ +void KURLRequester::slotUpdateURL() +{ + // bin compat, myButton is declared as QPushButton +//US KURL u( QDir::currentDirPath() + '/', url() ); + KURL u( url() ); + (static_cast<KURLDragPushButton *>( myButton))->setURL( u ); +} + +QPushButton * KURLRequester::button() const +{ + return myButton; +} +/*US +KEditListBox::CustomEditor KURLRequester::customEditor() +{ + setSizePolicy(QSizePolicy( QSizePolicy::Preferred, + QSizePolicy::Fixed)); + + KLineEdit *edit = d->edit; + if ( !edit && d->combo ) + edit = dynamic_cast<KLineEdit*>( d->combo->lineEdit() ); + +#ifndef NDEBUG + if ( !edit ) + kdWarning() << "KURLRequester's lineedit is not a KLineEdit!??\n"; +#endif + + KEditListBox::CustomEditor editor( this, edit ); + return editor; +} +*/ +void KURLRequester::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +/*US +KURLComboRequester::KURLComboRequester( QWidget *parent, + const char *name ) + : KURLRequester( new KComboBox(false), parent, name) +{ +} +*/ + +//US #include "kurlrequester.moc" diff --git a/microkde/kio/kfile/kurlrequester.h b/microkde/kio/kfile/kurlrequester.h new file mode 100644 index 0000000..3253dd5 --- a/dev/null +++ b/microkde/kio/kfile/kurlrequester.h @@ -0,0 +1,269 @@ +/* This file is part of the KDE libraries + Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org> + + library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#ifndef KURLREQUESTER_H +#define KURLREQUESTER_H + +#include <qhbox.h> + +#include <keditlistbox.h> +//US #include <kfile.h> +//US #include <kpushbutton.h> +#include <kurl.h> + +//US class KComboBox; + +class KFileDialog; +class KLineEdit; +//US class KURLCompletion; +class KURLDragPushButton; + +class QPushButton; +class QString; +class QTimer; + +/** + * This class is a widget showing a lineedit and a button, which invokes a + * filedialog. File name completion is available in the lineedit. + * + * The defaults for the filedialog are to ask for one existing local file, i.e. + * KFileDialog::setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly ) + * The default filter is "*", i.e. show all files, and the start directory is + * the current working directory, or the last directory where a file has been + * selected. + * + * You can change this behavior by using @ref setMode() or @ref setFilter(). + * + * @short A widget to request a filename/url from the user + * @author Carsten Pfeiffer <pfeiffer@kde.org> + */ +class KURLRequester : public QHBox +{ + Q_OBJECT + Q_PROPERTY( QString url READ url WRITE setURL ) + +public: + /** + * Constructs a KURLRequester widget. + */ + KURLRequester( QWidget *parent=0, const char *name=0 ); + + /** + * Constructs a KURLRequester widget with the initial URL @p url. + */ + KURLRequester( const QString& url, QWidget *parent=0, const char *name=0 ); + + /** + * Special constructor, which creates a KURLRequester widget with a custom + * edit-widget. The edit-widget can be either a KComboBox or a KLineEdit + * (or inherited thereof). Note: for geometry management reasons, the + * edit-widget is reparented to have the KURLRequester as parent. + * @param modal specifies whether the filedialog should be opened as modal + * or not. + */ +//US KURLRequester( QWidget *editWidget, QWidget *parent, const char *name=0 ); + /** + * Destructs the KURLRequester. + */ + ~KURLRequester(); + + /** + * @returns the current url in the lineedit. May be malformed, if the user + * entered something weird. ~user or environment variables are substituted + * for local files. + */ + QString url() const; + + /** + * Enables/disables showing file:/ in the lineedit, when a local file has + * been selected in the filedialog or was set via @ref setURL(). + * Default is false, not showing file:/ + * @see #showLocalProtocol + */ + void setShowLocalProtocol( bool b ); + + /** + * Sets the mode of the file dialog. + * Note: you can only select one file with the filedialog, + * so KFile::Files doesn't make much sense. + * @see KFileDialog::setMode() + */ + void setMode( unsigned int m ); + + /** + * Sets the filter for the file dialog. + * @see KFileDialog::setFilter() + */ + void setFilter( const QString& filter ); + + /** + * @returns whether local files will be prefixed with file:/ in the + * lineedit + * @see #setShowLocalProtocol + */ + bool showLocalProtocol() const { return myShowLocalProt; } + + /** + * @returns a pointer to the filedialog + * You can use this to customize the dialog, e.g. to specify a filter. + * Never returns 0L. + */ + virtual KFileDialog * fileDialog() const; + + /** + * @returns a pointer to the lineedit, either the default one, or the + * special one, if you used the special constructor. + * + * It is provided so that you can e.g. set an own completion object + * (e.g. @ref KShellCompletion) into it. + */ + KLineEdit * lineEdit() const; + + /** + * @returns a pointer to the combobox, in case you have set one using the + * special constructor. Returns 0L otherwise. + */ +//US KComboBox * comboBox() const; + + /** + * @returns a pointer to the pushbutton. It is provided so that you can + * specify an own pixmap or a text, if you really need to. + */ + QPushButton * button() const; + + /** + * @returns the KURLCompletion object used in the lineedit/combobox. + */ +//US KURLCompletion *completionObject() const { return myCompletion; } + + /** + * @returns an object, suitable for use with KEditListBox. It allows you + * to put this KURLRequester into a KEditListBox. + * Basically, do it like this: + * <pre> + * KURLRequester *req = new KURLRequester( someWidget ); + * [...] + * KEditListBox *editListBox = new KEditListBox( i18n("Some Title"), req->customEditor(), someWidget ); + * </pre> + * @since 3.1 + */ +//US KEditListBox::CustomEditor customEditor(); + +public slots: + /** + * Sets the url in the lineedit to @p url. Depending on the state of + * @ref showLocalProtocol(), file:/ on local files will be shown or not. + * @since 3.1 + */ + void setURL( const QString& url ); + + /** + * @reimp + * Sets the caption of the file dialog. + * @since 3.1 + */ + virtual void setCaption( const QString& caption ); + + /** + * Clears the lineedit/combobox. + */ + void clear(); + +signals: + // forwards from LineEdit + /** + * Emitted when the text in the lineedit changes. + * The parameter contains the contents of the lineedit. + * @since 3.1 + */ + void textChanged( const QString& ); + + /** + * Emitted when return or enter was pressed in the lineedit. + */ + void returnPressed(); + + /** + * Emitted when return or enter was pressed in the lineedit. + * The parameter contains the contents of the lineedit. + */ + void returnPressed( const QString& ); + + /** + * Emitted before the filedialog is going to open. Connect + * to this signal to "configure" the filedialog, e.g. set the + * filefilter, the mode, a preview-widget, etc. It's usually + * not necessary to set a URL for the filedialog, as it will + * get set properly from the editfield contents. + * + * If you use multiple KURLRequesters, you can connect all of them + * to the same slot and use the given KURLRequester pointer to know + * which one is going to open. + */ + void openFileDialog( KURLRequester * ); + + /** + * Emitted when the user changed the URL via the file dialog. + * The parameter contains the contents of the lineedit. + */ + void urlSelected( const QString& ); + +protected: + void init(); + +//US KURLCompletion * myCompletion; + + +private: + KURLDragPushButton * myButton; + bool myShowLocalProt; + mutable KFileDialog * myFileDialog; + + +protected slots: + /** + * Called when the button is pressed to open the filedialog. + * Also called when @ref KStdAccel::Open (default is Ctrl-O) is pressed. + */ + void slotOpenDialog(); + +private slots: + void slotUpdateURL(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KURLRequesterPrivate; + KURLRequesterPrivate *d; +}; +/*US +class KURLComboRequester : public KURLRequester // For use in Qt Designer +{ + Q_OBJECT +public: +*/ + /** + * Constructs a KURLRequester widget with a combobox. + */ +/*US + KURLComboRequester( QWidget *parent=0, const char *name=0 ); +}; +*/ + +#endif // KURLREQUESTER_H diff --git a/microkde/klineedit.h b/microkde/klineedit.h new file mode 100644 index 0000000..65e2f59 --- a/dev/null +++ b/microkde/klineedit.h @@ -0,0 +1,24 @@ +#ifndef MINIKDE_KLINEEDIT_H +#define MINIKDE_KLINEEDIT_H + +#include <qlineedit.h> + +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#endif + + +class KLineEdit : public QLineEdit +{ + public: + KLineEdit( QWidget *parent=0, const char *name=0 ) : + QLineEdit( parent, name ) { +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( this, QPEApplication::RightOnHold ); +#endif +} + + void setTrapReturnKey( bool ) {} +}; + +#endif diff --git a/microkde/klineeditdlg.h b/microkde/klineeditdlg.h new file mode 100644 index 0000000..68e9252 --- a/dev/null +++ b/microkde/klineeditdlg.h @@ -0,0 +1,34 @@ +#ifndef MICROKDE_KLINEEDITDLG_H +#define MICROKDE_KLINEEDITDLG_H + +#include "kdialogbase.h" +#include <klineedit.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qdialog.h> +#include <qpushbutton.h> + +class KLineEditDlg : public QDialog +{ + public: + KLineEditDlg( const QString & text, const QString & editText, QWidget *parent ) : + QDialog( parent,"lineedit", true ) { + QLabel* lab = new QLabel( text, this ); + mEdit = new KLineEdit( this ); + QVBoxLayout* vl = new QVBoxLayout( this ); + vl->setSpacing(5); + vl->setMargin(7); + vl->addWidget( lab ); + vl->addWidget( mEdit ); + mEdit->setText( editText ); + QPushButton * p = new QPushButton (" OK ", this ); + vl->addWidget( p ); + connect( p, SIGNAL ( clicked () ), this , SLOT (accept() ) ); + } + + QString text() { return mEdit->text(); } + private: + KLineEdit* mEdit; +}; + +#endif diff --git a/microkde/kmessagebox.cpp b/microkde/kmessagebox.cpp new file mode 100644 index 0000000..f06708a --- a/dev/null +++ b/microkde/kmessagebox.cpp @@ -0,0 +1,90 @@ +#include "kmessagebox.h" +#include "klocale.h" + +#include <qmessagebox.h> + +void KMessageBox::sorry( QWidget *parent, + const QString &text, + const QString &caption, bool ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Sorry"); + } + + QMessageBox::warning( parent, cap, text ); +} + +int KMessageBox::warningContinueCancel( QWidget *parent, + const QString &text, + const QString &caption, + const QString &buttonContinue, + const QString &dontAskAgainName, + bool notify ) +{ + QString cap = caption; + + int result = QMessageBox::warning( parent, cap, text, buttonContinue, + dontAskAgainName); + + if ( result == 0 ) return KMessageBox::Continue; + return KMessageBox::Cancel; +} + +int KMessageBox::warningYesNoCancel( QWidget *parent, + const QString &text, + const QString &caption, + const QString &buttonYes, + const QString &buttonNo ) +{ + QString cap = caption; + + int result = QMessageBox::warning( parent, cap, text,buttonYes ,buttonNo, + i18n("Cancel") ); + + if ( result == 0 ) return KMessageBox::Yes; + else if ( result == 1 ) return KMessageBox::No; + return KMessageBox::Cancel; +} + +int KMessageBox::questionYesNo(QWidget *parent, + const QString &text, + const QString &caption) +{ + QString cap = caption; + + int result = QMessageBox::warning( parent, cap, text, i18n("Yes"), + i18n("No") ); + + if ( result == 0 ) return KMessageBox::Yes; + else return KMessageBox::No; +} + +void KMessageBox::error( QWidget *parent, + const QString &text, + const QString &caption, bool notify ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Error"); + } + + QMessageBox::critical( parent, cap, text ); +} + +void KMessageBox::information( QWidget *parent, + const QString &text, + const QString &caption, + const QString &, + bool ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Information"); + } + + QMessageBox::information( parent, cap, text ); +} diff --git a/microkde/kmessagebox.h b/microkde/kmessagebox.h new file mode 100644 index 0000000..01d83b1 --- a/dev/null +++ b/microkde/kmessagebox.h @@ -0,0 +1,47 @@ +#ifndef MINIKDE_KMESSAGEBOX_H +#define MINIKDE_KMESSAGEBOX_H + +#include <qstring.h> + +#include "klocale.h" +class QWidget; + +class KMessageBox +{ + public: + enum { Ok = 1, Cancel = 2, Yes = 3, No = 4, Continue = 5 }; + + static void sorry(QWidget *parent, + const QString &text, + const QString &caption = QString::null, bool notify=true); + + static int warningContinueCancel(QWidget *parent, + const QString &text, + const QString &caption = i18n("Warning"), + const QString &buttonContinue =i18n("Continue"), + const QString &dontAskAgainName = i18n("Cancel"), + bool notify=true ); + + static int warningYesNoCancel(QWidget *parent, + const QString &text, + const QString &caption = i18n("Warning"), + const QString &buttonYes = i18n("Yes"), + const QString &buttonNo = i18n("No")); + + static int questionYesNo(QWidget *parent, + const QString &text, + const QString &caption = i18n("Question")); + + static void error(QWidget *parent, + const QString &text, + const QString &caption = i18n("Error"), bool notify=true); + + static void information(QWidget *parent, + const QString &text, + const QString &caption = i18n("Information"), + const QString &dontShowAgainName = QString::null, + bool notify=true); +}; + + +#endif diff --git a/microkde/knotifyclient.h b/microkde/knotifyclient.h new file mode 100644 index 0000000..118026a --- a/dev/null +++ b/microkde/knotifyclient.h @@ -0,0 +1,14 @@ +#ifndef MINIKDE_KNOTIFYCLIENT_H +#define MINIKDE_KNOTIFYCLIENT_H + +#include <qstring.h> + +class KNotifyClient +{ + public: + + static void beep() {} + static void beep( const QString & ) {} +}; + +#endif diff --git a/microkde/kprinter.h b/microkde/kprinter.h new file mode 100644 index 0000000..b99d689 --- a/dev/null +++ b/microkde/kprinter.h @@ -0,0 +1,8 @@ +#ifndef MINIKDE_KPRINTER_H +#define MINIKDE_KPRINTER_H + +#include <qprinter.h> + +#define KPrinter QPrinter + +#endif diff --git a/microkde/kprocess.cpp b/microkde/kprocess.cpp new file mode 100644 index 0000000..665d0bd --- a/dev/null +++ b/microkde/kprocess.cpp @@ -0,0 +1,19 @@ +#include "kprocess.h" + +void KProcess::clearArguments() +{ +// mProcess.clearArguments(); +} + +KProcess & KProcess::operator<<( const QString &arg ) +{ +// mProcess.addArgument( arg ); + + return *this; +} + +bool KProcess::start( KProcess::RunMode ) +{ +// return mProcess.start(); + return false; +} diff --git a/microkde/kprocess.h b/microkde/kprocess.h new file mode 100644 index 0000000..dffe96d --- a/dev/null +++ b/microkde/kprocess.h @@ -0,0 +1,22 @@ +#ifndef MINIKDE_KPROCESS_H +#define MINIKDE_KPROCESS_H + +#include <qobject.h> +//#include <qpe/qprocess.h> + +class KProcess : public QObject +{ + public: + enum RunMode { DontCare, NotifyOnExit, Block }; + + void clearArguments(); + + KProcess & operator<<( const QString & ); + + bool start( RunMode mode = DontCare ); + + private: +// QProcess mProcess; +}; + +#endif diff --git a/microkde/kresources/configdialog.cpp b/microkde/kresources/configdialog.cpp new file mode 100644 index 0000000..48d9137 --- a/dev/null +++ b/microkde/kresources/configdialog.cpp @@ -0,0 +1,137 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <klocale.h> +#include <kglobal.h> +#include <kmessagebox.h> + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> + +#include <qcheckbox.h> + +#include <kbuttonbox.h> +#include <kdialog.h> +#include <klineedit.h> + +#include "factory.h" +#include "configwidget.h" +#include "configdialog.h" + +using namespace KRES; + +ConfigDialog::ConfigDialog( QWidget *parent, const QString& resourceFamily, + /*const QString& type,*/ Resource* resource, /*KConfig *config, */const char *name ) + : KDialogBase( parent, name, true, i18n( "Resource Configuration" ), + Ok|Cancel, Ok, true )/*, mConfig( config )*/, mResource( resource ) +{ + Factory *factory = Factory::self( resourceFamily ); + +//US resize( 250, 240 ); + resize( KMIN(KGlobal::getDesktopWidth(), 250), KMIN(KGlobal::getDesktopHeight(), 240)); + +//US QFrame *main = makeMainWidget(); + QFrame *main = plainPage(); + + QVBoxLayout *mainLayout = new QVBoxLayout( main, 0, spacingHint() ); + + QGroupBox *generalGroupBox = new QGroupBox( 2, Qt::Horizontal, main ); + generalGroupBox->layout()->setSpacing( spacingHint() ); + generalGroupBox->setTitle( i18n( "General Settings" ) ); + + new QLabel( i18n( "Name:" ), generalGroupBox ); + + mName = new KLineEdit( generalGroupBox ); + + mReadOnly = new QCheckBox( i18n( "Read-only" ), generalGroupBox ); + + mName->setText( mResource->resourceName() ); + mReadOnly->setChecked( mResource->readOnly() ); + + mainLayout->addWidget( generalGroupBox ); + + QGroupBox *resourceGroupBox = new QGroupBox( 2, Qt::Horizontal, main ); + resourceGroupBox->layout()->setSpacing( spacingHint()); + resourceGroupBox->setTitle( i18n( "%1 Resource Settings" ) + .arg( factory->typeName( resource->type() ) ) ); + mainLayout->addWidget( resourceGroupBox ); + + mainLayout->addStretch(); + + mConfigWidget = factory->configWidget( resource->type(), resourceGroupBox ); + if ( mConfigWidget ) { + mConfigWidget->setInEditMode( false ); + mConfigWidget->loadSettings( mResource ); + mConfigWidget->show(); + connect( mConfigWidget, SIGNAL( setReadOnly( bool ) ), + SLOT( setReadOnly( bool ) ) ); + } + + connect( mName, SIGNAL( textChanged(const QString &)), + SLOT( slotNameChanged(const QString &))); + + slotNameChanged( mName->text() ); + +//US setMinimumSize( 400, 250 ); + setMinimumSize( KMIN(KGlobal::getDesktopWidth(), 400), KMIN(KGlobal::getDesktopHeight(), 250)); + +} + +void ConfigDialog::setInEditMode( bool value ) +{ + if ( mConfigWidget ) + mConfigWidget->setInEditMode( value ); +} + +void ConfigDialog::slotNameChanged( const QString &text) +{ + enableButtonOK( !text.isEmpty() ); +} + +void ConfigDialog::setReadOnly( bool value ) +{ + mReadOnly->setChecked( value ); +} + +void ConfigDialog::accept() +{ + if ( mName->text().isEmpty() ) { + KMessageBox::sorry( this, i18n( "Please enter a resource name" ) ); + return; + } + + mResource->setResourceName( mName->text() ); + mResource->setReadOnly( mReadOnly->isChecked() ); + + if ( mConfigWidget ) { + // First save generic information + // Also save setting of specific resource type + mConfigWidget->saveSettings( mResource ); + } + + KDialog::accept(); +} + +//US #include "configdialog.moc" diff --git a/microkde/kresources/configdialog.h b/microkde/kresources/configdialog.h new file mode 100644 index 0000000..6acc5d9 --- a/dev/null +++ b/microkde/kresources/configdialog.h @@ -0,0 +1,60 @@ +/* + This file is part of libkresources. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_CONFIGDIALOG_H +#define KRESOURCES_CONFIGDIALOG_H + +#include <kdialogbase.h> + +class KLineEdit; +class QCheckBox; +class KButtonBox; + +namespace KRES { + class Resource; + class ConfigWidget; + +class ConfigDialog : public KDialogBase +{ + Q_OBJECT + public: + // Resource=0: create new resource + ConfigDialog( QWidget *parent, const QString& resourceFamily, + Resource* resource, const char *name = 0); + + void setInEditMode( bool value ); + + protected slots: + void accept(); + void setReadOnly( bool value ); + void slotNameChanged( const QString &text); + + private: + ConfigWidget *mConfigWidget; + Resource* mResource; + + KLineEdit *mName; + QCheckBox *mReadOnly; +}; + +} + +#endif diff --git a/microkde/kresources/configpage.cpp b/microkde/kresources/configpage.cpp new file mode 100644 index 0000000..0f1469d --- a/dev/null +++ b/microkde/kresources/configpage.cpp @@ -0,0 +1,507 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qgroupbox.h> +#include <qinputdialog.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <kapplication.h> +#include <kcombobox.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <kurlrequester.h> +#include <klistview.h> +#include <kbuttonbox.h> +//US #include <ktrader.h> + +#include "resource.h" +#include "configdialog.h" + +#include "configpage.h" + +//US +#include <qpushbutton.h> +#include <qfile.h> +#include <kglobal.h> + +using namespace KRES; + +class ConfigViewItem : public QCheckListItem +{ + public: + ConfigViewItem( QListView *parent, Resource* resource ) : + QCheckListItem( parent, resource->resourceName(), CheckBox ), + mResource( resource ), + mIsStandard( false ) + { + setText( 1, mResource->type() ); + setOn( mResource->isActive() ); + } + + void setStandard( bool value ) + { + setText( 2, ( value ? i18n( "Yes" ) : QString::null ) ); + mIsStandard = value; + } + + bool standard() const { return mIsStandard; } + bool readOnly() const { return mResource->readOnly(); } + + Resource *resource() { return mResource; } + + private: + Resource* mResource; + + bool mIsStandard; +}; + +ConfigPage::ConfigPage( QWidget *parent, const char *name ) + : QWidget( parent, name ), + mCurrentManager( 0 ), + mCurrentConfig( 0 ) +{ + setCaption( i18n( "Resource Configuration" ) ); + + QVBoxLayout *mainLayout = new QVBoxLayout( this ); + + QGroupBox *groupBox = new QGroupBox( i18n( "Resources" ), this ); + groupBox->setColumnLayout(0, Qt::Vertical ); + groupBox->layout()->setSpacing( 6 ); + groupBox->layout()->setMargin( 11 ); + QGridLayout *groupBoxLayout = new QGridLayout( groupBox->layout(), 2, 2 ); + +//US mFamilyCombo = new KComboBox( false, groupBox ); + mFamilyCombo = new KComboBox( groupBox ); + groupBoxLayout->addMultiCellWidget( mFamilyCombo, 0, 0, 0, 1 ); + + mListView = new KListView( groupBox ); + mListView->setAllColumnsShowFocus( true ); + mListView->addColumn( i18n( "Name" ) ); + mListView->addColumn( i18n( "Type" ) ); + mListView->addColumn( i18n( "Standard" ) ); + + groupBoxLayout->addWidget( mListView, 1, 0 ); + + KButtonBox *buttonBox = new KButtonBox( groupBox, Vertical ); + mAddButton = buttonBox->addButton( i18n( "&Add..." ), this, SLOT(slotAdd()) ); + mRemoveButton = buttonBox->addButton( i18n( "&Remove" ), this, SLOT(slotRemove()) ); + mRemoveButton->setEnabled( false ); + mEditButton = buttonBox->addButton( i18n( "&Edit..." ), this, SLOT(slotEdit()) ); + mEditButton->setEnabled( false ); + mStandardButton = buttonBox->addButton( i18n( "&Use as Standard" ), this, SLOT(slotStandard()) ); + mStandardButton->setEnabled( false ); + buttonBox->layout(); + + groupBoxLayout->addWidget( buttonBox, 1, 1 ); + + mainLayout->addWidget( groupBox ); + + connect( mFamilyCombo, SIGNAL( activated( int ) ), + SLOT( slotFamilyChanged( int ) ) ); + connect( mListView, SIGNAL( selectionChanged() ), + SLOT( slotSelectionChanged() ) ); + connect( mListView, SIGNAL( clicked( QListViewItem * ) ), + SLOT( slotItemClicked( QListViewItem * ) ) ); + + mLastItem = 0; + +//US mConfig = new KConfig( "kcmkresourcesrc" ); + mConfig = new KConfig( locateLocal( "config", "kcmkresourcesrc") ); + mConfig->setGroup( "General" ); + + load(); +} + +ConfigPage::~ConfigPage() +{ + QValueList<ResourcePageInfo>::Iterator it; + for ( it = mInfoMap.begin(); it != mInfoMap.end(); ++it ) { + (*it).mManager->removeListener( this ); + delete (*it).mManager; + delete (*it).mConfig; + } + + mConfig->writeEntry( "CurrentFamily", mFamilyCombo->currentItem() ); + delete mConfig; + mConfig = 0; +} + +void ConfigPage::load() +{ + kdDebug(5650) << "ConfigPage::load()" << endl; + + mListView->clear(); + +//US we remove the dynamic pluginloader, and set the one family we need (contact) manually. + +//US KTrader::OfferList plugins = KTrader::self()->query( "KResources/Plugin" ); +//US KTrader::OfferList::ConstIterator it; +//US for ( it = plugins.begin(); it != plugins.end(); ++it ) { +//US QVariant tmp = (*it)->property( "X-KDE-ResourceFamily" ); +//US QString family = tmp.toString(); + + QString family = "contact"; + if ( !family.isEmpty() ) { + if ( !mFamilyMap.contains( family ) ) { + mCurrentManager = new Manager<Resource>( family ); + if ( mCurrentManager ) { + mFamilyMap.append( family ); + mCurrentManager->addListener( this ); + + ResourcePageInfo info; + info.mManager = mCurrentManager; + QString configDir = KGlobal::dirs()->saveLocation( "config" ); + //QString configDir = KStandardDirs::appDir() + "/config"; + if ( family == "contact" && QFile::exists( configDir + "/kabcrc" ) ) { + info.mConfig = new KConfig( locateLocal( "config", "kabcrc" ) ); + } else if ( family == "calendar" && QFile::exists( configDir + "/kcalrc" ) ) { + info.mConfig = new KConfig( locateLocal( "config", "kcalrc" ) ); + } else { + QString configFile = locateLocal( "config", QString( "kresources/%1/stdrc" ).arg( family ) ); + info.mConfig = new KConfig( configFile ); + } + info.mManager->readConfig( info.mConfig ); + + mInfoMap.append( info ); + } + } + } +//US } + mCurrentManager = 0; + + mFamilyCombo->insertStringList( mFamilyMap ); + + int currentFamily = mConfig->readNumEntry( "CurrentFamily", 0 ); + mFamilyCombo->setCurrentItem( currentFamily ); + slotFamilyChanged( currentFamily ); +} + +void ConfigPage::save() +{ + saveResourceSettings(); + + QValueList<ResourcePageInfo>::Iterator it; + for ( it = mInfoMap.begin(); it != mInfoMap.end(); ++it ) + (*it).mManager->writeConfig( (*it).mConfig ); + + emit changed( false ); +} + +void ConfigPage::defaults() +{ +} + +void ConfigPage::slotFamilyChanged( int pos ) +{ + if ( pos < 0 || pos >= (int)mFamilyMap.count() ) + return; + + saveResourceSettings(); + + mFamily = mFamilyMap[ pos ]; + +//US qDebug("ConfigPage::slotFamilyChanged 4 family=%s", mFamily.latin1()); + + mCurrentManager = mInfoMap[ pos ].mManager; + mCurrentConfig = mInfoMap[ pos ].mConfig; + + if ( !mCurrentManager ) + kdDebug(5650) << "ERROR: cannot create ResourceManager<Resource>( mFamily )" << endl; + + mListView->clear(); + + if ( mCurrentManager->isEmpty() ) { +//US qDebug("ConfigPage::slotFamilyChanged 4.1 mCurrentManager=%ul", mCurrentManager ); + + defaults(); + } + + Resource *standardResource = mCurrentManager->standardResource(); + +//US qDebug("ConfigPage::slotFamilyChanged 4.4 resourcename=%s", standardResource->resourceName().latin1()); + + + Manager<Resource>::Iterator it; + for ( it = mCurrentManager->begin(); it != mCurrentManager->end(); ++it ) { + ConfigViewItem *item = new ConfigViewItem( mListView, *it ); + if ( *it == standardResource ) + item->setStandard( true ); + } + + if ( mListView->childCount() == 0 ) { +//US qDebug("ConfigPage::slotFamilyChanged 4.5 "); + + defaults(); + emit changed( true ); + mCurrentManager->writeConfig( mCurrentConfig ); + } else { +//US qDebug("ConfigPage::slotFamilyChanged 4.6 "); + + if ( !standardResource ) { + KMessageBox::sorry( this, i18n( "There is no standard resource! Please select one." ) ); + +//US qDebug("ConfigPage::slotFamilyChanged 4.7" ); + + } + + emit changed( false ); + } +} + +void ConfigPage::slotAdd() +{ + if ( !mCurrentManager ) + return; + + QStringList types = mCurrentManager->resourceTypeNames(); + QStringList descs = mCurrentManager->resourceTypeDescriptions(); + bool ok = false; + QString desc = QInputDialog::getItem( i18n( "Resource Configuration" ), + i18n( "Please select type of the new resource:" ), descs, 0, + false, &ok, this ); + if ( !ok ) + return; + + QString type = types[ descs.findIndex( desc ) ]; + + // Create new resource + Resource *resource = mCurrentManager->createResource( type ); + if ( !resource ) { + KMessageBox::error( this, i18n("Unable to create resource of type '%1'.") + .arg( type ) ); + return; + } + + resource->setResourceName( type + "-resource" ); + + ConfigDialog dlg( this, mFamily, resource, "KRES::ConfigDialog" ); + + if ( dlg.exec() ) { + mCurrentManager->add( resource ); + + ConfigViewItem *item = new ConfigViewItem( mListView, resource ); + + mLastItem = item; + + // if there are only read-only resources we'll set this resource + // as standard resource + if ( !resource->readOnly() ) { + bool onlyReadOnly = true; + QListViewItem *it = mListView->firstChild(); + while ( it != 0 ) { + ConfigViewItem *confIt = static_cast<ConfigViewItem*>( it ); + if ( !confIt->readOnly() && confIt != item ) + onlyReadOnly = false; + + it = it->itemBelow(); + } + + if ( onlyReadOnly ) + item->setStandard( true ); + } + + emit changed( true ); + } else { + delete resource; + resource = 0; + } +} + +void ConfigPage::slotRemove() +{ + if ( !mCurrentManager ) + return; + + QListViewItem *item = mListView->currentItem(); + ConfigViewItem *confItem = static_cast<ConfigViewItem*>( item ); + + if ( !confItem ) + return; + + if ( confItem->standard() ) { + KMessageBox::sorry( this, i18n( "You cannot remove your standard resource!\n Please select a new standard resource first." ) ); + return; + } + + mCurrentManager->remove( confItem->resource() ); + + if ( item == mLastItem ) + mLastItem = 0; + + mListView->takeItem( item ); + delete item; + + emit changed( true ); +} + +void ConfigPage::slotEdit() +{ + if ( !mCurrentManager ) + return; + + QListViewItem *item = mListView->currentItem(); + ConfigViewItem *configItem = static_cast<ConfigViewItem*>( item ); + if ( !configItem ) + return; + + Resource *resource = configItem->resource(); + + ConfigDialog dlg( this, mFamily, resource, "KRES::ConfigDialog" ); + + if ( dlg.exec() ) { + configItem->setText( 0, resource->resourceName() ); + configItem->setText( 1, resource->type() ); + + if ( configItem->standard() && configItem->readOnly() ) { + KMessageBox::sorry( this, i18n( "You cannot use a read-only resource as standard!" ) ); + configItem->setStandard( false ); + } + + mCurrentManager->resourceChanged( resource ); + emit changed( true ); + } +} + +void ConfigPage::slotStandard() +{ + if ( !mCurrentManager ) + return; + + ConfigViewItem *item = static_cast<ConfigViewItem*>( mListView->currentItem() ); + if ( !item ) + return; + + if ( item->readOnly() ) { + KMessageBox::sorry( this, i18n( "You cannot use a read-only resource as standard!" ) ); + return; + } + + if ( !item->isOn() ) { + KMessageBox::sorry( this, i18n( "You cannot use an inactive resource as standard!" ) ); + return; + } + + QListViewItem *it = mListView->firstChild(); + while ( it != 0 ) { + ConfigViewItem *configItem = static_cast<ConfigViewItem*>( it ); + if ( configItem->standard() ) + configItem->setStandard( false ); + it = it->itemBelow(); + } + + item->setStandard( true ); + mCurrentManager->setStandardResource( item->resource() ); + emit changed( true ); + +} + +void ConfigPage::slotSelectionChanged() +{ + bool state = ( mListView->currentItem() != 0 ); + + mRemoveButton->setEnabled( state ); + mEditButton->setEnabled( state ); + mStandardButton->setEnabled( state ); +} + +void ConfigPage::resourceAdded( Resource* resource ) +{ + qDebug("ConfigPage::resourceAdded : %s", resource->resourceName().latin1()); + kdDebug(5650) << "ConfigPage::resourceAdded( " << resource->resourceName() << " )" << endl; + ConfigViewItem *item = new ConfigViewItem( mListView, resource ); + + // FIXME: this sucks. This should be in the config file, + // or application-dependent, in which case it's always Off + item->setOn( false ); + + mLastItem = item; + + emit changed( true ); +} + +void ConfigPage::resourceModified( Resource* resource ) +{ + qDebug("ConfigPage::resourceModified : %s", resource->resourceName().latin1()); + kdDebug(5650) << "ConfigPage::resourceModified( " << resource->resourceName() << " )" << endl; +} + +void ConfigPage::resourceDeleted( Resource* resource ) +{ + qDebug("ConfigPage::resourceDeleted : %s", resource->resourceName().latin1()); + kdDebug(5650) << "ConfigPage::resourceDeleted( " << resource->resourceName() << " )" << endl; +} + +void ConfigPage::slotItemClicked( QListViewItem *item ) +{ + ConfigViewItem *configItem = static_cast<ConfigViewItem *>( item ); + if ( !configItem ) return; + + if ( configItem->standard() && !configItem->isOn() ) { + KMessageBox::sorry( this, i18n( "You cannot deactivate the standard resource. Choose another standard resource first." ) ); + configItem->setOn( true ); + return; + } + + if ( configItem->isOn() != configItem->resource()->isActive() ) { + emit changed( true ); + } +} + +void ConfigPage::saveResourceSettings() +{ + qDebug("ConfigPage::saveResourceSettings() begin"); + + if ( mCurrentManager ) { + + QListViewItem *item = mListView->firstChild(); + while ( item ) { + ConfigViewItem *configItem = static_cast<ConfigViewItem*>( item ); + + // check if standard resource + if ( configItem->standard() && !configItem->readOnly() && + configItem->isOn() ) { + + mCurrentManager->setStandardResource( configItem->resource() ); + } + + // check if active or passive resource + configItem->resource()->setActive( configItem->isOn() ); + + item = item->nextSibling(); + } + mCurrentManager->writeConfig( mCurrentConfig ); + + if ( !mCurrentManager->standardResource() ) + KMessageBox::sorry( this, i18n( "There is no valid standard resource! Please select one which is neither read-only nor inactive." ) ); + } + + qDebug("ConfigPage::saveResourceSettings() end"); + +} + +//US #include "configpage.moc" + diff --git a/microkde/kresources/configpage.h b/microkde/kresources/configpage.h new file mode 100644 index 0000000..492ea54 --- a/dev/null +++ b/microkde/kresources/configpage.h @@ -0,0 +1,103 @@ +/* + This file is part of libkresources. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#ifndef KRESOURCES_CONFIGPAGE_H +#define KRESOURCES_CONFIGPAGE_H + +#include <qstringlist.h> +#include <qwidget.h> + +#include "manager.h" + +class KComboBox; +class KListView; + +class QListViewItem; +class QPushButton; + + +namespace KRES { + +class ResourcePageInfo +{ + public: + Manager<Resource> *mManager; + KConfig *mConfig; +}; + +class Resource; + +class ConfigPage : public QWidget, public ManagerListener<Resource> +{ + Q_OBJECT + + public: + ConfigPage( QWidget *parent = 0, const char *name = 0 ); + virtual ~ConfigPage(); + + void load(); + void save(); + virtual void defaults(); + + public slots: + void slotFamilyChanged( int ); + void slotAdd(); + void slotRemove(); + void slotEdit(); + void slotStandard(); + void slotSelectionChanged(); + + // From ManagerListener<Resource> + public: + virtual void resourceAdded( Resource* resource ); + virtual void resourceModified( Resource* resource ); + virtual void resourceDeleted( Resource* resource ); + + protected slots: + void slotItemClicked( QListViewItem * ); + + signals: + void changed( bool ); + + private: + void saveResourceSettings(); + + Manager<Resource>* mCurrentManager; + KConfig* mCurrentConfig; + KConfig* mConfig; + QString mFamily; + QStringList mFamilyMap; + QValueList<ResourcePageInfo> mInfoMap; + + KComboBox* mFamilyCombo; + KListView* mListView; + QPushButton* mAddButton; + QPushButton* mRemoveButton; + QPushButton* mEditButton; + QPushButton* mStandardButton; + + QListViewItem* mLastItem; +}; + +} + +#endif diff --git a/microkde/kresources/configwidget.cpp b/microkde/kresources/configwidget.cpp new file mode 100644 index 0000000..c42cbd4 --- a/dev/null +++ b/microkde/kresources/configwidget.cpp @@ -0,0 +1,45 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "configwidget.h" + +using namespace KRES; + +ConfigWidget::ConfigWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ +} + +void ConfigWidget::setInEditMode( bool ) +{ +} + +void ConfigWidget::loadSettings( Resource * ) +{ +} + +void ConfigWidget::saveSettings( Resource * ) +{ +} + +//US #include "configwidget.moc" diff --git a/microkde/kresources/configwidget.h b/microkde/kresources/configwidget.h new file mode 100644 index 0000000..04dd696 --- a/dev/null +++ b/microkde/kresources/configwidget.h @@ -0,0 +1,59 @@ +/* + This file is part of libkresources. + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_CONFIGWIDGET_H +#define KRESOURCES_CONFIGWIDGET_H + +#include <qwidget.h> + +#include <kconfig.h> + +#include "resource.h" + +namespace KRES { + +class ConfigWidget : public QWidget +{ + Q_OBJECT + +public: + ConfigWidget( QWidget *parent = 0, const char *name = 0 ); + + /** + Sets the widget to 'edit' mode. Reimplement this method if you are + interested in the mode change (to disable some GUI element for + example). By default the widget is in 'create new' mode. + */ + virtual void setInEditMode( bool value ); + +public slots: + virtual void loadSettings( Resource *resource ); + virtual void saveSettings( Resource *resource ); + +signals: + void setReadOnly( bool value ); + +protected: + Resource* mResource; +}; + +} +#endif diff --git a/microkde/kresources/factory.cpp b/microkde/kresources/factory.cpp new file mode 100644 index 0000000..709cd4a --- a/dev/null +++ b/microkde/kresources/factory.cpp @@ -0,0 +1,216 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> +#include <klocale.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <kstaticdeleter.h> + +#include <qfile.h> + +#include <plugins/file/resourcefile.h> +#include <plugins/file/resourcefileconfig.h> +#include <plugins/dir/resourcedir.h> +#include <plugins/dir/resourcedirconfig.h> +//#include <plugins/ldap/resourceldap.h> +//#include <plugins/ldap/resourceldapconfig.h> + + +#include "resource.h" +#include "factory.h" + +using namespace KRES; + +QDict<Factory> *Factory::mSelves = 0; +static KStaticDeleter< QDict<Factory> > staticDeleter; + +Factory *Factory::self( const QString& resourceFamily ) +{ + kdDebug(5650) << "Factory::self()" << endl; + + Factory *factory = 0; + if ( !mSelves ) + { + mSelves = staticDeleter.setObject( new QDict<Factory> ); + } + + factory = mSelves->find( resourceFamily ); + + if ( !factory ) { + factory = new Factory( resourceFamily ); + mSelves->insert( resourceFamily, factory ); + } + + return factory; +} + +Factory::Factory( const QString& resourceFamily ) : + mResourceFamily( resourceFamily ) +{ +//US so far we have three types available for resourceFamily "contact" +// and that are "file", "dir", "ldap" +/*US + + KTrader::OfferList plugins = KTrader::self()->query( "KResources/Plugin", QString( "[X-KDE-ResourceFamily] == '%1'" ) + .arg( resourceFamily ) ); + KTrader::OfferList::ConstIterator it; + for ( it = plugins.begin(); it != plugins.end(); ++it ) { + QVariant type = (*it)->property( "X-KDE-ResourceType" ); + if ( !type.toString().isEmpty() ) + mTypeMap.insert( type.toString(), *it ); + } +*/ + +//US !!!!!!!!!!!!!!! + KRES::PluginFactoryBase* pf = (KRES::PluginFactoryBase*)new KRES::PluginFactory<KABC::ResourceFile,KABC::ResourceFileConfig>(); + mTypeMap.insert( "file", pf ); + + pf = (KRES::PluginFactoryBase*)new KRES::PluginFactory<KABC::ResourceDir,KABC::ResourceDirConfig>(); + mTypeMap.insert( "dir", pf ); + /* + pf = (KRES::PluginFactoryBase*)new KRES::PluginFactory<KABC::ResourceLDAP,KABC::ResourceLDAPConfig>(); + mTypeMap.insert( "ldap", pf ); + */ +} + +Factory::~Factory() +{ +} + +QStringList Factory::typeNames() const +{ +//US method QMap::keys() not available yet. SO collect the data manually +//US return mTypeMap.keys(); + + QStringList result; + + QMap<QString, PluginFactoryBase*>::ConstIterator it; + for( it = mTypeMap.begin(); it != mTypeMap.end(); ++it ) { + result << it.key().latin1(); +// qDebug("Factory::typeNames() : %s ", it.key().latin1()); + + } + return result; +} + +ConfigWidget *Factory::configWidget( const QString& type, QWidget *parent ) +{ + if ( type.isEmpty() || !mTypeMap.contains( type ) ) + return 0; + +/*US load the lib not dynamically. !! + KService::Ptr ptr = mTypeMap[ type ]; + KLibFactory *factory = KLibLoader::self()->factory( ptr->library().latin1() ); + if ( !factory ) { + kdDebug() << "KRES::Factory::configWidget(): Factory creation failed" << endl; + return 0; + } +*/ + PluginFactoryBase *factory = mTypeMap[ type ]; + if ( !factory ) { + kdDebug() << "KRES::Factory::configWidget(): Factory creation failed" << endl; + return 0; + } + + + PluginFactoryBase *pluginFactory = static_cast<PluginFactoryBase *>( factory ); + + if ( !pluginFactory ) { + kdDebug() << "KRES::Factory::configWidget(): no plugin factory." << endl; + return 0; + } + + ConfigWidget *wdg = pluginFactory->configWidget( parent ); + if ( !wdg ) { +//US kdDebug() << "'" << ptr->library() << "' is not a " + mResourceFamily + " plugin." << endl; + kdDebug() << " is not a " + mResourceFamily + " plugin." << endl; + return 0; + } + return wdg; + +} + +QString Factory::typeName( const QString &type ) const +{ + if ( type.isEmpty() || !mTypeMap.contains( type ) ) + return QString(); + +//US KService::Ptr ptr = mTypeMap[ type ]; +//US return ptr->name(); +//US I guess this is correct since we loaded the factory staticly. + return type; + +} + +QString Factory::typeDescription( const QString &type ) const +{ + if ( type.isEmpty() || !mTypeMap.contains( type ) ) + return QString(); + +//US KService::Ptr ptr = mTypeMap[ type ]; +//US return ptr->comment(); +//US I guess this is correct since we loaded the factory staticly. + return type; + +} + +Resource *Factory::resource( const QString& type, const KConfig *config ) +{ + kdDebug() << "Factory::resource( " << type << ", config)" << endl; + + if ( type.isEmpty() || !mTypeMap.contains( type ) ) + return 0; + +/*US load the lib not dynamicly. !! + KService::Ptr ptr = mTypeMap[ type ]; + KLibFactory *factory = KLibLoader::self()->factory( ptr->library().latin1() ); + if ( !factory ) { + kdDebug() << "KRES::Factory::resource(): Factory creation failed" << endl; + return 0; + } +*/ + PluginFactoryBase *factory = mTypeMap[ type ]; + if ( !factory ) { + kdDebug() << "KRES::Factory::resource(): Factory creation failed" << endl; + return 0; + } + + PluginFactoryBase *pluginFactory = static_cast<PluginFactoryBase *>( factory ); + + if ( !pluginFactory ) { + kdDebug() << "KRES::Factory::resource(): no plugin factory." << endl; + return 0; + } + + Resource *resource = pluginFactory->resource( config ); + if ( !resource ) { +//US kdDebug() << "'" << ptr->library() << "' is not a " + mResourceFamily + " plugin." << endl; + kdDebug() << " is not a " + mResourceFamily + " plugin." << endl; + return 0; + } + + resource->setType( type ); + + return resource; +} diff --git a/microkde/kresources/factory.h b/microkde/kresources/factory.h new file mode 100644 index 0000000..f391bb3 --- a/dev/null +++ b/microkde/kresources/factory.h @@ -0,0 +1,113 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_FACTORY_H +#define KRESOURCES_FACTORY_H + +#include <qdict.h> +#include <qstring.h> + +#include <kconfig.h> + + +#include "resource.h" + +namespace KRES { + +/** + * Class for loading resource plugins. + * Do not use this class directly. Use ResourceManager instead + * + * Example: + * + * <pre> + * KABC::Factory<Calendar> *factory = KABC::Factory<Calendar>::self(); + * + * QStringList list = factory->resources(); + * QStringList::Iterator it; + * for ( it = list.begin(); it != list.end(); ++it ) { + * Resource<Calendar> *resource = factory->resource( (*it), + * KABC::StdAddressBook::self(), 0 ); + * // do something with resource + * } + * </pre> + */ +class Factory +{ + public: + + /** + * Returns the global resource factory. + */ + static Factory *self( const QString& resourceFamily ); + + ~Factory(); + + /** + * Returns the config widget for the given resource type, + * or a null pointer if resource type doesn't exist. + * + * @param type The type of the resource, returned by @ref resources() + * @param resource The resource to be editted. + * @param parent The parent widget + */ + ConfigWidget *configWidget( const QString& type, QWidget *parent = 0 ); + + /** + * Returns a pointer to a resource object or a null pointer + * if resource type doesn't exist. + * + * @param type The type of the resource, returned by @ref resources() + * @param ab The address book, the resource should belong to + * @param config The config object where the resource get it settings from, or 0 if a new resource should be created. + */ + Resource *resource( const QString& type, const KConfig *config ); + + /** + * Returns a list of all available resource types. + */ + QStringList typeNames() const; + + /** + * Returns the name for a special type. + */ + QString typeName( const QString &type ) const; + + /** + * Returns the description for a special type. + */ + QString typeDescription( const QString &type ) const; + + protected: + Factory( const QString& resourceFamily ); + + private: + static QDict<Factory> *mSelves; + + QString mResourceFamily; +//US QMap<QString, KService::Ptr> mTypeMap; + QMap<QString, PluginFactoryBase*> mTypeMap; +}; + +} +#endif diff --git a/microkde/kresources/kcmkresources.cpp b/microkde/kresources/kcmkresources.cpp new file mode 100644 index 0000000..d600a31 --- a/dev/null +++ b/microkde/kresources/kcmkresources.cpp @@ -0,0 +1,89 @@ +/* + This file is part of libkresources. + + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qlayout.h> + +//US #include <kaboutdata.h> +//US #include <kgenericfactory.h> +#include <klocale.h> + +#include "configpage.h" + +#include "kcmkresources.h" + +using namespace KRES; + +//US typedef KGenericFactory<KCMKResources, QWidget> ResourcesFactory; +//US K_EXPORT_COMPONENT_FACTORY( kcm_kresources, ResourcesFactory( "kcmkresources" ) ); + +//US KCMKResources::KCMKResources( QWidget *parent, const char *name, const QStringList& ) +//US : KCModule( ResourcesFactory::instance(), parent, name ) +KCMKResources::KCMKResources( QWidget *parent, const char *name, const QStringList& ) + : KDialogBase( parent, name, true, i18n( "Configure Resources" ), + Ok|Cancel, Ok, true ) +{ + QFrame *main = plainPage(); + + QVBoxLayout *layout = new QVBoxLayout( main ); + mConfigPage = new KRES::ConfigPage( main ); + layout->addWidget( mConfigPage ); + + + connect( mConfigPage, SIGNAL( changed( bool ) ), SLOT( changed( bool ) ) ); +#ifndef DESKTOP_VERSION + showMaximized(); +#endif +} + +void KCMKResources::changed( bool changed) +{ + modified = changed; +} + +void KCMKResources::slotOk() +{ + if (modified) { + mConfigPage->save(); + modified = false; + } + + KDialogBase::slotOk(); +} + +void KCMKResources::load() +{ + qDebug("KCMKResources::load" ); + mConfigPage->load(); +} + +void KCMKResources::save() +{ + qDebug("KCMKResources::save" ); + mConfigPage->save(); +} + +void KCMKResources::defaults() +{ + qDebug("KCMKResources::defaults" ); + mConfigPage->defaults(); +} + +//US #include "kcmkresources.moc" diff --git a/microkde/kresources/kcmkresources.h b/microkde/kresources/kcmkresources.h new file mode 100644 index 0000000..a83bb33 --- a/dev/null +++ b/microkde/kresources/kcmkresources.h @@ -0,0 +1,54 @@ +/* + This file is part of libkresources. + + Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_KCMKRESOURCES_H +#define KRESOURCES_KCMKRESOURCES_H + +#include <kdialogbase.h> + +namespace KRES { + +class ConfigPage; + + +//US class KCMKResources : public KCModule +class KCMKResources : public KDialogBase +{ + Q_OBJECT + + public: + KCMKResources( QWidget *parent, const char *name, const QStringList& ); + + void load(); + void save(); + void defaults(); + + protected slots: + virtual void slotOk(); + void changed( bool ); + + private: + KRES::ConfigPage *mConfigPage; + bool modified; +}; + +} +#endif diff --git a/microkde/kresources/manager.h b/microkde/kresources/manager.h new file mode 100644 index 0000000..b5e97fc --- a/dev/null +++ b/microkde/kresources/manager.h @@ -0,0 +1,332 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_MANAGER_H +#define KRESOURCES_MANAGER_H + +#include <qdict.h> +#include <qstringlist.h> + +#include "factory.h" +#include "managerimpl.h" + +namespace KRES { + +class Resource; + +template<class T> +class ManagerListener +{ + public: + virtual void resourceAdded( T *resource ) = 0; + virtual void resourceModified( T *resource ) = 0; + virtual void resourceDeleted( T *resource ) = 0; +}; + +// TODO: +// The resource manager should provide some signals +// to warn applications that resources have been added, +// removed or modified. +// +// The manager should also keep track of which (or at least +// how many) applications hve opened a resource, so that it +// is only closed if none of them is using it any more + +template<class T> +class Manager : private ManagerImplListener +{ + public: + class Iterator + { + friend class Manager; + public: + Iterator() {}; + Iterator( const Iterator &it ) { mIt = it.mIt; } + + T *operator*() { return static_cast<T *>( *mIt ); } + Iterator &operator++() { mIt++; return *this; } + Iterator &operator++(int) { mIt++; return *this; } + Iterator &operator--() { mIt--; return *this; } + Iterator &operator--(int) { mIt--; return *this; } + bool operator==( const Iterator &it ) { return mIt == it.mIt; } + bool operator!=( const Iterator &it ) { return mIt != it.mIt; } + + private: + Resource::List::Iterator mIt; + }; + + Iterator begin() + { + Iterator it; + it.mIt = mImpl->resourceList()->begin(); + return it; + } + + Iterator end() + { + Iterator it; + it.mIt = mImpl->resourceList()->end(); + return it; + } + + class ActiveIterator + { + friend class Manager; + public: + ActiveIterator() : mList( 0 ) {}; + ActiveIterator( const ActiveIterator &it ) + { + mIt = it.mIt; + mList = it.mList; + } + + T *operator*() { return static_cast<T *>( *mIt ); } + ActiveIterator &operator++() + { + do { mIt++; } while ( checkActive() ); + return *this; + } + ActiveIterator &operator++(int) + { + do { mIt++; } while ( checkActive() ); + return *this; + } + ActiveIterator &operator--() + { + do { mIt--; } while ( checkActive() ); + return *this; + } + ActiveIterator &operator--(int) + { + do { mIt--; } while ( checkActive() ); + return *this; + } + bool operator==( const ActiveIterator &it ) { return mIt == it.mIt; } + bool operator!=( const ActiveIterator &it ) { return mIt != it.mIt; } + + private: + /** + Check if iterator needs to be advanced once more. + */ + bool checkActive() + { + if ( !mList || mIt == mList->end() ) return false; + return !(*mIt)->isActive(); + } + + Resource::List::Iterator mIt; + Resource::List *mList; + }; + + ActiveIterator activeBegin() + { + ActiveIterator it; + it.mIt = mImpl->resourceList()->begin(); + it.mList = mImpl->resourceList(); + if ( it.mIt != mImpl->resourceList()->end() ) { + if ( !(*it)->isActive() ) it++; + } + return it; + } + + ActiveIterator activeEnd() + { + ActiveIterator it; + it.mIt = mImpl->resourceList()->end(); + it.mList = mImpl->resourceList(); + return it; + } + + bool isEmpty() const { return mImpl->resourceList()->isEmpty(); } + + Manager( const QString &family ) + { + mFactory = Factory::self( family ); + // The managerimpl will use the same Factory object as the manager + // because of the Factory::self() pattern + mImpl = new ManagerImpl( family ); + mImpl->setListener( this ); + + mListeners = new QPtrList<ManagerListener<T> >; + } + + virtual ~Manager() + { + mImpl->setListener( 0 ); + delete mListeners; + delete mImpl; + } + + /** + Recreate Resource objects from configuration file. If cfg is 0, read standard + configuration file. + */ + void readConfig( KConfig *cfg = 0 ) + { + mImpl->readConfig( cfg ); + } + + /** + Write configuration of Resource objects to configuration file. If cfg is 0, write + to standard configuration file. + */ + void writeConfig( KConfig *cfg = 0 ) + { + mImpl->writeConfig( cfg ); + } + + /** + Add resource to manager. This passes ownership of the Resource object + to the manager. + */ + void add( Resource *resource ) + { + if ( resource ) mImpl->add( resource ); + } + + void remove( Resource *resource ) + { + if ( resource ) mImpl->remove( resource ); + } + + T* standardResource() + { + return static_cast<T *>( mImpl->standardResource() ); + } + + void setStandardResource( T *resource ) + { + if ( resource ) mImpl->setStandardResource( resource ); + } + + void setActive( Resource *resource, bool active ) + { + if ( resource ) mImpl->setActive( resource, active ); + } + + /** + Returns a list of the names of the reources managed by the + Manager for this family. + */ + QStringList resourceNames() const + { + return mImpl->resourceNames(); + } + + ConfigWidget *configWidget( const QString& type, QWidget *parent = 0 ) + { + return mFactory->resourceConfigWidget( type, parent ); + } + + /** + Creates a new resource of type @param type, with default + settings. The resource is + not added to the manager, the application has to do that. + Returns a pointer to a resource object or a null pointer + if resource type doesn't exist. + + @param type The type of the resource, one of those returned + by @ref resourceTypeNames() + */ + T *createResource( const QString& type ) + { + return (T *)( mFactory->resource( type, 0 ) ); + } + + /** + Returns a list of the names of all available resource types. + */ + QStringList resourceTypeNames() const + { + return mFactory->typeNames(); + } + + QStringList resourceTypeDescriptions() const + { + QStringList typeDescs; + QStringList types = mFactory->typeNames(); + + for ( QStringList::ConstIterator it = types.begin(); it != types.end(); ++it ) { + QString desc = mFactory->typeName( *it ); + if ( !mFactory->typeDescription( *it ).isEmpty() ) + desc += " (" + mFactory->typeDescription( *it ) + ")"; + + typeDescs.append( desc ); + } + + return typeDescs; + } + + void resourceChanged( T *resource ) + { + mImpl->resourceChanged( resource ); + } + + void addListener( ManagerListener<T> *listener ) + { + mListeners->append( listener ); + } + + void removeListener( ManagerListener<T> *listener ) + { + mListeners->remove( listener ); + } + + virtual void resourceAdded( Resource *res ) + { + kdDebug(5650) << "Manager::resourceAdded " << res->resourceName() << endl; + T* resource = (T *)( res ); + ManagerListener<T> *listener; + for ( listener = mListeners->first(); listener; listener = mListeners->next() ) + listener->resourceAdded( resource ); + } + + virtual void resourceModified( Resource *res ) + { + kdDebug(5650) << "Manager::resourceModified " << res->resourceName() << endl; + T* resource = (T *)( res ); + ManagerListener<T> *listener; + for ( listener = mListeners->first(); listener; listener = mListeners->next() ) + listener->resourceModified( resource ); + } + + virtual void resourceDeleted( Resource *res ) + { + kdDebug(5650) << "Manager::resourceDeleted " << res->resourceName() << endl; + T* resource = (T *)( res ); + ManagerListener<T> *listener; + for ( listener = mListeners->first(); listener; listener = mListeners->next() ) { + kdDebug(5650) << "Notifying a listener to Manager..." << endl; + listener->resourceDeleted( resource ); + } + } + + private: + ManagerImpl *mImpl; + Factory *mFactory; + QPtrList<ManagerListener<T> > *mListeners; +}; + +} + +#endif diff --git a/microkde/kresources/managerimpl.cpp b/microkde/kresources/managerimpl.cpp new file mode 100644 index 0000000..1baa6be --- a/dev/null +++ b/microkde/kresources/managerimpl.cpp @@ -0,0 +1,353 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kglobal.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kstandarddirs.h> + +#include "resource.h" +#include "factory.h" +#include "managerimpl.h" + +using namespace KRES; + +ManagerImpl::ManagerImpl( const QString &family ) + : mFamily( family ), mConfig( 0 ), mStdConfig( 0 ), mStandard( 0 ), + mFactory( 0 ) + +{ + kdDebug(5650) << "ManagerImpl::ManagerImpl()" << endl; + + +} + +ManagerImpl::~ManagerImpl() +{ + kdDebug(5650) << "ManagerImpl::~ManagerImpl()" << endl; + + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + delete *it; + } + + delete mStdConfig; +} + +void ManagerImpl::createStandardConfig() +{ + if ( !mStdConfig ) { + QString file = locateLocal( "data", KGlobal::getAppName() + + "/kresources/" + mFamily + "rc" ); + mStdConfig = new KConfig( file ); + } + + mConfig = mStdConfig; +} + +void ManagerImpl::readConfig( KConfig *cfg ) +{ + kdDebug(5650) << "ManagerImpl::readConfig()" << endl; + + delete mFactory; + mFactory = Factory::self( mFamily ); + + if ( !cfg ) { + createStandardConfig(); + } else { + mConfig = cfg; + } + + mStandard = 0; + + mConfig->setGroup( "General" ); + + QStringList keys = mConfig->readListEntry( "ResourceKeys" ); + keys += mConfig->readListEntry( "PassiveResourceKeys" ); + + QString standardKey = mConfig->readEntry( "Standard" ); + + for ( QStringList::Iterator it = keys.begin(); it != keys.end(); ++it ) { + readResourceConfig( *it, false ); + } + +} + +void ManagerImpl::writeConfig( KConfig *cfg ) +{ +//USqDebug("ManagerImpl::writeConfig begin this= %ul cfg=%ul", this, cfg); + + + kdDebug(5650) << "ManagerImpl::writeConfig()" << endl; + + if ( !cfg ) { + createStandardConfig(); + } else { + mConfig = cfg; + } + + QStringList activeKeys; + QStringList passiveKeys; + + // First write all keys, collect active and passive keys on the way + Resource::List::Iterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + writeResourceConfig( *it, false ); + + QString key = (*it)->identifier(); + if( (*it)->isActive() ) + activeKeys.append( key ); + else + passiveKeys.append( key ); + } + + // And then the general group + + kdDebug(5650) << "Saving general info" << endl; + mConfig->setGroup( "General" ); + mConfig->writeEntry( "ResourceKeys", activeKeys ); + mConfig->writeEntry( "PassiveResourceKeys", passiveKeys ); + if ( mStandard ) + mConfig->writeEntry( "Standard", mStandard->identifier() ); + else + mConfig->writeEntry( "Standard", "" ); + + mConfig->sync(); + kdDebug(5650) << "ManagerImpl::save() finished" << endl; + +//US qDebug("ManagerImpl::writeConfig end this= %ul cfg=%ul", this, cfg); + +} + +void ManagerImpl::add( Resource *resource, bool useDCOP ) +{ +qDebug("ManagerImpl::add begin this= %ul resource=%ul", this, resource); + + resource->setActive( true ); + + if ( mResources.isEmpty() ) { + mStandard = resource; + } + + mResources.append( resource ); + + writeResourceConfig( resource, true ); + + qDebug("ManagerImpl::add end this= %ul resource=%ul", this, resource); + +} + +void ManagerImpl::remove( Resource *resource, bool useDCOP ) +{ + if ( mStandard == resource ) mStandard = 0; + removeResource( resource ); + + mResources.remove( resource ); + + delete resource; + + kdDebug(5650) << "Finished ManagerImpl::remove()" << endl; +} + +void ManagerImpl::setActive( Resource *resource, bool active ) +{ + if ( resource && resource->isActive() != active ) { + resource->setActive( active ); + } +} + +Resource *ManagerImpl::standardResource() +{ + return mStandard; +} + +void ManagerImpl::setStandardResource( Resource *resource ) +{ + mStandard = resource; +} + +void ManagerImpl::resourceChanged( Resource *resource ) +{ + writeResourceConfig( resource, true ); + + +// ManagerIface_stub allManagers( "*", "ManagerIface_" + mFamily.utf8() ); +// allManagers.dcopResourceModified( resource->identifier() ); +} + +// DCOP asynchronous functions +//US since we work from inside the application, we call the methods directly. + +QStringList ManagerImpl::resourceNames() +{ + QStringList result; + + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + result.append( (*it)->resourceName() ); + } + return result; +} + +Resource::List *ManagerImpl::resourceList() +{ + return &mResources; +} + +QPtrList<Resource> ManagerImpl::resources() +{ + QPtrList<Resource> result; + + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + result.append( *it ); + } + return result; +} + +QPtrList<Resource> ManagerImpl::resources( bool active ) +{ + QPtrList<Resource> result; + + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + if ( (*it)->isActive() == active ) { + result.append( *it ); + } + } + return result; +} + +void ManagerImpl::setListener( ManagerImplListener *listener ) +{ + mListener = listener; +} + +Resource* ManagerImpl::readResourceConfig( const QString& identifier, + bool checkActive ) +{ + kdDebug() << "ManagerImpl::readResourceConfig() " << identifier << endl; + +// qDebug("ManagerImpl::readResourceConfig() %s", identifier.latin1()); + + mConfig->setGroup( "Resource_" + identifier ); + + QString type = mConfig->readEntry( "ResourceType" ); + QString name = mConfig->readEntry( "ResourceName" ); + Resource *resource = mFactory->resource( type, mConfig ); + if ( !resource ) { + kdDebug(5650) << "Failed to create resource with id " << identifier << endl; + return 0; + } + + if ( resource->identifier().isEmpty() ) + resource->setIdentifier( identifier ); + + mConfig->setGroup( "General" ); + + QString standardKey = mConfig->readEntry( "Standard" ); + if ( standardKey == identifier ) { + mStandard = resource; + } + + if ( checkActive ) { + QStringList activeKeys = mConfig->readListEntry( "ResourceKeys" ); + resource->setActive( activeKeys.contains( identifier ) ); + } + mResources.append( resource ); + + return resource; +} + +void ManagerImpl::writeResourceConfig( Resource *resource, + bool checkActive ) +{ + QString key = resource->identifier(); + + kdDebug(5650) << "Saving resource " << key << endl; + + if ( !mConfig ) createStandardConfig(); + + mConfig->setGroup( "Resource_" + key ); + resource->writeConfig( mConfig ); + + mConfig->setGroup( "General" ); + QString standardKey = mConfig->readEntry( "Standard" ); + + if ( resource == mStandard && standardKey != key ) + mConfig->writeEntry( "Standard", resource->identifier() ); + else if ( resource != mStandard && standardKey == key ) + mConfig->writeEntry( "Standard", "" ); + + if ( checkActive ) { + QStringList activeKeys = mConfig->readListEntry( "ResourceKeys" ); + if ( resource->isActive() && !activeKeys.contains( key ) ) { + activeKeys.append( resource->identifier() ); + mConfig->writeEntry( "ResourceKeys", activeKeys ); + } else if ( !resource->isActive() && activeKeys.contains( key ) ) { + activeKeys.remove( key ); + mConfig->writeEntry( "ResourceKeys", activeKeys ); + } + } + + mConfig->sync(); +} + +void ManagerImpl::removeResource( Resource *resource ) +{ + QString key = resource->identifier(); + + if ( !mConfig ) createStandardConfig(); + + mConfig->setGroup( "General" ); + QStringList activeKeys = mConfig->readListEntry( "ResourceKeys" ); + if ( activeKeys.contains( key ) ) { + activeKeys.remove( key ); + mConfig->writeEntry( "ResourceKeys", activeKeys ); + } else { + QStringList passiveKeys = mConfig->readListEntry( "PassiveResourceKeys" ); + passiveKeys.remove( key ); + mConfig->writeEntry( "PassiveResourceKeys", passiveKeys ); + } + + QString standardKey = mConfig->readEntry( "Standard" ); + if ( standardKey == key ) { + mConfig->writeEntry( "Standard", "" ); + } + + mConfig->deleteGroup( "Resource_" + resource->identifier() ); + + mConfig->sync(); +} + +Resource* ManagerImpl::getResource( const QString& identifier ) +{ + Resource::List::ConstIterator it; + for ( it = mResources.begin(); it != mResources.end(); ++it ) { + if ( (*it)->identifier() == identifier ) + return *it; + } + return 0; +} diff --git a/microkde/kresources/managerimpl.h b/microkde/kresources/managerimpl.h new file mode 100644 index 0000000..a049bcc --- a/dev/null +++ b/microkde/kresources/managerimpl.h @@ -0,0 +1,113 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_MANAGERIMPL_H +#define KRESOURCES_MANAGERIMPL_H + +#include <qstring.h> +#include <qptrlist.h> +#include <qdict.h> +//US +#include <qobject.h> + +#include "resource.h" + + +class KConfig; + +namespace KRES { + +class Resource; +class Factory; + +class ManagerImplListener +{ + public: + virtual void resourceAdded( Resource *resource ) = 0; + virtual void resourceModified( Resource *resource ) = 0; + virtual void resourceDeleted( Resource *resource ) = 0; +}; + + +/** + @internal + + Do not use this class directly. Use ResourceManager instead +*/ +class ManagerImpl : public QObject +{ + Q_OBJECT + public: + ManagerImpl( const QString &family ); + ~ManagerImpl(); + + void readConfig( KConfig * ); + void writeConfig( KConfig * ); + + void add( Resource *resource, bool useDCOP = true ); + void remove( Resource *resource, bool useDCOP = true ); + + Resource *standardResource(); + void setStandardResource( Resource *resource ); + + void setActive( Resource *resource, bool active ); + + Resource::List *resourceList(); + + QPtrList<Resource> resources(); + + // Get only active or passive resources + QPtrList<Resource> resources( bool active ); + + QStringList resourceNames(); + + void setListener( ManagerImplListener *listener ); + + public slots: + void resourceChanged( Resource *resource ); + + private: + // dcop calls + + private: + void createStandardConfig(); + + Resource *readResourceConfig( const QString& identifier, bool checkActive ); + void writeResourceConfig( Resource *resource, bool checkActive ); + + void removeResource( Resource *resource ); + Resource *getResource( Resource *resource ); + Resource *getResource( const QString& identifier ); + + QString mFamily; + KConfig *mConfig; + KConfig *mStdConfig; + Resource *mStandard; + Factory *mFactory; + Resource::List mResources; + ManagerImplListener *mListener; +}; + +} + +#endif diff --git a/microkde/kresources/resource.cpp b/microkde/kresources/resource.cpp new file mode 100644 index 0000000..169eaa4 --- a/dev/null +++ b/microkde/kresources/resource.cpp @@ -0,0 +1,185 @@ +/* + This file is part of libkresources. + + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <kdebug.h> +#include <kapplication.h> +#include <kconfig.h> + +#include "resource.h" + +using namespace KRES; + +class Resource::ResourcePrivate +{ + public: +#ifdef QT_THREAD_SUPPORT + QMutex mMutex; +#endif + int mOpenCount; + QString mType; + QString mIdentifier; + bool mReadOnly; + QString mName; + bool mActive; + bool mIsOpen; +}; + +Resource::Resource( const KConfig* config ) + : QObject( 0, "" ), d( new ResourcePrivate ) +{ + d->mOpenCount = 0; + d->mIsOpen = false; + + //US compiler claimed that const discards qualifier + KConfig* cfg = (KConfig*)config; + if ( cfg ) { + d->mType = cfg->readEntry( "ResourceType" ); + d->mName = cfg->readEntry( "ResourceName" ); + d->mReadOnly = cfg->readBoolEntry( "ResourceIsReadOnly", false ); + d->mActive = cfg->readBoolEntry( "ResourceIsActive", true ); + d->mIdentifier = cfg->readEntry( "ResourceIdentifier" ); + } else { + d->mType = "type"; + d->mName = "resource-name"; + d->mReadOnly = false; + d->mActive = true; + d->mIdentifier = KApplication::randomString( 10 ); + } +} + +Resource::~Resource() +{ + delete d; + d = 0; +} + +void Resource::writeConfig( KConfig* config ) +{ + kdDebug(5650) << "Resource::writeConfig()" << endl; + + config->writeEntry( "ResourceType", d->mType ); + config->writeEntry( "ResourceName", d->mName ); + config->writeEntry( "ResourceIsReadOnly", d->mReadOnly ); + config->writeEntry( "ResourceIsActive", d->mActive ); + config->writeEntry( "ResourceIdentifier", d->mIdentifier ); +} + +bool Resource::open() +{ + d->mIsOpen = true; +#ifdef QT_THREAD_SUPPORT + QMutexLocker guard( &(d->mMutex) ); +#endif + if ( !d->mOpenCount ) { + kdDebug(5650) << "Opening resource " << resourceName() << endl; + d->mIsOpen = doOpen(); + } + d->mOpenCount++; + return d->mIsOpen; +} + +void Resource::close() +{ +#ifdef QT_THREAD_SUPPORT + QMutexLocker guard( &(d->mMutex) ); +#endif + if ( !d->mOpenCount ) { + kdDebug(5650) << "ERROR: Resource " << resourceName() << " closed more times than previously opened" << endl; + return; + } + d->mOpenCount--; + if ( !d->mOpenCount ) { + kdDebug(5650) << "Closing resource " << resourceName() << endl; + doClose(); + d->mIsOpen = false; + } else { + kdDebug(5650) << "Not yet closing resource " << resourceName() << ", open count = " << d->mOpenCount << endl; + } +} + +bool Resource::isOpen() const +{ + return d->mIsOpen; +} + +void Resource::setIdentifier( const QString& identifier ) +{ + d->mIdentifier = identifier; +} + +QString Resource::identifier() const +{ + return d->mIdentifier; +} + +void Resource::setType( const QString& type ) +{ + d->mType = type; +} + +QString Resource::type() const +{ + return d->mType; +} + +void Resource::setReadOnly( bool value ) +{ + d->mReadOnly = value; +} + +bool Resource::readOnly() const +{ + return d->mReadOnly; +} + +void Resource::setResourceName( const QString &name ) +{ + d->mName = name; +} + +QString Resource::resourceName() const +{ + return d->mName; +} + +void Resource::setActive( bool value ) +{ + d->mActive = value; +} + +bool Resource::isActive() const +{ + return d->mActive; +} + +void Resource::dump() const +{ + kdDebug(5650) << "Resource:" << endl; + kdDebug(5650) << " Name: " << d->mName << endl; + kdDebug(5650) << " Identifier: " << d->mIdentifier << endl; + kdDebug(5650) << " Type: " << d->mType << endl; + kdDebug(5650) << " OpenCount: " << d->mOpenCount << endl; + kdDebug(5650) << " ReadOnly: " << ( d->mReadOnly ? "yes" : "no" ) << endl; + kdDebug(5650) << " Active: " << ( d->mActive ? "yes" : "no" ) << endl; + kdDebug(5650) << " IsOpen: " << ( d->mIsOpen ? "yes" : "no" ) << endl; +} diff --git a/microkde/kresources/resource.h b/microkde/kresources/resource.h new file mode 100644 index 0000000..7ff4f23 --- a/dev/null +++ b/microkde/kresources/resource.h @@ -0,0 +1,401 @@ +/* + This file is part of libkresources + + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_RESOURCE_H +#define KRESOURCES_RESOURCE_H + +//US +#ifdef QT_THREAD_SUPPORT +#include <qmutex.h> +#endif //QT_THREAD_SUPPORT + +#include <qvaluelist.h> +#include <qwidget.h> + +#include <qobject.h> + +class KConfig; + +namespace KRES { + +class KLibFactory; +class ConfigWidget; + +/** + * @internal + * @libdoc The KDE Resource library + * + * NOTE: this library is NOT (YET?) PUBLIC. Do not publish this + * interface, it is in constant flux. + * + * The KDE Resource framework can be used to manage resources of + * different types, organized in families. The Resource framework + * is currently used for addressbook resources in libkabc and for + * calendar resources in libkcal. + * + * When you want to use the framework for a new family, you need to + * <ul><li>Define a name for your resource family</li> + * <li>subclass Resource and add the fields and method that are needed + * in your application</li> + * <li>If needed, override the doOpen() and doClose() methods. + * <li> Provide a configuration possibility for resources in your + * new family. You can use @ref ResourcesConfigPage to easily create a + * KControl applet</li> + * <li>In your application, you can use @ref ResourceManager to keep track + * of the resources in your family, and you can use @ref ResourceSelectDialog + * to let the user select a single resource.</li> + * </ul> + * + * When you want to add a new resource type to an existing resource family, + * you need to + * <ul><li>Further subclass the family-specific Resource to implement + * resource type-specific operation</li> + * <li>Subclass ResourceConfigWidget to provide a configuration widget + * for your new resource type</li> + * <li>Provide a .desktop file so that the new resource type can be found + * automatically by the ResourceManager</li> + * </ul> + * + * Example: + * +<B>resourceexample.h</B>: +<pre> +#include <kconfig.h> +#include <kresources/resource.h> + +class ResourceExample : public KRES::ResourceExample +{ +public: + ResourceExample( const KConfig * ); + ~ResourceCalendarExchange(); + void writeConfig( KConfig *config ); +private: + QString mLocation; + QString mPassword; +} +</pre> +<B>resourceexample.cpp</B>: +<pre> +#include <kconfig.h> + +#include "resourceexample.h" + +ResourceExample::ResourceExample( const KConfig *config ) + : Resource( config ) +{ + if ( config ) { + mLocation = config->readEntry( "Location" ); + mPassword = KStringHandler::obscure( config->readEntry( "Password" ) ); + } else { + mLocation = ""; // Or some sensible default + mPassword = ""; + } +} + +void ResourceExample::writeConfig( KConfig *config ) +{ + KRES::Resource::writeConfig( config ); + config->writeEntry( "Location", mLocation ); + config->writeEntry( "Password", KStringHandler::obscure( mPassword ) ); +} + +extern "C" +{ + KRES::ResourceExample *config_widget( QWidget *parent ) { + return new ResourceExampleConfig( parent, "Configure Example Resource" ); + } + + KRES::Resource *resource( const KConfig *config ) { + return new ResourceExample( config ); + } +} +</pre> +* <B>resourceexampleconfig.h</B>: +<pre> +#include <klineedit.h> +#include <kresources/resourceconfigwidget.h> + +#include "resourceexample.h" + +class ResourceExampleConfig : public KRES::ResourceConfigWidget +{ + Q_OBJECT + +public: + ResourceExampleConfig( QWidget* parent = 0, const char* name = 0 ); + +public slots: + virtual void loadSettings( KRES::Resource *resource); + virtual void saveSettings( KRES::Resource *resource ); + +private: + KLineEdit* mLocationEdit; + KLineEdit* mPasswordEdit; +}; +</pre> +* <B>resourceexampleconfig.cpp</B>: +<pre> +#include <qlayout.h> +#include <qlabel.h" +#include <kresources/resourceconfigwidget.h> +#include "resourceexample.h" +#include "resourceexampleconfig.h" + +ResourceExampleConfig::ResourceExampleConfig( QWidget* parent, const char* name ) + : KRES::ResourceConfigWidget( parent, name ) +{ + resize( 245, 115 ); + QGridLayout *mainLayout = new QGridLayout( this, 2, 2 ); + + QLabel *label = new QLabel( i18n( "Location:" ), this ); + mHostEdit = new KLineEdit( this ); + mainLayout->addWidget( label, 1, 0 ); + mainLayout->addWidget( mHostEdit, 1, 1 ); + + label = new QLabel( i18n( "Password:" ), this ); + mPasswordEdit = new KLineEdit( this ); + mPasswordEdit->setEchoMode( QLineEdit::Password ); + mainLayout->addWidget( label, 2, 0 ); + mainLayout->addWidget( mPasswordEdit, 2, 1 ); +} + +void ResourceExampleConfig::loadSettings( KRES::Resource *resource ) +{ + ResourceExample* res = dynamic_cast<ResourceExample *>( resource ); + if (res) { + mHostEdit->setText( res->host() ); + mPasswordEdit->setText( res->password() ); + } else + kdDebug(5700) << "ERROR: ResourceExampleConfig::loadSettings(): no ResourceExample, cast failed" << endl; +} + +void ResourceExampleConfig::saveSettings( KRES::Resource *resource ) +{ + ResourceExample* res = dynamic_cast<ResourceExample *>( resource ); + if (res) { + res->setHost(mHostEdit->text()); + res->setPassword(mPasswordEdit->text()); + } else + kdDebug(5700) << "ERROR: ResourceExampleConfig::saveSettings(): no ResourceExample, cast failed" << endl; +} +</pre> +* <B>resourceexample.desktop</B>: +<pre> +[Desktop Entry] +Type=Service + +[Misc] +Encoding=UTF-8 +Name=Example Resource + +[Plugin] +Type=exchange +X-KDE-Library=resourceexample +</pre> +* <B>Makefile.am</B> +<pre> +kde_module_LTLIBRARIES = resourceexample.la + +resourceexample_la_SOURCES = resourceexample.cpp resourceexampleconfig.cpp +resourceexample_la_LDFLAGS= $(all_libraries) -module $(KDE_PLUGIN) +resourceexample_la_LIBADD= -lkderesources + +linkdir= $(kde_datadir)/resources/family +link_DATA= resourceexample.desktop +</pre> + * + * + */ + +/** + * A @ref Resource is a ... + * + * A subclass should reimplement at least the constructor and the + * @ref writeConfig method. + * + */ +class Resource : public QObject +{ + Q_OBJECT + + public: + typedef QValueList<Resource *> List; + + /** + * Constructor. Construct resource from config. + * @param config Configuration to read persistence information from. + * If config==0, create object using default settings. + */ + Resource( const KConfig* config ); + + /** + * Destructor. + */ + virtual ~Resource(); + + /** + * Write configuration information for this resource to a configuration + * file. If you override this method, remember to call Resource::writeConfig + * or Terrible Things(TM) will happen. + * @param config Configuration to write persistence information to. + */ + virtual void writeConfig( KConfig* config ); + + /** + * Open this resource, if it not already open. Increase the open + * count of this object, and open the resource by calling @ref doOpen(). + * This method may block while another thread is concurrently opening + * or closing the resource. + * + * Returns true if the resource was already opened or if it was opened + * successfully; returns false if the resource was not opened successfully. + */ + bool open(); + + /** + * Decrease the open count of this object, and if the count reaches + * zero, close this resource by calling @ref doClose(). + * This method may block while another thread is concurrently closing + * or opening the resource. + */ + void close(); + + /** + * Returns whether the resource is open or not. + */ + bool isOpen() const; + + /** + * Returns a unique identifier. The identifier is unique for this resource. + * It is created when the resource is first created, and it is retained + * in the resource family configuration file for this resource. + * @return This resource's identifier + */ + QString identifier() const; + + /** + * Returns the type of this resource. + */ + QString type() const; + + /** + * Mark the resource as read-only. You can override this method, + * but also remember to call Resource::setReadOnly(). + */ + virtual void setReadOnly( bool value ); + + /** + * Returns, if the resource is read-only. + */ + virtual bool readOnly() const; + + /** + * Set the name of resource.You can override this method, + * but also remember to call Resource::setResourceName(). + */ + virtual void setResourceName( const QString &name ); + + /** + * Returns the name of resource. + */ + virtual QString resourceName() const; + + /** + Sets, if the resource is active. + */ + void setActive( bool active ); + + /** + Return true, if the resource is active. + */ + bool isActive() const; + + friend class Factory; + friend class ManagerImpl; + + /** + Print resource information as debug output. + */ + virtual void dump() const; + + protected: + /** + * Open this resource. When called, the resource must be in + * a closed state. + * + * Returns true if the resource was opened successfully; + * returns false if the resource was not opened successfully. + * + * The result of this call can be accessed later by @ref isOpen() + */ + virtual bool doOpen() { return true; } + + /** + * Close this resource. Pre-condition: resource is open. + * Post-condition: resource is closed. + */ + virtual void doClose() {} + + void setIdentifier( const QString& identifier ); + void setType( const QString& type ); + + private: + class ResourcePrivate; + ResourcePrivate *d; +}; + +//US class PluginFactoryBase : public KLibFactory +class PluginFactoryBase +{ + public: + virtual Resource *resource( const KConfig *config ) = 0; + + virtual ConfigWidget *configWidget( QWidget *parent ) = 0; + + protected: + virtual QObject* createObject( QObject*, const char*, const char*, + const QStringList & ) + { + return 0; + } +}; + +template<class TR,class TC> +class PluginFactory : public PluginFactoryBase +{ + public: + Resource *resource( const KConfig *config ) + { + return new TR( config ); + } + + ConfigWidget *configWidget( QWidget *parent ) + { + return new TC( parent ); + } +}; + + + +} + +#endif diff --git a/microkde/kresources/resourceselectdialog.h b/microkde/kresources/resourceselectdialog.h new file mode 100644 index 0000000..fef689d --- a/dev/null +++ b/microkde/kresources/resourceselectdialog.h @@ -0,0 +1,12 @@ +#ifndef MICRO_KRES_RESOURCESELECTDIALOG_H +#define MICRO_KRES_RESOURCESELECTDIALOG_H + +namespace KRES { + +class ResourceSelectDialog +{ +}; + +} + +#endif diff --git a/microkde/kresources/selectdialog.cpp b/microkde/kresources/selectdialog.cpp new file mode 100644 index 0000000..fba8648 --- a/dev/null +++ b/microkde/kresources/selectdialog.cpp @@ -0,0 +1,154 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/*US +#include <kbuttonbox.h> +#include <klistbox.h> +#include <klocale.h> +#include <kmessagebox.h> + +*/ +#include <klocale.h> +#include <kmessagebox.h> + +//US +#include <kglobal.h> + +#include <qlistbox.h> +#include <qlayout.h> +#include <qgroupbox.h> + +#include "resource.h" + +#include "selectdialog.h" + +using namespace KRES; + +//US I am using KBaseDialog instead of KDialog +//US : KDialog( parent, name, true ) +SelectDialog::SelectDialog( QPtrList<Resource> list, QWidget *parent, + const char *name ) + : KDialogBase( parent, name, true, i18n( "Resource Selection" ), Help | Ok | Cancel, + Ok, true) + +{ +//US setCaption( i18n( "Resource Selection" ) ); +//US resize( 300, 200 ); + resize( KMIN(KGlobal::getDesktopWidth(), 300), KMIN(KGlobal::getDesktopHeight(), 200) ); + +//US + QFrame *main = plainPage(); +/*US + QVBoxLayout *layout = new QVBoxLayout( main ); + mConfigPage = new KRES::ConfigPage( main ); + layout->addWidget( mConfigPage ); +*/ + +//US QVBoxLayout *mainLayout = new QVBoxLayout( this ); + QVBoxLayout *mainLayout = new QVBoxLayout( main ); + mainLayout->setMargin( marginHint() ); + +//US QGroupBox *groupBox = new QGroupBox( 2, Qt::Horizontal, this ); + QGroupBox *groupBox = new QGroupBox( 2, Qt::Horizontal, main ); + groupBox->setTitle( i18n( "Resources" ) ); + +//US mResourceId = new KListBox( groupBox ); + mResourceId = new QListBox( groupBox ); + + mainLayout->addWidget( groupBox ); + + mainLayout->addSpacing( 40 ); + +/*US + KButtonBox *buttonBox = new KButtonBox( this ); + + buttonBox->addStretch(); + buttonBox->addButton( i18n( "&OK" ), this, SLOT( accept() ) ); + buttonBox->addButton( i18n( "&Cancel" ), this, SLOT( reject() ) ); + buttonBox->layout(); + + mainLayout->addWidget( buttonBox ); +*/ + // setup listbox + uint counter = 0; + for ( uint i = 0; i < list.count(); ++i ) { + Resource *resource = list.at( i ); + if ( resource && !resource->readOnly() ) { + mResourceMap.insert( counter, resource ); + mResourceId->insertItem( resource->resourceName() ); + counter++; + } + } + + mResourceId->setCurrentItem( 0 ); + connect( mResourceId, SIGNAL(returnPressed(QListBoxItem*)), + SLOT(accept()) ); +} + +Resource *SelectDialog::resource() +{ + if ( mResourceId->currentItem() != -1 ) + return mResourceMap[ mResourceId->currentItem() ]; + else + return 0; +} + +Resource *SelectDialog::getResource( QPtrList<Resource> list, QWidget *parent ) +{ + if ( list.count() == 0 ) { + KMessageBox::error( parent, i18n( "There is no resource available!" ) ); + return 0; + } + + if ( list.count() == 1 ) return list.first(); + + // the following lines will return a writeable resource if only _one_ writeable + // resource exists + Resource *found = 0; + Resource *it = list.first(); + while ( it ) { + if ( !it->readOnly() ) { + if ( found ) { + found = 0; + break; + } else + found = it; + } + it = list.next(); + } + + if ( found ) + return found; + + SelectDialog dlg( list, parent); +//US if ( dlg.exec() == KDialog::Accepted ) + if ( dlg.exec() ) + return dlg.resource(); + else + return 0; +} + +/*US +#include "selectdialog.moc" +*/ + diff --git a/microkde/kresources/selectdialog.h b/microkde/kresources/selectdialog.h new file mode 100644 index 0000000..7026212 --- a/dev/null +++ b/microkde/kresources/selectdialog.h @@ -0,0 +1,92 @@ +/* + This file is part of libkresources. + + Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> + Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KRESOURCES_SELECTDIALOG_H +#define KRESOURCES_SELECTDIALOG_H + +#include <qobject.h> +#include <qptrlist.h> +#include <qmap.h> + +#include <kdialogbase.h> + +//US class KListBox; +class QListBox; + +namespace KRES { + +class Resource; + +/** + * Dialog for selecting a resource. + * + * Example: + * + * <pre> + * KABC::Resource *res = KABC::SelectDialog::getResource(); + * if ( !( res ) ) { + * // no resource selected + * } else { + * // do something with resource + * } + * </pre> + */ +//US class SelectDialog : KDialog +class SelectDialog : KDialogBase +{ + // Q_OBJECT + public: + /** + * Constructor. + * @param ab The address book you want to select the resource from + * @param parent The parent widget + * @param name The name of the dialog + */ + SelectDialog( QPtrList<Resource> list, QWidget *parent = 0, + const char *name = 0); + + // ~SelectDialog(); + + /** + * Return selected resource. + */ + Resource *resource(); + + /** + * Open a dialog showing the available resources and return the resource the + * user has selected. Returns 0, if the dialog was canceled. + */ + static Resource *getResource( QPtrList<Resource> list, QWidget *parent = 0 ); + + private: +//US KListBox *mResourceId; + QListBox *mResourceId; + + QMap<int, Resource*> mResourceMap; +}; + + + +} + +#endif diff --git a/microkde/krestrictedline.h b/microkde/krestrictedline.h new file mode 100644 index 0000000..200546c --- a/dev/null +++ b/microkde/krestrictedline.h @@ -0,0 +1,13 @@ +#ifndef MINIKDE_KRESTRICTEDLINE_H +#define MINIKDE_KRESTRICTEDLINE_H + +#include "klineedit.h" + +class KRestrictedLine : public KLineEdit +{ + public: + KRestrictedLine( QWidget *parent, const char *, const QString & ) : + KLineEdit( parent ) {} +}; + +#endif diff --git a/microkde/krun.cpp b/microkde/krun.cpp new file mode 100644 index 0000000..a170add --- a/dev/null +++ b/microkde/krun.cpp @@ -0,0 +1,6 @@ +#include "krun.h" + +bool KRun::runCommand(const QString &, const QString &, const QString &) +{ + return false; +} diff --git a/microkde/krun.h b/microkde/krun.h new file mode 100644 index 0000000..1b63cb7 --- a/dev/null +++ b/microkde/krun.h @@ -0,0 +1,13 @@ +#ifndef MINIKDE_KRUN_H +#define MINIKDE_KRUN_H + +#include <qstring.h> + +class KRun +{ + public: + static bool runCommand(const QString &a, const QString &b=QString::null, + const QString &c=QString::null); +}; + +#endif diff --git a/microkde/ksimpleconfig.h b/microkde/ksimpleconfig.h new file mode 100644 index 0000000..1efd982 --- a/dev/null +++ b/microkde/ksimpleconfig.h @@ -0,0 +1,12 @@ +#ifndef MINIKDE_KSIMPLECONFIG_H +#define MINIKDE_KSIMPLECONFIG_H + +#include "kconfig.h" + +class KSimpleConfig : public KConfig +{ + public: + KSimpleConfig( const QString &file ) : KConfig( file ) {} +}; + +#endif diff --git a/microkde/kstandarddirs_old.cpp b/microkde/kstandarddirs_old.cpp new file mode 100644 index 0000000..ac2c085 --- a/dev/null +++ b/microkde/kstandarddirs_old.cpp @@ -0,0 +1,151 @@ +#include "kdebug.h" +#include "kurl.h" + +#include "kstandarddirs.h" +#ifdef DESKTOP_VERSION +#include <qregexp.h> +#include <qmessagebox.h> + +#endif + + +#include <qfile.h> +#include <qdir.h> + +QString KStandardDirs::mAppDir = QString::null; + +QString locate( const char *type, const QString& filename ) +{ +/*US why do we put all files into one directory. It is quit complicated. +why not staying with the original directorystructure ? + + + QString escapedFilename = filename; + escapedFilename.replace( QRegExp( "/" ), "_" ); + + QString path = KStandardDirs::appDir() + type + "_" + escapedFilename; + + kdDebug() << "locate: '" << path << "'" << endl; + qDebug("locate: %s" , path.latin1()); + return path; +*/ +//US so my proposal is this: + +// QString escapedFilename = filename; +// escapedFilename.replace( QRegExp( "/" ), "_" ); + +#ifdef _WIN32_ + QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename); +#else + QString path = KStandardDirs::appDir() + type + "/" + filename; +#endif + + //US Create the containing dir if needed + KURL pathurl; + pathurl.setPath(path); + QString dir=pathurl.directory(); + // QMessageBox::information( 0,"path", path, 1 ); +#ifdef _WIN32_ + KStandardDirs::makeDir(path); +#else + KStandardDirs::makeDir(dir); +#endif + + kdDebug() << "locate: '" << path << "'" << endl; + qDebug("locate: %s" , path.latin1()); + return path; + + +} + +QString locateLocal( const char *type, const QString& filename ) +{ + return locate( type, filename ); +} + +QStringList KStandardDirs::findAllResources( const QString &, const QString &, bool, bool) +{ + return QStringList(); +} + +QString KStandardDirs::findResourceDir( const QString &, const QString & ) +{ + return QString::null; +} + +void KStandardDirs::setAppDir( const QString &appDir ) +{ + mAppDir = appDir; + + if ( mAppDir.right( 1 ) != "/" ) mAppDir += "/"; +} + +bool KStandardDirs::makeDir(const QString& dir, int mode) +{ + QDir dirObj; + + + // we want an absolute path +#ifndef _WIN32_ + if (dir.at(0) != '/') + return false; +#endif + + + + QString target = dir; + uint len = target.length(); +#ifndef _WIN32_ + // append trailing slash if missing + if (dir.at(len - 1) != '/') + target += '/'; +#endif + + QString base(""); + uint i = 1; + + while( i < len ) + { +//US struct stat st; +#ifndef _WIN32_ + int pos = target.find('/', i); +#else + int pos = target.find('\\', i); +#endif + if ( pos < 0 ) + return true; + base += target.mid(i - 1, pos - i + 1); + //QMessageBox::information( 0,"cap111", base, 1 ); +/*US + QCString baseEncoded = QFile::encodeName(base); + // bail out if we encountered a problem + if (stat(baseEncoded, &st) != 0) + { + // Directory does not exist.... + // Or maybe a dangling symlink ? + if (lstat(baseEncoded, &st) == 0) + (void)unlink(baseEncoded); // try removing + + + if ( mkdir(baseEncoded, (mode_t) mode) != 0) { + perror("trying to create local folder"); + return false; // Couldn't create it :-( + } + } +*/ + + if (dirObj.exists(base) == false) + { + qDebug("KStandardDirs::makeDir try to create : %s" , base.latin1()); + if (dirObj.mkdir(base) != true) + { + qDebug("KStandardDirs::makeDir could not create: %s" , base.latin1()); + return false; + } + } + + i = pos + 1; + } + return true; +} + diff --git a/microkde/kstandarddirs_old.h b/microkde/kstandarddirs_old.h new file mode 100644 index 0000000..87f8d69 --- a/dev/null +++ b/microkde/kstandarddirs_old.h @@ -0,0 +1,35 @@ +#ifndef MINIKDE_KSTANDARDDIRS_H +#define MINIKDE_KSTANDARDDIRS_H + +#include <qstring.h> +#include <qstringlist.h> + +QString locate( const char *type, const QString& filename ); +QString locateLocal( const char *type, const QString& filename ); + +class KStandardDirs +{ + public: + QStringList findAllResources( const QString &, const QString &, bool, bool); + QString findResourceDir( const QString &, const QString & ); + + static void setAppDir( const QString & ); + static QString appDir() { return mAppDir; } + + /** + * Recursively creates still-missing directories in the given path. + * + * The resulting permissions will depend on the current umask setting. + * permission = mode & ~umask. + * + * @param dir Absolute path of the directory to be made. + * @param mode Directory permissions. + * @return true if successful, false otherwise + */ + static bool makeDir(const QString& dir, int mode = 0755); + + private: + static QString mAppDir; +}; + +#endif diff --git a/microkde/kstaticdeleter.h b/microkde/kstaticdeleter.h new file mode 100644 index 0000000..190f3e4 --- a/dev/null +++ b/microkde/kstaticdeleter.h @@ -0,0 +1,35 @@ +/* + * This file is part of the KDE Libraries + * Copyright (C) 2000 Stephan Kulow <coolo@kde.org> + * 2001 KDE Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _KSTATIC_DELETER_H_ +#define _KSTATIC_DELETER_H_ + +template<class type> +class KStaticDeleter +{ + public: + KStaticDeleter() {}; + type *setObject( type *obj, bool isArray = false) { return obj; } + virtual ~KStaticDeleter() {}; +}; + +#endif diff --git a/microkde/ksystemtray.cpp b/microkde/ksystemtray.cpp new file mode 100644 index 0000000..4f81d02 --- a/dev/null +++ b/microkde/ksystemtray.cpp @@ -0,0 +1,11 @@ +#include "ksystemtray.h" + +void KSystemTray::mousePressEvent( QMouseEvent *) +{ + ; //qDebug("hallo"); +} + +KSystemTray::KSystemTray( QWidget *parent ) : QLabel( parent ) +{ + +} diff --git a/microkde/ksystemtray.h b/microkde/ksystemtray.h new file mode 100644 index 0000000..f3e4f6a --- a/dev/null +++ b/microkde/ksystemtray.h @@ -0,0 +1,14 @@ +#ifndef MICROKDE_KSYSTEMTRAY_H +#define MICROKDE_KSYSTEMTRAY_H + +#include <qlabel.h> + +class KSystemTray : public QLabel +{ + Q_OBJECT + public: + KSystemTray( QWidget *parent = 0 ); + void mousePressEvent( QMouseEvent *); +}; + +#endif diff --git a/microkde/ktempfile.cpp b/microkde/ktempfile.cpp new file mode 100644 index 0000000..b9166bd --- a/dev/null +++ b/microkde/ktempfile.cpp @@ -0,0 +1,25 @@ +#include <qtextstream.h> + +#include "ktempfile.h" + +KTempFile::KTempFile() +{ +} + +KTempFile::KTempFile( const QString &filename, const QString &extension ) +{ +} + +void KTempFile::setAutoDelete( bool ) +{ +} + +QString KTempFile::name() +{ + return QString::null; +} + +QTextStream *KTempFile::textStream() +{ + return 0; +} diff --git a/microkde/ktempfile.h b/microkde/ktempfile.h new file mode 100644 index 0000000..20dfa82 --- a/dev/null +++ b/microkde/ktempfile.h @@ -0,0 +1,20 @@ +#ifndef MINIKDE_KTEMPFILE_H +#define MINIKDE_KTEMPFILE_H + +#include <qstring.h> + +class QTextStream; + +class KTempFile +{ + public: + KTempFile(); + KTempFile( const QString &filename, const QString &extension ); + + void setAutoDelete( bool ); + QString name(); + + QTextStream *textStream(); +}; + +#endif diff --git a/microkde/ktextedit.cpp b/microkde/ktextedit.cpp new file mode 100644 index 0000000..4dd6875 --- a/dev/null +++ b/microkde/ktextedit.cpp @@ -0,0 +1,53 @@ + +#include <ktextedit.h> +#ifndef DESKTOP_VERSION +#include <qpe/qpeapplication.h> +#endif + + +KTextEdit::KTextEdit ( QWidget *parent ) : QMultiLineEdit( parent ) +{ + mAllowPopupMenu = false; + mMouseDown = false; + mIgnoreMark = false; +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( this, QPEApplication::RightOnHold ); +#endif +} + +void KTextEdit::mousePressEvent(QMouseEvent *e) +{ + if ( e->button() == LeftButton ) { + mAllowPopupMenu = true; + mYMousePos = mapToGlobal( (e->pos())).y(); + mXMousePos = mapToGlobal( (e->pos())).x(); + } + if ( e->button() == RightButton && !mAllowPopupMenu ) + return; + if ( e->button() == LeftButton ) { + if ( hasMarkedText () ) + mIgnoreMark = !mIgnoreMark; + if ( mIgnoreMark && hasMarkedText () ) { + mMouseDown = false; + return ; + } + } + QMultiLineEdit::mousePressEvent( e ); +} + +void KTextEdit::mouseReleaseEvent(QMouseEvent *e) +{ + QMultiLineEdit::mouseReleaseEvent(e); +} + +void KTextEdit::mouseMoveEvent(QMouseEvent *e) +{ + int diff = mYMousePos - mapToGlobal( (e->pos())).y(); + if ( diff < 0 ) diff = -diff; + int diff2 = mXMousePos - mapToGlobal( (e->pos())).x(); + if ( diff2 < 0 ) diff2 = -diff2; + if ( diff+ diff2 > 20 ) + mAllowPopupMenu = false; + QMultiLineEdit::mouseMoveEvent(e); +} + diff --git a/microkde/ktextedit.h b/microkde/ktextedit.h new file mode 100644 index 0000000..c912f3b --- a/dev/null +++ b/microkde/ktextedit.h @@ -0,0 +1,22 @@ +#ifndef MICROKDE_KTEXTEDIT_H +#define MICROKDE_KTEXTEDIT_H + +#include <qmultilineedit.h> + +class KTextEdit : public QMultiLineEdit +{ + public: + KTextEdit( QWidget *parent ) ; + + private: + bool mAllowPopupMenu; + bool mMouseDown; + bool mIgnoreMark; + int mYMousePos; + int mXMousePos; + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); +}; + +#endif diff --git a/microkde/kunload.h b/microkde/kunload.h new file mode 100644 index 0000000..1c3d00f --- a/dev/null +++ b/microkde/kunload.h @@ -0,0 +1,6 @@ +#ifndef MINIKDE_KUNLOAD_H +#define MINIKDE_KUNLOAD_H + +#define _UNLOAD(p) + +#endif diff --git a/microkde/kurl.cpp b/microkde/kurl.cpp new file mode 100644 index 0000000..2574e25 --- a/dev/null +++ b/microkde/kurl.cpp @@ -0,0 +1,1942 @@ +/* + Copyright (C) 1999 Torben Weis <weis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kurl.h" + +#ifndef KDE_QT_ONLY +#include <kdebug.h> +#include <kglobal.h> +//US#include <kidna.h> +#endif + +#include <stdio.h> +#include <assert.h> +#include <ctype.h> +#include <stdlib.h> +#ifdef _WIN32_ + +#else +#include <unistd.h> +#endif +#include <qurl.h> +#include <qdir.h> +#include <qstringlist.h> +#include <qregexp.h> +//US#include <qstylesheet.h> +#include <qmap.h> +#include <qtextcodec.h> + +static const QString fileProt = "file"; + +static QTextCodec * codecForHint( int encoding_hint /* not 0 ! */ ) +{ + return QTextCodec::codecForMib( encoding_hint ); +} + +static QString encode( const QString& segment, bool encode_slash, int encoding_hint ) +{ + const char *encode_string; + if (encode_slash) + encode_string = "<>#@\"&%?={}|^~[]\'`\\:+/"; + else + encode_string = "<>#@\"&%?={}|^~[]\'`\\:+"; + + QCString local; + if (encoding_hint==0) + local = segment.local8Bit(); + else + { + QTextCodec * textCodec = codecForHint( encoding_hint ); + if (!textCodec) + local = segment.local8Bit(); + else + local = textCodec->fromUnicode( segment ); + } + + int old_length = local.length(); + + if ( !old_length ) + return segment.isNull() ? QString::null : QString(""); // differenciate null and empty + + // a worst case approximation + QChar *new_segment = new QChar[ old_length * 3 + 1 ]; + int new_length = 0; + + for ( int i = 0; i < old_length; i++ ) + { + // 'unsave' and 'reserved' characters + // according to RFC 1738, + // 2.2. URL Character Encoding Issues (pp. 3-4) + // WABA: Added non-ascii + unsigned char character = local[i]; + if ( (character <= 32) || (character >= 127) || + strchr(encode_string, character) ) + { + new_segment[ new_length++ ] = '%'; + + unsigned int c = character / 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_segment[ new_length++ ] = c; + + c = character % 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_segment[ new_length++ ] = c; + + } + else + new_segment[ new_length++ ] = local[i]; + } + + QString result = QString(new_segment, new_length); + delete [] new_segment; + return result; +} + +static QString encodeHost( const QString& segment, bool encode_slash, int encoding_hint ) +{ + // Hostnames are encoded differently + // we use the IDNA transformation instead + + // Note: when merging qt-addon, use QResolver::domainToAscii here +#ifndef KDE_QT_ONLY + Q_UNUSED( encode_slash ); + Q_UNUSED( encoding_hint ); + return KIDNA::toAscii(segment); +#else + return encode(segment, encode_slash, encoding_hint); +#endif +} + +static int hex2int( unsigned int _char ) +{ + if ( _char >= 'A' && _char <='F') + return _char - 'A' + 10; + if ( _char >= 'a' && _char <='f') + return _char - 'a' + 10; + if ( _char >= '0' && _char <='9') + return _char - '0'; + return -1; +} + +// WABA: The result of lazy_encode isn't usable for a URL which +// needs to satisfies RFC requirements. However, the following +// operation will make it usable again: +// encode(decode(...)) +// +// As a result one can see that url.prettyURL() does not result in +// a RFC compliant URL but that the following sequence does: +// KURL(url.prettyURL()).url() + + +static QString lazy_encode( const QString& segment ) +{ + int old_length = segment.length(); + + if ( !old_length ) + return QString::null; + + // a worst case approximation + QChar *new_segment = new QChar[ old_length * 3 + 1 ]; + int new_length = 0; + + for ( int i = 0; i < old_length; i++ ) + { + unsigned int character = segment[i].unicode(); // Don't use latin1() + // It returns 0 for non-latin1 values + // Small set of really ambiguous chars + if ((character < 32) || // Low ASCII + ((character == '%') && // The escape character itself + (i+2 < old_length) && // But only if part of a valid escape sequence! + (hex2int(segment[i+1].unicode())!= -1) && + (hex2int(segment[i+2].unicode())!= -1)) || + (character == '?') || // Start of query delimiter + (character == '@') || // Username delimiter + (character == '#') || // Start of reference delimiter + ((character == 32) && (i+1 == old_length))) // A trailing space + { + new_segment[ new_length++ ] = '%'; + + unsigned int c = character / 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_segment[ new_length++ ] = c; + + c = character % 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_segment[ new_length++ ] = c; + } + else + new_segment[ new_length++ ] = segment[i]; + } + + QString result = QString(new_segment, new_length); + delete [] new_segment; + return result; +} + +static void decode( const QString& segment, QString &decoded, QString &encoded, int encoding_hint=0, bool updateDecoded = true ) +{ + decoded = QString::null; + encoded = segment; + + int old_length = segment.length(); + if ( !old_length ) + return; + + QTextCodec *textCodec = 0; + if (encoding_hint) + textCodec = codecForHint( encoding_hint ); + + if (!textCodec) + textCodec = QTextCodec::codecForLocale(); + + QCString csegment = textCodec->fromUnicode(segment); + // Check if everything went ok + if (textCodec->toUnicode(csegment) != segment) + { + // Uh oh + textCodec = codecForHint( 106 ); // Fall back to utf-8 + csegment = textCodec->fromUnicode(segment); + } + old_length = csegment.length(); + + int new_length = 0; + int new_length2 = 0; + + // make a copy of the old one + char *new_segment = new char[ old_length + 1 ]; + QChar *new_usegment = new QChar[ old_length * 3 + 1 ]; + + int i = 0; + while( i < old_length ) + { + bool bReencode = false; + unsigned char character = csegment[ i++ ]; + if ((character <= ' ') || (character > 127)) + bReencode = true; + + new_usegment [ new_length2++ ] = character; + if (character == '%' ) + { + int a = i+1 < old_length ? hex2int( csegment[i] ) : -1; + int b = i+1 < old_length ? hex2int( csegment[i+1] ) : -1; + if ((a == -1) || (b == -1)) // Only replace if sequence is valid + { + // Contains stray %, make sure to re-encode! + bReencode = true; + } + else + { + // Valid %xx sequence + character = a * 16 + b; // Replace with value of %dd + if (!character && updateDecoded) + break; // Stop at %00 + + new_usegment [ new_length2++ ] = (unsigned char) csegment[i++]; + new_usegment [ new_length2++ ] = (unsigned char) csegment[i++]; + } + } + if (bReencode) + { + new_length2--; + new_usegment [ new_length2++ ] = '%'; + + unsigned int c = character / 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_usegment[ new_length2++ ] = c; + + c = character % 16; + c += (c > 9) ? ('A' - 10) : '0'; + new_usegment[ new_length2++ ] = c; + } + + new_segment [ new_length++ ] = character; + } + new_segment [ new_length ] = 0; + + encoded = QString( new_usegment, new_length2); + + // Encoding specified + if (updateDecoded) + { + QByteArray array; + array.setRawData(new_segment, new_length); + decoded = textCodec->toUnicode( array, new_length ); + array.resetRawData(new_segment, new_length); + QCString validate = textCodec->fromUnicode(decoded); + + if (strcmp(validate.data(), new_segment) != 0) + { + decoded = QString::fromLocal8Bit(new_segment, new_length); + } + } + + delete [] new_segment; + delete [] new_usegment; +} + +static QString decode(const QString &segment, int encoding_hint = 0) +{ + QString result; + QString tmp; + decode(segment, result, tmp, encoding_hint); + return result; +} + +static QString cleanpath(const QString &path, bool cleanDirSeparator=true) +{ + if (path.isEmpty()) return QString::null; + int len = path.length(); + bool slash = (len && path[len-1] == '/') || + (len > 1 && path[len-2] == '/' && path[len-1] == '.'); + + // The following code cleans up directory path much like + // QDir::cleanDirPath() except it can be made to ignore multiple + // directory separators by setting the flag to false. That fixes + // bug# 15044, mail.altavista.com and other similar brain-dead server + // implementations that do not follow what has been specified in + // RFC 2396!! (dA) + QString result; + int cdUp, orig_pos, pos; + + cdUp = 0; + pos = orig_pos = len; + while ( pos && (pos = path.findRev('/',--pos)) != -1 ) + { + len = orig_pos - pos - 1; + if ( len == 2 && path[pos+1] == '.' && path[pos+2] == '.' ) + cdUp++; + else + { + // Ignore any occurances of '.' + // This includes entries that simply do not make sense like /..../ + if ( (len || !cleanDirSeparator) && + (len != 1 || path[pos+1] != '.' ) ) + { + if ( !cdUp ) + result.prepend(path.mid(pos, len+1)); + else + cdUp--; + } + } + orig_pos = pos; + } + + if ( result.isEmpty() ) + result = "/"; + else if ( slash && result.at(result.length()-1) != '/' ) + result.append('/'); + + return result; +} + +bool KURL::isRelativeURL(const QString &_url) +{ + int len = _url.length(); + if (!len) return true; // Very short relative URL. + const QChar *str = _url.unicode(); + + // Absolute URL must start with alpha-character + if (!isalpha(str[0].latin1())) + return true; // Relative URL + + for(int i = 1; i < len; i++) + { + char c = str[i].latin1(); // Note: non-latin1 chars return 0! + if (c == ':') + return false; // Absolute URL + + // Protocol part may only contain alpha, digit, + or - + if (!isalpha(c) && !isdigit(c) && (c != '+') && (c != '-')) + return true; // Relative URL + } + // URL did not contain ':' + return true; // Relative URL +} + +KURL::List::List(const KURL &url) +{ + append( url ); +} + +KURL::List::List(const QStringList &list) +{ + for (QStringList::ConstIterator it = list.begin(); + it != list.end(); + it++) + { + append( KURL(*it) ); + } +} + +QStringList KURL::List::toStringList() const +{ + QStringList lst; + for( KURL::List::ConstIterator it = begin(); + it != end(); + it++) + { + lst.append( (*it).url() ); + } + return lst; +} + + +KURL::KURL() +{ + reset(); +} + +KURL::~KURL() +{ +} + + +KURL::KURL( const QString &url, int encoding_hint ) +{ + reset(); + parse( url, encoding_hint ); +} + +KURL::KURL( const char * url, int encoding_hint ) +{ + reset(); + parse( QString::fromLatin1(url), encoding_hint ); +} + +KURL::KURL( const QCString& url, int encoding_hint ) +{ + reset(); + parse( QString::fromLatin1(url), encoding_hint ); +} + +KURL::KURL( const KURL& _u ) +{ + *this = _u; +} + +QDataStream & operator<< (QDataStream & s, const KURL & a) +{ + QString QueryForWire=a.m_strQuery_encoded; + if (!a.m_strQuery_encoded.isNull()) + QueryForWire.prepend("?"); + + s << a.m_strProtocol << a.m_strUser << a.m_strPass << a.m_strHost + << a.m_strPath << a.m_strPath_encoded << QueryForWire << a.m_strRef_encoded + << Q_INT8(a.m_bIsMalformed ? 1 : 0) << a.m_iPort; + return s; +} + +QDataStream & operator>> (QDataStream & s, KURL & a) +{ + Q_INT8 malf; + QString QueryFromWire; + s >> a.m_strProtocol >> a.m_strUser >> a.m_strPass >> a.m_strHost + >> a.m_strPath >> a.m_strPath_encoded >> QueryFromWire >> a.m_strRef_encoded + >> malf >> a.m_iPort; + a.m_bIsMalformed = (malf != 0); + + if ( QueryFromWire.isEmpty() ) + a.m_strQuery_encoded = QString::null; + else + a.m_strQuery_encoded = QueryFromWire.mid(1); + + return s; +} + +#ifndef QT_NO_NETWORKPROTOCOL +KURL::KURL( const QUrl &u ) +{ + *this = u; +} +#endif + +KURL::KURL( const KURL& _u, const QString& _rel_url, int encoding_hint ) +{ + // WORKAROUND THE RFC 1606 LOOPHOLE THAT ALLOWS + // http:/index.html AS A VALID SYNTAX FOR RELATIVE + // URLS. ( RFC 2396 section 5.2 item # 3 ) + QString rUrl = _rel_url; + int len = _u.m_strProtocol.length(); + if ( !_u.m_strHost.isEmpty() && !rUrl.isEmpty() && + rUrl.find( _u.m_strProtocol, 0, false ) == 0 && + rUrl[len] == ':' && (rUrl[len+1] != '/' || + (rUrl[len+1] == '/' && rUrl[len+2] != '/')) ) + { + rUrl.remove( 0, rUrl.find( ':' ) + 1 ); + } + + if ( rUrl.isEmpty() ) + { + *this = _u; + } + else if ( rUrl[0] == '#' ) + { + *this = _u; + QString ref = decode(rUrl.mid(1), encoding_hint); + if ( ref.isNull() ) + ref = ""; // we know there was an (empty) html ref, we saw the '#' + setHTMLRef( ref ); + } + else if ( isRelativeURL( rUrl) ) + { + *this = _u; + m_strQuery_encoded = QString::null; + m_strRef_encoded = QString::null; + if ( rUrl[0] == '/') + { + if ((rUrl.length() > 1) && (rUrl[1] == '/')) + { + m_strHost = QString::null; + } + m_strPath = QString::null; + m_strPath_encoded = QString::null; + } + else if ( rUrl[0] != '?' ) + { + int pos = m_strPath.findRev( '/' ); + if (pos >= 0) + m_strPath.truncate(pos); + m_strPath += '/'; + if (!m_strPath_encoded.isEmpty()) + { + pos = m_strPath_encoded.findRev( '/' ); + if (pos >= 0) + m_strPath_encoded.truncate(pos); + m_strPath_encoded += '/'; + } + } + else + { + if ( m_strPath.isEmpty() ) + m_strPath = '/'; + } + KURL tmp( url() + rUrl, encoding_hint); + *this = tmp; + cleanPath(false); + } + else + { + KURL tmp( rUrl, encoding_hint); + *this = tmp; + // Preserve userinfo if applicable. + if (!_u.m_strUser.isEmpty() && m_strUser.isEmpty() && (_u.m_strHost == m_strHost) && (_u.m_strProtocol == m_strProtocol)) + { + m_strUser = _u.m_strUser; + m_strPass = _u.m_strPass; + } + } +} + +void KURL::reset() +{ + m_strProtocol = QString::null; + m_strUser = QString::null; + m_strPass = QString::null; + m_strHost = QString::null; + m_strPath = QString::null; + m_strPath_encoded = QString::null; + m_strQuery_encoded = QString::null; + m_strRef_encoded = QString::null; + m_bIsMalformed = true; + m_iPort = 0; +} + +bool KURL::isEmpty() const +{ + return (m_strPath.isEmpty() && m_strProtocol.isEmpty()); +} + +void KURL::parse( const QString& _url, int encoding_hint ) +{ + //kdDebug(126) << "parse " << _url << endl; + // Return immediately whenever the given url + // is empty or null. + if ( _url.isEmpty() ) + { + m_strProtocol = _url; + return; + } + + QString port; + bool badHostName = false; + int start = 0; + uint len = _url.length(); + const QChar* buf = _url.unicode(); + const QChar* orig = buf; + + QChar delim; + QString tmp; + + uint pos = 0; + + // Node 1: Accept alpha or slash + QChar x = buf[pos++]; + if ( x == '/' ) + goto Node9; + if ( !isalpha( (int)x ) ) + goto NodeErr; + + // Node 2: Accept any amount of (alpha|digit|'+'|'-') + // '.' is not currently accepted, because current KURL may be confused. + // Proceed with :// :/ or : + while( pos < len && (isalpha((int)buf[pos]) || isdigit((int)buf[pos]) || + buf[pos] == '+' || buf[pos] == '-')) pos++; + + if ( pos+2 < len && buf[pos] == ':' && buf[pos+1] == '/' && buf[pos+2] == '/' ) + { + m_strProtocol = QString( orig, pos ).lower(); + pos += 3; + } + else if (pos+1 < len && buf[pos] == ':' ) // Need to always compare length()-1 otherwise KURL passes "http:" as legal!! + { + m_strProtocol = QString( orig, pos ).lower(); + //kdDebug(126)<<"setting protocol to "<<m_strProtocol<<endl; + pos++; + start = pos; + goto Node9; + } + else + goto NodeErr; + + //Node 3: We need at least one character here + if ( pos == len ) + goto NodeErr; + start = pos; + + // Node 4: Accept any amount of characters. + if (buf[pos] == '[') // An IPv6 host follows. + goto Node8; + // Terminate on / or @ or ? or # or " or ; or < + x = buf[pos]; + while( (x != ':') && (x != '@') && (x != '/') && (x != '?') && (x != '#') ) + { + if ((x == '\"') || (x == ';') || (x == '<')) + badHostName = true; + if (++pos == len) + break; + x = buf[pos]; + } + if ( pos == len ) + { + if (badHostName) + goto NodeErr; + + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + goto NodeOk; + } + if ( x == '@' ) + { + m_strUser = decode(QString( buf + start, pos - start ), encoding_hint); + pos++; + goto Node7; + } + else if ( (x == '/') || (x == '?') || (x == '#')) + { + if (badHostName) + goto NodeErr; + + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + start = pos; + goto Node9; + } + else if ( x != ':' ) + goto NodeErr; + m_strUser = decode(QString( buf + start, pos - start ), encoding_hint); + pos++; + + // Node 5: We need at least one character + if ( pos == len ) + goto NodeErr; + start = pos++; + + // Node 6: Read everything until @, /, ? or # + while( (pos < len) && + (buf[pos] != '@') && + (buf[pos] != '/') && + (buf[pos] != '?') && + (buf[pos] != '#')) pos++; + // If we now have a '@' the ':' seperates user and password. + // Otherwise it seperates host and port. + if ( (pos == len) || (buf[pos] != '@') ) + { + // Ok the : was used to separate host and port + if (badHostName) + goto NodeErr; + setHost(m_strUser); + m_strUser = QString::null; + QString tmp( buf + start, pos - start ); + char *endptr; + m_iPort = (unsigned short int)strtol(tmp.ascii(), &endptr, 10); + if ((pos == len) && (strlen(endptr) == 0)) + goto NodeOk; + // there is more after the digits + pos -= strlen(endptr); + start = pos++; + goto Node9; + } + m_strPass = decode(QString( buf + start, pos - start), encoding_hint); + pos++; + + // Node 7: We need at least one character + Node7: + if ( pos == len ) + goto NodeErr; + + Node8: + if (buf[pos] == '[') + { + // IPv6 address + start = ++pos; // Skip '[' + + if (pos == len) + { + badHostName = true; + goto NodeErr; + } + // Node 8b: Read everything until ] or terminate + badHostName = false; + x = buf[pos]; + while( (x != ']') ) + { + if ((x == '\"') || (x == ';') || (x == '<')) + badHostName = true; + if (++pos == len) + { + badHostName = true; + break; + } + x = buf[pos]; + } + if (badHostName) + goto NodeErr; + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + if (pos < len) pos++; // Skip ']' + if (pos == len) + goto NodeOk; + } + else + { + // Non IPv6 address + start = pos; + + // Node 8b: Read everything until / : or terminate + badHostName = false; + x = buf[pos]; + while( (x != ':') && (x != '@') && (x != '/') && (x != '?') && (x != '#') ) + { + if ((x == '\"') || (x == ';') || (x == '<')) + badHostName = true; + if (++pos == len) + break; + x = buf[pos]; + } + if (badHostName) + goto NodeErr; + if ( pos == len ) + { + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + goto NodeOk; + } + setHost(decode(QString( buf + start, pos - start ), encoding_hint)); + } + x = buf[pos]; + if ( x == '/' ) + { + start = pos++; + goto Node9; + } + else if ( x != ':' ) + goto NodeErr; + pos++; + + // Node 8a: Accept at least one digit + if ( pos == len ) + goto NodeErr; + start = pos; + if ( !isdigit( buf[pos++] ) ) + goto NodeErr; + + // Node 8b: Accept any amount of digits + while( pos < len && isdigit( buf[pos] ) ) pos++; + port = QString( buf + start, pos - start ); + m_iPort = port.toUShort(); + if ( pos == len ) + goto NodeOk; + start = pos++; + + Node9: // parse path until query or reference reached + + while( pos < len && buf[pos] != '#' && buf[pos]!='?' ) pos++; + + tmp = QString( buf + start, pos - start ); + //kdDebug(126)<<" setting encoded path&query to:"<<tmp<<endl; + setEncodedPath( tmp, encoding_hint ); + + if ( pos == len ) + goto NodeOk; + + //Node10: // parse query or reference depending on what comes first + delim = (buf[pos++]=='#'?'?':'#'); + + start = pos; + + while(pos < len && buf[pos]!=delim ) pos++; + + tmp = QString(buf + start, pos - start); + if (delim=='#') + setQuery(tmp, encoding_hint); + else + m_strRef_encoded = tmp; + + if (pos == len) + goto NodeOk; + + //Node11: // feed the rest into the remaining variable + tmp = QString( buf + pos + 1, len - pos - 1); + if (delim == '#') + m_strRef_encoded = tmp; + else + setQuery(tmp, encoding_hint); + + NodeOk: + //kdDebug(126)<<"parsing finished. m_strProtocol="<<m_strProtocol<<" m_strHost="<<m_strHost<<" m_strPath="<<m_strPath<<endl; + m_bIsMalformed = false; // Valid URL + + //kdDebug()<<"Prot="<<m_strProtocol<<"\nUser="<<m_strUser<<"\nPass="<<m_strPass<<"\nHost="<<m_strHost<<"\nPath="<<m_strPath<<"\nQuery="<<m_strQuery_encoded<<"\nRef="<<m_strRef_encoded<<"\nPort="<<m_iPort<<endl; + if (m_strProtocol.isEmpty()) + { + m_strProtocol = fileProt; + } + return; + + NodeErr: +// kdDebug(126) << "KURL couldn't parse URL \"" << _url << "\"" << endl; + reset(); + m_strProtocol = _url; +} + +KURL& KURL::operator=( const QString& _url ) +{ + reset(); + parse( _url ); + + return *this; +} + +KURL& KURL::operator=( const char * _url ) +{ + reset(); + parse( QString::fromLatin1(_url) ); + + return *this; +} + +#ifndef QT_NO_NETWORKPROTOCOL +KURL& KURL::operator=( const QUrl & u ) +{ + m_strProtocol = u.protocol(); + m_strUser = u.user(); + m_strPass = u.password(); + m_strHost = u.host(); + m_strPath = u.path( FALSE ); + m_strPath_encoded = QString::null; + m_strQuery_encoded = u.query(); + m_strRef_encoded = u.ref(); + m_bIsMalformed = !u.isValid(); + m_iPort = u.port(); + + return *this; +} +#endif + +KURL& KURL::operator=( const KURL& _u ) +{ + m_strProtocol = _u.m_strProtocol; + m_strUser = _u.m_strUser; + m_strPass = _u.m_strPass; + m_strHost = _u.m_strHost; + m_strPath = _u.m_strPath; + m_strPath_encoded = _u.m_strPath_encoded; + m_strQuery_encoded = _u.m_strQuery_encoded; + m_strRef_encoded = _u.m_strRef_encoded; + m_bIsMalformed = _u.m_bIsMalformed; + m_iPort = _u.m_iPort; + + return *this; +} + +bool KURL::operator==( const KURL& _u ) const +{ + if ( isMalformed() || _u.isMalformed() ) + return false; + + if ( m_strProtocol == _u.m_strProtocol && + m_strUser == _u.m_strUser && + m_strPass == _u.m_strPass && + m_strHost == _u.m_strHost && + m_strPath == _u.m_strPath && + // The encoded path may be null, but the URLs are still equal (David) + ( m_strPath_encoded.isNull() || _u.m_strPath_encoded.isNull() || + m_strPath_encoded == _u.m_strPath_encoded ) && + m_strQuery_encoded == _u.m_strQuery_encoded && + m_strRef_encoded == _u.m_strRef_encoded && + m_iPort == _u.m_iPort ) + { + return true; + } + + return false; +} + +bool KURL::operator==( const QString& _u ) const +{ + KURL u( _u ); + return ( *this == u ); +} + +bool KURL::cmp( const KURL &u, bool ignore_trailing ) const +{ + return equals( u, ignore_trailing ); +} + +bool KURL::equals( const KURL &_u, bool ignore_trailing ) const +{ + if ( isMalformed() || _u.isMalformed() ) + return false; + + if ( ignore_trailing ) + { + QString path1 = path(1); + QString path2 = _u.path(1); + if ( path1 != path2 ) + return false; + + if ( m_strProtocol == _u.m_strProtocol && + m_strUser == _u.m_strUser && + m_strPass == _u.m_strPass && + m_strHost == _u.m_strHost && + m_strQuery_encoded == _u.m_strQuery_encoded && + m_strRef_encoded == _u.m_strRef_encoded && + m_iPort == _u.m_iPort ) + return true; + + return false; + } + + return ( *this == _u ); +} + +bool KURL::isParentOf( const KURL& _u ) const +{ + if ( isMalformed() || _u.isMalformed() ) + return false; + + if ( m_strProtocol == _u.m_strProtocol && + m_strUser == _u.m_strUser && + m_strPass == _u.m_strPass && + m_strHost == _u.m_strHost && + m_strQuery_encoded == _u.m_strQuery_encoded && + m_strRef_encoded == _u.m_strRef_encoded && + m_iPort == _u.m_iPort ) + { + if ( path().isEmpty() || _u.path().isEmpty() ) + return false; // can't work with implicit paths + + QString p1( cleanpath( path() ) ); + if ( p1.at(p1.length()-1) != '/' ) + p1 += '/'; + QString p2( cleanpath( _u.path() ) ); + if ( p2.at(p2.length()-1) != '/' ) + p2 += '/'; + + //kdDebug(126) << "p1=" << p1 << endl; + //kdDebug(126) << "p2=" << p2 << endl; + //kdDebug(126) << "p1.length()=" << p1.length() << endl; + //kdDebug(126) << "p2.left(!$)=" << p2.left( p1.length() ) << endl; + return p2.startsWith( p1 ); + } + return false; +} + +void KURL::setFileName( const QString& _txt ) +{ + m_strRef_encoded = QString::null; + int i = 0; + while( _txt[i] == '/' ) ++i; + QString tmp; + if ( i ) + tmp = _txt.mid( i ); + else + tmp = _txt; + + QString path = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded; + if ( path.isEmpty() ) + path = "/"; + else + { + int lastSlash = path.findRev( '/' ); + if ( lastSlash == -1) + { + // The first character is not a '/' ??? + // This looks strange ... + path = "/"; + } + else if ( path.right(1) != "/" ) + path.truncate( lastSlash+1 ); // keep the "/" + } + if (m_strPath_encoded.isEmpty()) + { + path += tmp; + setPath( path ); + } + else + { + path += encode_string(tmp); + setEncodedPath( path ); + } + cleanPath(); +} + +void KURL::cleanPath( bool cleanDirSeparator ) // taken from the old KURL +{ + m_strPath = cleanpath(m_strPath, cleanDirSeparator); + // WABA: Is this safe when "/../" is encoded with %? + m_strPath_encoded = cleanpath(m_strPath_encoded, cleanDirSeparator); +} + +static QString trailingSlash( int _trailing, const QString &path ) +{ + QString result = path; + + if ( _trailing == 0 ) + return result; + else if ( _trailing == 1 ) + { + int len = result.length(); + if ( len == 0 ) + result = QString::null; + else if ( result[ len - 1 ] != '/' ) + result += "/"; + return result; + } + else if ( _trailing == -1 ) + { + if ( result == "/" ) + return result; + int len = result.length(); + if ( len != 0 && result[ len - 1 ] == '/' ) + result.truncate( len - 1 ); + return result; + } + else { + assert( 0 ); + return QString::null; + } +} + +void KURL::adjustPath( int _trailing ) +{ + if (!m_strPath_encoded.isEmpty()) + { + m_strPath_encoded = trailingSlash( _trailing, m_strPath_encoded ); + } + m_strPath = trailingSlash( _trailing, m_strPath ); +} + + +QString KURL::encodedPathAndQuery( int _trailing, bool _no_empty_path, int encoding_hint ) const +{ + QString tmp; + if (!m_strPath_encoded.isEmpty() && encoding_hint == 0) + { + tmp = trailingSlash( _trailing, m_strPath_encoded ); + } + else + { + tmp = path( _trailing ); + if ( _no_empty_path && tmp.isEmpty() ) + tmp = "/"; + tmp = encode( tmp, false, encoding_hint ); + } + + // TODO apply encoding_hint to the query + if (!m_strQuery_encoded.isNull()) + tmp += '?' + m_strQuery_encoded; + return tmp; +} + +void KURL::setEncodedPath( const QString& _txt, int encoding_hint ) +{ + m_strPath_encoded = _txt; + + decode( m_strPath_encoded, m_strPath, m_strPath_encoded, encoding_hint ); + // Throw away encoding for local files, makes file-operations faster. + if (m_strProtocol == fileProt) + m_strPath_encoded = QString::null; +} + + +void KURL::setEncodedPathAndQuery( const QString& _txt, int encoding_hint ) +{ + int pos = _txt.find( '?' ); + if ( pos == -1 ) + { + setEncodedPath(_txt, encoding_hint); + m_strQuery_encoded = QString::null; + } + else + { + setEncodedPath(_txt.left( pos ), encoding_hint); + setQuery(_txt.right(_txt.length() - pos - 1), encoding_hint); + } +} + +QString KURL::path( int _trailing ) const +{ + return trailingSlash( _trailing, path() ); +} + +bool KURL::isLocalFile() const +{ + if ( (m_strProtocol != fileProt ) || hasSubURL() ) + return false; + + if (m_strHost.isEmpty() || (m_strHost == "localhost")) + return true; + + char hostname[ 256 ]; + hostname[ 0 ] = '\0'; +#ifdef _WIN32_ + // pending LR fixme + //hostname = "localhost"; +#else + if (!gethostname( hostname, 255 )) + hostname[sizeof(hostname)-1] = '\0'; +#endif + for(char *p = hostname; *p; p++) + *p = tolower(*p); + + return (m_strHost == hostname); +} + +void KURL::setFileEncoding(const QString &encoding) +{ + if (!isLocalFile()) + return; + + QString q = query(); + + if (!q.isEmpty() && (q[0] == '?')) + q = q.mid(1); + + QStringList args = QStringList::split('&', q); + for(QStringList::Iterator it = args.begin(); + it != args.end();) + { + QString s = decode_string(*it); + if (s.startsWith("charset=")) +//US changed erase into remove ??? + it = args.remove(it); + else + ++it; + } + if (!encoding.isEmpty()) + args.append("charset="+encode_string(encoding)); + + if (args.isEmpty()) + setQuery(QString::null); + else + setQuery(args.join("&")); +} + +QString KURL::fileEncoding() const +{ + if (!isLocalFile()) + return QString::null; + + QString q = query(); + + if (q.isEmpty()) + return QString::null; + + if (q[0] == '?') + q = q.mid(1); + + QStringList args = QStringList::split('&', q); + for(QStringList::ConstIterator it = args.begin(); + it != args.end(); + ++it) + { + QString s = decode_string(*it); + if (s.startsWith("charset=")) + return s.mid(8); + } + return QString::null; +} + +bool KURL::hasSubURL() const +{ + if ( m_strProtocol.isEmpty() || m_bIsMalformed ) + return false; + if (m_strRef_encoded.isEmpty()) + return false; + if (m_strRef_encoded.startsWith("gzip:")) + return true; + if (m_strRef_encoded.startsWith("bzip:")) + return true; + if (m_strRef_encoded.startsWith("bzip2:")) + return true; + if (m_strRef_encoded.startsWith("tar:")) + return true; + if ( m_strProtocol == "error" ) // anything that starts with error: has suburls + return true; + return false; +} + +QString KURL::url( int _trailing, int encoding_hint ) const +{ + if( m_bIsMalformed ) + { + // Return the whole url even when the url is + // malformed. Under such conditions the url + // is stored in m_strProtocol. + return m_strProtocol; + } + + QString u = m_strProtocol; + if (!u.isEmpty()) + u += ":"; + + if ( hasHost() ) + { + u += "//"; + if ( hasUser() ) + { + u += encode(m_strUser, true, encoding_hint); + if ( hasPass() ) + { + u += ":"; + u += encode(m_strPass, true, encoding_hint); + } + u += "@"; + } + bool IPv6 = (m_strHost.find(':') != -1); + if (IPv6) + u += '[' + m_strHost + ']'; + else + u += encodeHost(m_strHost, true, encoding_hint); + if ( m_iPort != 0 ) { + QString buffer; + buffer.sprintf( ":%u", m_iPort ); + u += buffer; + } + } + + u += encodedPathAndQuery( _trailing, false, encoding_hint ); + + if ( hasRef() ) + { + u += "#"; + u += m_strRef_encoded; + } + + return u; +} + +QString KURL::prettyURL( int _trailing ) const +{ + if( m_bIsMalformed ) + { + // Return the whole url even when the url is + // malformed. Under such conditions the url + // is stored in m_strProtocol. + return m_strProtocol; + } + + QString u = m_strProtocol; + if (!u.isEmpty()) + u += ":"; + + if ( hasHost() ) + { + u += "//"; + if ( hasUser() ) + { + u += lazy_encode(m_strUser); + // Don't show password! + u += "@"; + } + bool IPv6 = (m_strHost.find(':') != -1); + if (IPv6) + { + u += '[' + m_strHost + ']'; + } + else + { + u += lazy_encode(m_strHost); + } + if ( m_iPort != 0 ) { + QString buffer; + buffer.sprintf( ":%u", m_iPort ); + u += buffer; + } + } + + u += trailingSlash( _trailing, lazy_encode( m_strPath ) ); + if (!m_strQuery_encoded.isNull()) + u += '?' + m_strQuery_encoded; + + if ( hasRef() ) + { + u += "#"; + u += m_strRef_encoded; + } + + return u; +} + +QString KURL::prettyURL( int _trailing, AdjustementFlags _flags) const +{ + QString u = prettyURL(_trailing); + if (_flags & StripFileProtocol && u.startsWith("file:")) + u.remove(0, 5); + return u; +} + +QString KURL::htmlURL() const +{ +//US QStyleSheet::escape was not in my Qt distribution. Why ??? +//US return QStyleSheet::escape(prettyURL()); + return prettyURL(); +} + +KURL::List KURL::split( const KURL& _url ) +{ + QString ref; + KURL::List lst; + KURL url = _url; + + while(true) + { + KURL u = url; + u.m_strRef_encoded = QString::null; + lst.append(u); + if (url.hasSubURL()) + { + url = KURL(url.m_strRef_encoded); + } + else + { + ref = url.m_strRef_encoded; + break; + } + } + + // Set HTML ref in all URLs. + KURL::List::Iterator it; + for( it = lst.begin() ; it != lst.end(); ++it ) + { + (*it).m_strRef_encoded = ref; + } + + return lst; +} + +KURL::List KURL::split( const QString& _url ) +{ + return split(KURL(_url)); +} + +KURL KURL::join( const KURL::List & lst ) +{ + if (lst.isEmpty()) return KURL(); + KURL tmp; + + KURL::List::ConstIterator first = lst.fromLast(); + for( KURL::List::ConstIterator it = first; it != lst.end(); --it ) + { + KURL u(*it); + if (it != first) + { + if (!u.m_strRef_encoded) u.m_strRef_encoded = tmp.url(); + else u.m_strRef_encoded += "#" + tmp.url(); // Support more than one suburl thingy + } + tmp = u; + } + + return tmp; +} + +QString KURL::fileName( bool _strip_trailing_slash ) const +{ + QString fname; + if (hasSubURL()) { // If we have a suburl, then return the filename from there + KURL::List list = KURL::split(*this); + KURL::List::Iterator it = list.fromLast(); + return (*it).fileName(_strip_trailing_slash); + } + const QString &path = m_strPath; + + int len = path.length(); + if ( len == 0 ) + return fname; + + if ( _strip_trailing_slash ) + { + while ( len >= 1 && path[ len - 1 ] == '/' ) + len--; + } + else if ( path[ len - 1 ] == '/' ) + return fname; + + // Does the path only consist of '/' characters ? + if ( len == 1 && path[ 0 ] == '/' ) + return fname; + + // Skip last n slashes + int n = 1; + if (!m_strPath_encoded.isEmpty()) + { + // This is hairy, we need the last unencoded slash. + // Count in the encoded string how many encoded slashes follow the last + // unencoded one. + int i = m_strPath_encoded.findRev( '/', len - 1 ); + QString fileName_encoded = m_strPath_encoded.mid(i+1); + n += fileName_encoded.contains("%2f", false); + } + int i = len; + do { + i = path.findRev( '/', i - 1 ); + } + while (--n && (i > 0)); + + // If ( i == -1 ) => the first character is not a '/' + // So it's some URL like file:blah.tgz, return the whole path + if ( i == -1 ) { + if ( len == (int)path.length() ) + fname = path; + else + // Might get here if _strip_trailing_slash is true + fname = path.left( len ); + } + else + { + fname = path.mid( i + 1, len - i - 1 ); // TO CHECK + } + return fname; +} + +void KURL::addPath( const QString& _txt ) +{ + if (hasSubURL()) + { + KURL::List lst = split( *this ); + KURL &u = lst.last(); + u.addPath(_txt); + *this = join( lst ); + return; + } + + m_strPath_encoded = QString::null; + + if ( _txt.isEmpty() ) + return; + + int i = 0; + int len = m_strPath.length(); + // NB: avoid three '/' when building a new path from nothing + if ( len == 0 ) { + while( _txt[i] == '/' ) ++i; + } + // Add the trailing '/' if it is missing + else if ( _txt[0] != '/' && ( len == 0 || m_strPath[ len - 1 ] != '/' ) ) + m_strPath += "/"; + + // No double '/' characters + i = 0; + if ( len != 0 && m_strPath[ len - 1 ] == '/' ) + { + while( _txt[i] == '/' ) + ++i; + } + + m_strPath += _txt.mid( i ); +} + +QString KURL::directory( bool _strip_trailing_slash_from_result, + bool _ignore_trailing_slash_in_path ) const +{ + QString result = m_strPath_encoded.isEmpty() ? m_strPath : m_strPath_encoded; + if ( _ignore_trailing_slash_in_path ) + result = trailingSlash( -1, result ); + + if ( result.isEmpty() || result == "/" ) + return result; + + int i = result.findRev( "/" ); + // If ( i == -1 ) => the first character is not a '/' + // So it's some URL like file:blah.tgz, with no path + if ( i == -1 ) + return QString::null; + + if ( i == 0 ) + { + result = "/"; + return result; + } + + if ( _strip_trailing_slash_from_result ) + result = result.left( i ); + else + result = result.left( i + 1 ); + + if (!m_strPath_encoded.isEmpty()) + result = decode(result); + + return result; +} + + +bool KURL::cd( const QString& _dir ) +{ + if ( _dir.isEmpty() || m_bIsMalformed ) + return false; + + if (hasSubURL()) + { + KURL::List lst = split( *this ); + KURL &u = lst.last(); + u.cd(_dir); + *this = join( lst ); + return true; + } + + // absolute path ? + if ( _dir[0] == '/' ) + { + m_strPath_encoded = QString::null; + m_strPath = _dir; + setHTMLRef( QString::null ); + m_strQuery_encoded = QString::null; + return true; + } + + // Users home directory on the local disk ? + if ( ( _dir[0] == '~' ) && ( m_strProtocol == fileProt )) + { + m_strPath_encoded = QString::null; + m_strPath = QDir::homeDirPath(); + m_strPath += "/"; + m_strPath += _dir.right(m_strPath.length() - 1); + setHTMLRef( QString::null ); + m_strQuery_encoded = QString::null; + return true; + } + + // relative path + // we always work on the past of the first url. + // Sub URLs are not touched. + + // append '/' if necessary + QString p = path(1); + p += _dir; + p = cleanpath( p ); + setPath( p ); + + setHTMLRef( QString::null ); + m_strQuery_encoded = QString::null; + + return true; +} + +KURL KURL::upURL( ) const +{ + if (!query().isEmpty()) + { + KURL u(*this); + u.setQuery(QString::null); + return u; + }; + + if (!hasSubURL()) + { + KURL u(*this); + u.cd("../"); + return u; + } + + // We have a subURL. + KURL::List lst = split( *this ); + if (lst.isEmpty()) + return KURL(); // Huh? + while (true) + { + KURL &u = lst.last(); + QString old = u.path(); + u.cd("../"); + if (u.path() != old) + break; // Finshed. + if (lst.count() == 1) + break; // Finished. + lst.remove(lst.fromLast()); + } + return join( lst ); +} + +QString KURL::htmlRef() const +{ + if ( !hasSubURL() ) + { + return decode( ref() ); + } + + List lst = split( *this ); + return decode( (*lst.begin()).ref() ); +} + +QString KURL::encodedHtmlRef() const +{ + if ( !hasSubURL() ) + { + return ref(); + } + + List lst = split( *this ); + return (*lst.begin()).ref(); +} + +void KURL::setHTMLRef( const QString& _ref ) +{ + if ( !hasSubURL() ) + { + m_strRef_encoded = encode( _ref, true, 0 /*?*/); + return; + } + + List lst = split( *this ); + + (*lst.begin()).setRef( encode( _ref, true, 0 /*?*/) ); + + *this = join( lst ); +} + +bool KURL::hasHTMLRef() const +{ + if ( !hasSubURL() ) + { + return hasRef(); + } + + List lst = split( *this ); + return (*lst.begin()).hasRef(); +} + +void +KURL::setProtocol( const QString& _txt ) +{ + m_strProtocol = _txt; + m_bIsMalformed = false; +} + +void +KURL::setUser( const QString& _txt ) +{ + m_strUser = _txt; +} + +void +KURL::setPass( const QString& _txt ) +{ + m_strPass = _txt; +} + +void +KURL::setHost( const QString& _txt ) +{ +#ifndef KDE_QT_ONLY + m_strHost = KIDNA::toUnicode(_txt); + if (m_strHost.isEmpty()) + m_strHost = _txt.lower(); // Probably an invalid hostname, but... +#else + m_strHost = _txt.lower(); +#endif +} + +void +KURL::setPort( unsigned short int _p ) +{ + m_iPort = _p; +} + +void KURL::setPath( const QString & path ) +{ + if (isEmpty()) + m_bIsMalformed = false; + if (m_strProtocol.isEmpty()) + { + m_strProtocol = fileProt; + } + m_strPath = path; + m_strPath_encoded = QString::null; +} + +void KURL::setDirectory( const QString &dir) +{ +//US this has to be fixed. endsWith is not available in my distribution +//US if ( dir.endsWith("/")) +//US setPath(dir); +//US else + setPath(dir+"/"); +} + +void KURL::setQuery( const QString &_txt, int encoding_hint) +{ + if (!_txt.length()) + { + m_strQuery_encoded = _txt; + return; + } + if (_txt[0] =='?') + m_strQuery_encoded = _txt.mid(1); + else + m_strQuery_encoded = _txt; + + int l = m_strQuery_encoded.length(); + int i = 0; + QString result; + while (i < l) + { + int s = i; + // Re-encode. Break encoded string up according to the reserved + // characters '&:;=/?' and re-encode part by part. + while(i < l) + { + char c = m_strQuery_encoded[i].latin1(); + if ((c == '&') || (c == ':') || (c == ';') || + (c == '=') || (c == '/') || (c == '?')) + break; + i++; + } + if (i > s) + { + QString tmp = m_strQuery_encoded.mid(s, i-s); + QString newTmp; + decode( tmp, newTmp, tmp, encoding_hint, false ); + result += tmp; + } + if (i < l) + { + result += m_strQuery_encoded[i]; + i++; + } + } + m_strQuery_encoded = result; +} + +QString KURL::query() const +{ + if (m_strQuery_encoded.isNull()) + return QString::null; + return '?'+m_strQuery_encoded; +} + +QString KURL::decode_string(const QString &str, int encoding_hint) +{ + return decode(str, encoding_hint); +} + +QString KURL::encode_string(const QString &str, int encoding_hint) +{ + return encode(str, false, encoding_hint); +} + +QString KURL::encode_string_no_slash(const QString &str, int encoding_hint) +{ + return encode(str, true, encoding_hint); +} + +bool urlcmp( const QString& _url1, const QString& _url2 ) +{ + // Both empty ? + if ( _url1.isEmpty() && _url2.isEmpty() ) + return true; + // Only one empty ? + if ( _url1.isEmpty() || _url2.isEmpty() ) + return false; + + KURL::List list1 = KURL::split( _url1 ); + KURL::List list2 = KURL::split( _url2 ); + + // Malformed ? + if ( list1.isEmpty() || list2.isEmpty() ) + return false; + + return ( list1 == list2 ); +} + +bool urlcmp( const QString& _url1, const QString& _url2, bool _ignore_trailing, bool _ignore_ref ) +{ + // Both empty ? + if ( _url1.isEmpty() && _url2.isEmpty() ) + return true; + // Only one empty ? + if ( _url1.isEmpty() || _url2.isEmpty() ) + return false; + + KURL::List list1 = KURL::split( _url1 ); + KURL::List list2 = KURL::split( _url2 ); + + // Malformed ? + if ( list1.isEmpty() || list2.isEmpty() ) + return false; + + unsigned int size = list1.count(); + if ( list2.count() != size ) + return false; + + if ( _ignore_ref ) + { + (*list1.begin()).setRef(QString::null); + (*list2.begin()).setRef(QString::null); + } + + KURL::List::Iterator it1 = list1.begin(); + KURL::List::Iterator it2 = list2.begin(); + for( ; it1 != list1.end() ; ++it1, ++it2 ) + if ( !(*it1).equals( *it2, _ignore_trailing ) ) + return false; + + return true; +} +/*US we do not need this functions + +QMap< QString, QString > KURL::queryItems( int options ) const { + return queryItems(options, 0); +} + +QMap< QString, QString > KURL::queryItems( int options, int encoding_hint ) const { + if ( m_strQuery_encoded.isEmpty() ) + return QMap<QString,QString>(); + + QMap< QString, QString > result; + QStringList items = QStringList::split( '&', m_strQuery_encoded ); + for ( QStringList::const_iterator it = items.begin() ; it != items.end() ; ++it ) { + int equal_pos = (*it).find( '=' ); + if ( equal_pos > 0 ) { // = is not the first char... + QString name = (*it).left( equal_pos ); + if ( options & CaseInsensitiveKeys ) + name = name.lower(); + QString value = (*it).mid( equal_pos + 1 ); + if ( value.isEmpty() ) + result.insert( name, QString::fromLatin1("") ); + else { + // ### why is decoding name not neccessary? + value.replace( '+', ' ' ); // + in queries means space + result.insert( name, decode_string( value, encoding_hint ) ); + } + } else if ( equal_pos < 0 ) { // no = + QString name = (*it); + if ( options & CaseInsensitiveKeys ) + name = name.lower(); + result.insert( name, QString::null ); + } + } + + return result; +} + +QString KURL::queryItem( const QString& _item ) const +{ + return queryItem( _item, 0 ); +} + +QString KURL::queryItem( const QString& _item, int encoding_hint ) const +{ + QString item = _item + '='; + if ( m_strQuery_encoded.length() <= 1 ) + return QString::null; + + QStringList items = QStringList::split( '&', m_strQuery_encoded ); + unsigned int _len = item.length(); + for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it ) + { + if ( (*it).startsWith( item ) ) + { + if ( (*it).length() > _len ) + { + QString str = (*it).mid( _len ); + str.replace( '+', ' ' ); // + in queries means space. + return decode_string( str, encoding_hint ); + } + else // empty value + return QString::fromLatin1(""); + } + } + + return QString::null; +} +US we do not need this functions*/ + +void KURL::removeQueryItem( const QString& _item ) +{ + QString item = _item + '='; + if ( m_strQuery_encoded.length() <= 1 ) + return; + + QStringList items = QStringList::split( '&', m_strQuery_encoded ); + for ( QStringList::Iterator it = items.begin(); it != items.end(); ) + { + if ( (*it).startsWith( item ) || (*it == _item) ) + { + QStringList::Iterator deleteIt = it; + ++it; + items.remove(deleteIt); + } + else + { + ++it; + } + } + m_strQuery_encoded = items.join( "&" ); +} + +void KURL::addQueryItem( const QString& _item, const QString& _value, int encoding_hint ) +{ + QString item = _item + '='; + QString value = encode( _value, true, encoding_hint ); + + if (!m_strQuery_encoded.isEmpty()) + m_strQuery_encoded += '&'; + m_strQuery_encoded += item + value; +} + +// static +KURL KURL::fromPathOrURL( const QString& text ) +{ + if ( text.isEmpty() ) + return KURL(); + + KURL url; + if ( text[0] == '/' ) + url.setPath( text ); + else + url = text; + + return url; +} diff --git a/microkde/kurl.h b/microkde/kurl.h new file mode 100644 index 0000000..cd65a1c --- a/dev/null +++ b/microkde/kurl.h @@ -0,0 +1,853 @@ +/* This file is part of the KDE libraries + * Copyright (C) 1999 Torben Weis <weis@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + **/ + +#ifndef __kurl_h__ +#define __kurl_h__ "$Id$" + +#include <qstring.h> +#include <qvaluelist.h> + +class QUrl; +class QStringList; +template <typename K, typename V> class QMap; + +class KURLPrivate; +/** + * Represents and parses a URL. + * + * A prototypical URL looks like: + * <pre> + * protocol:/user:password\@hostname:port/path/to/file.ext#reference + * </pre> + * + * KURL has some restrictions regarding the path + * encoding. KURL works internally with the decoded path and + * and encoded query. For example, + * <pre> + * http://localhost/cgi-bin/test%20me.pl?cmd=Hello%20you + * </pre> + * would result in a decoded path "/cgi-bin/test me.pl" + * and in the encoded query "?cmd=Hello%20you". + * Since path is internally always encoded you may @em not use + * "%00" in the path, although this is OK for the query. + * + * @author Torben Weis <weis@kde.org> + */ +class KURL +{ +public: + enum AdjustementFlags + { + NoAdjustements = 0, + StripFileProtocol = 1 + }; + + /** + * KURL::List is a QValueList that contains KURLs with a few + * convenience methods. + * @see KURL + * @see QValueList + */ + class List : public QValueList<KURL> + { + public: + /** + * Creates an empty List. + */ + List() { } + /** + * Creates a list that contains the given URL as only + * item. + * @param url the url to add. + */ + List(const KURL &url); + /** + * Creates a list that contains the URLs from the given + * list. + * @param list the list containing the URLs as strings + */ + List(const QStringList &list); + /** + * Converts the URLs of this list to a list of strings. + * @return the list of strings + */ + QStringList toStringList() const; + }; + /** + * Constructs an empty URL. + */ + KURL(); + + /** + * Destructs the KURL object. + */ + ~KURL(); + + /** + * Usual constructor, to construct from a string. + * @param url A URL, not a filename. If the URL does not have a protocol + * part, "file:" is assumed. + * It is dangerous to feed unix filenames into this function, + * this will work most of the time but not always. + * For example "/home/Torben%20Weis" will be considered a URL + * pointing to the file "/home/Torben Weis" instead of to the + * file "/home/Torben%20Weis". + * This means that if you have a usual UNIX like path you + * should not use this constructor. + * Instead create an empty url and set the path by using + * @ref setPath(). + * @param encoding_hint MIB of original encoding of URL. + * @see QTextCodec::mibEnum() + */ + KURL( const QString& url, int encoding_hint = 0 ); + /** + * Constructor taking a char * @p url, which is an _encoded_ representation + * of the URL, exactly like the usual constructor. This is useful when + * then URL, in its encoded form, is strictly ascii. + * @param url A encoded URL. If the URL does not have a protocol part, + * "file:" is assumed. + * @param encoding_hint MIB of original encoding of URL. + * @see QTextCodec::mibEnum() + */ + KURL( const char * url, int encoding_hint = 0 ); + /** + * Constructor taking a QCString @p url, which is an _encoded_ representation + * of the URL, exactly like the usual constructor. This is useful when + * then URL, in its encoded form, is strictly ascii. + * @param url A encoded URL. If the URL does not have a protocol part, + * "file:" is assumed. + * @param encoding_hint MIB of original encoding of URL. + * @see QTextCodec::mibEnum() + */ + KURL( const QCString& url, int encoding_hint = 0 ); + /** + * Copy constructor. + * @param u the KURL to copy + */ + KURL( const KURL& u ); + /** + * Converts from a @ref QUrl. + * @param u the QUrl + */ + KURL( const QUrl &u ); + /** + * Constructor allowing relative URLs. + * + * @param _baseurl The base url. + * @param _rel_url A relative or absolute URL. + * If this is an absolute URL then @p _baseurl will be ignored. + * If this is a relative URL it will be combined with @p _baseurl. + * Note that _rel_url should be encoded too, in any case. + * So do NOT pass a path here (use setPath or addPath instead). + * @param encoding_hint MIB of original encoding of URL. + * @see QTextCodec::mibEnum() + */ + KURL( const KURL& _baseurl, const QString& _rel_url, int encoding_hint=0 ); + + /** + * Returns the protocol for the URL (i.e., file, http, etc.). + * @return the protocol of the URL, does not include the colon. If the + * URL is malformed, QString::null will be returned. + **/ + QString protocol() const { return m_bIsMalformed ? QString::null : m_strProtocol; } + /** + * Sets the protocol for the URL (i.e., file, http, etc.) + * @param _txt the new protocol of the URL (without colon) + **/ + void setProtocol( const QString& _txt ); + + /** + * Returns the decoded user name (login, user id, ...) included in the URL. + * @return the user name or QString::null if there is no user name + **/ + QString user() const { return m_strUser; } + /** + * Sets the user name (login, user id, ...) included in the URL. + * + * Special characters in the user name will appear encoded in the URL. + * @param _txt the name of the user or QString::null to remove the user + **/ + void setUser( const QString& _txt ); + /** + * Test to see if this URL has a user name included in it. + * @return true if the URL has an non-empty user name + **/ + bool hasUser() const { return !m_strUser.isEmpty(); } + + /** + * Returns the decoded password (corresponding to \ref user()) included in the URL. + * @return the password or QString::null if it does not exist + **/ + QString pass() const { return m_strPass; } + /** + * Sets the password (corresponding to @ref user()) included in the URL. + * + * Special characters in the password will appear encoded in the URL. + * Note that a password can only appear in a URL string if you also set + * a user. + * @param _txt the password to set or QString::null to remove the password + * @see #setUser + * @see #hasUser + **/ + void setPass( const QString& _txt ); + /** + * Test to see if this URL has a password included in it. + * @return true if there is a non-empty password set + **/ + bool hasPass() const { return !m_strPass.isEmpty(); } + + /** + * Returns the decoded hostname included in the URL. + * @return the name of the host or QString::null if no host is set + **/ + QString host() const { return m_strHost; } + + /** + * Sets the hostname included in the URL. + * + * Special characters in the hostname will appear encoded in the URL. + * @param _txt the new name of the host or QString::null to remove the host + **/ + void setHost( const QString& _txt ); + /** + * Test to see if this URL has a hostname included in it. + * @return true if the URL has a host + **/ + bool hasHost() const { return !m_strHost.isEmpty(); } + + /** + * Returns the port number included in the URL. + * @return the port number. If there is no port number specified in the + * URL, returns 0. + **/ + unsigned short int port() const { return m_iPort; } + /** + * Sets the port number included in the URL. + * @param _p the new port number or 0 to have no port number + **/ + void setPort( unsigned short int _p ); + + /** + * Returns the current decoded path. This does @em not include the query. + * @return the path of the URL (without query), or QString::null if no + * path set. + */ + QString path() const { return m_strPath; } + + /** + * @param _trailing May be ( -1, 0 +1 ). -1 strips a trailing '/', +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. If the URL has no path, then no '/' is added + * anyway. And on the other side: If the path is "/", then this + * character won't be stripped. Reason: "ftp://weis\@host" means something + * completely different than "ftp://weis\@host/". So adding or stripping + * the '/' would really alter the URL, while "ftp://host/path" and + * "ftp://host/path/" mean the same directory. + * + * @return The current decoded path. This does not include the query. Can + * be QString::null if no path is set. + */ + QString path( int _trailing ) const; + + /** + * Sets the path of the URL. The query is not changed by this function. + * + * @param path The new path. This is considered to be decoded. This + * means: %3f does not become decoded + * and the ? does not indicate the start of the query part. + * Can be QString::null to delete the path. + */ + void setPath( const QString& path ); + + /** + * Test to see if this URL has a path is included in it. + * @return true if there is a path + **/ + bool hasPath() const { return !m_strPath.isEmpty(); } + + /** + * Resolves "." and ".." components in path. + * Some servers seem not to like the removal of extra '/' + * even though it is against the specification in RFC 2396. + * + * @param cleanDirSeparator if true, occurrances of consecutive + * directory separators (e.g. /foo//bar) are cleaned up as well. + */ + void cleanPath(bool cleanDirSeparator = true); + + /** + * Add or remove a trailing slash to/from the path. + * @param _trailing May be ( -1, 0 +1 ). -1 strips a trailing '/', +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. If the URL has no path, then no '/' is added + * anyway. And on the other side: If the path is "/", then this + * character won't be stripped. Reason: "ftp://weis\@host" means something + * completely different than "ftp://weis\@host/". So adding or stripping + * the '/' would really alter the URL, while "ftp://host/path" and + * "ftp://host/path/" mean the same directory. + */ + void adjustPath(int _trailing); + + /** + * This is useful for HTTP. It looks first for '?' and decodes then. + * The encoded path is the concatenation of the current path and the query. + * @param _txt the new path and query. + * @param encoding_hint MIB of original encoding of @p _txt . + * @see QTextCodec::mibEnum() + */ + void setEncodedPathAndQuery( const QString& _txt, int encoding_hint = 0 ); + + /** + * Sets the (already encoded) path + * @param _txt the new path + * @param encoding_hint MIB of original encoding of @p _txt . + * @see QTextCodec::mibEnum() + */ + void setEncodedPath(const QString& _txt, int encoding_hint = 0 ); + + /** + * Returns the encoded path and the query. + * + * @param _trailing May be ( -1, 0 +1 ). -1 strips a trailing '/', +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. If the URL has no path, then no '/' is added + * anyway. And on the other side: If the path is "/", then this + * character won't be stripped. Reason: "ftp://weis\@host" means something + * completely different than "ftp://weis\@host/". So adding or stripping + * the '/' would really alter the URL, while "ftp://host/path" and + * "ftp://host/path/" mean the same directory. + * @param _no_empty_path If set to true then an empty path is substituted by "/". + * @param encoding_hint MIB of desired encoding of URL. + * @see QTextCodec::mibEnum() + * @return The concatenation if the encoded path , '?' and the encoded query. + * + */ + QString encodedPathAndQuery( int _trailing = 0, bool _no_empty_path = false, int encoding_hint = 0) const; + + /** + * @param _txt This is considered to be encoded. This has a good reason: + * The query may contain the 0 character. + * + * The query should start with a '?'. If it doesn't '?' is prepended. + * @param encoding_hint Reserved, should be 0. + * @see QTextCodec::mibEnum() + */ + void setQuery( const QString& _txt, int encoding_hint = 0); + + /** + * Returns the query of the URL. + * The query may contain the 0 character. + * If a query is present it always starts with a '?'. + * A single '?' means an empty query. + * An empty string means no query. + * @return The encoded query, or QString::null if there is none. + */ + QString query() const; + + /** + * The reference is @em never decoded automatically. + * @return the undecoded reference, or QString::null if there is none + */ + QString ref() const { return m_strRef_encoded; } + + /** + * Sets the reference part (everything after '#'). + * @param _txt The encoded reference (or QString::null to remove it). + */ + void setRef( const QString& _txt ) { m_strRef_encoded = _txt; } + + /** + * Checks whether the URL has a reference part. + * @return true if the URL has a reference part. In a URL like + * http://www.kde.org/kdebase.tar#tar:/README it would + * return true, too. + */ + bool hasRef() const { return !m_strRef_encoded.isNull(); } + + /** + * Returns the HTML reference (the part of the URL after "#"). + * @return The HTML-style reference. + * @see #split + * @see #hasSubURL + * @see #encodedHtmlRef + */ + QString htmlRef() const; + + /** + * Returns the HTML reference (the part of the URL after "#") in + * encoded form. + * @return The HTML-style reference in its original form. + */ + QString encodedHtmlRef() const; + + /** + * Sets the HTML-style reference. + * + * @param _ref The new reference. This is considered to be @em not encoded in + * contrast to @ref setRef(). Use QString::null to remove it. + * @see htmlRef() + */ + void setHTMLRef( const QString& _ref ); + + /** + * Checks whether there is a HTML reference. + * @return true if the URL has an HTML-style reference. + * @see htmlRef() + */ + bool hasHTMLRef() const; + + /** + * Checks whether the URL is well formed. + * @return false if the URL is malformed. This function does @em not test + * whether sub URLs are well-formed, too. + */ + bool isValid() const { return !m_bIsMalformed; } + /** + * @deprecated + */ + bool isMalformed() const { return !isValid(); } + + /** + * Checks whether the file is local. + * @return true if the file is a plain local file and has no filter protocols + * attached to it. + */ + bool isLocalFile() const; + + /** + * Adds encoding information to url by adding a "charset" parameter. If there + * is already a charset parameter, it will be replaced. + * @param encoding the encoding to add or QString::null to remove the + * encoding. + */ + void setFileEncoding(const QString &encoding); + + /** + * Returns encoding information from url, the content of the "charset" + * parameter. + * @return An encoding suitable for QTextCodec::codecForName() + * or QString::null if not encoding was specified. + */ + QString fileEncoding() const; + + /** + * Checks whether the URL has any sub URLs. See @ref #split() + * for examples for sub URLs. + * @return true if the file has at least one sub URL. + * @see #split + */ + bool hasSubURL() const; + + /** + * Adds to the current path. + * Assumes that the current path is a directory. @p _txt is appended to the + * current path. The function adds '/' if needed while concatenating. + * This means it does not matter whether the current path has a trailing + * '/' or not. If there is none, it becomes appended. If @p _txt + * has a leading '/' then this one is stripped. + * + * @param _txt The text to add. It is considered to be decoded. + */ + void addPath( const QString& _txt ); + + /** + * Returns the value of a certain query item. + * + * @param _item Item whose value we want + * @param encoding_hint MIB of encoding of query. + * + * @return the value of the given query item name or QString::null if the + * specified item does not exist. + */ +/*US we do not need this functions + QString queryItem( const QString& _item ) const; + QString queryItem( const QString& _item, int encoding_hint ) const; +*/ + /** + * Options for @ref #queryItems. Currently, only one option is + * defined: + * + * @param CaseInsensitiveKeys normalize query keys to lowercase. + * + * @since 3.1 + **/ + enum QueryItemsOptions { CaseInsensitiveKeys = 1 }; + + /** + * Returns the list of query items as a map mapping keys to values. + * + * @param options any of @ref QueryItemsOptions <em>or</or>ed together. + * @param encoding_hint MIB of encoding of query. + * + * @return the map of query items or the empty map if the url has no + * query items. + * + * @since 3.1 + */ + QMap< QString, QString > queryItems( int options=0 ) const; + QMap< QString, QString > queryItems( int options, int encoding_hint ) const; + + /** + * Add an additional query item. + * To replace an existing query item, the item should first be + * removed with @ref removeQueryItem() + * + * @param _item Name of item to add + * @param _value Value of item to add + * @param encoding_hint MIB of encoding to use for _value. + * @see QTextCodec::mibEnum() + */ + void addQueryItem( const QString& _item, const QString& _value, int encoding_hint = 0 ); + + /** + * Remove an item from the query. + * + * @param _item Item to be removed + */ + void removeQueryItem( const QString& _item ); + + /** + * Sets the filename of the path. + * In comparison to @ref addPath() this function does not assume that the current + * path is a directory. This is only assumed if the current path ends with '/'. + * + * Any reference is reset. + * + * @param _txt The filename to be set. It is considered to be decoded. If the + * current path ends with '/' then @p _txt int just appended, otherwise + * all text behind the last '/' in the current path is erased and + * @p _txt is appended then. It does not matter whether @p _txt starts + * with '/' or not. + */ + void setFileName( const QString&_txt ); + + /** + * Returns the filename of the path. + * @param _ignore_trailing_slash_in_path This tells whether a trailing '/' should + * be ignored. This means that the function would return "torben" for + * <tt>file:/hallo/torben/</tt> and <tt>file:/hallo/torben</tt>. + * If the flag is set to false, then everything behind the last '/' + * is considered to be the filename. + * @return The filename of the current path. The returned string is decoded. Null + * if there is no file (and thus no path). + */ + QString fileName( bool _ignore_trailing_slash_in_path = true ) const; + + /** + * Returns the directory of the path. + * @param _strip_trailing_slash_from_result tells whether the returned result should end with '/' or not. + * If the path is empty or just "/" then this flag has no effect. + * @param _ignore_trailing_slash_in_path means that <tt>file:/hallo/torben</tt> and + * <tt>file:/hallo/torben/"</tt> would both return <tt>/hallo/</tt> + * or <tt>/hallo</tt> depending on the other flag + * @return The directory part of the current path. Everything between the last and the second last '/' + * is returned. For example <tt>file:/hallo/torben/</tt> would return "/hallo/torben/" while + * <tt>file:/hallo/torben</tt> would return "hallo/". The returned string is decoded. QString::null is returned when there is no path. + */ + QString directory( bool _strip_trailing_slash_from_result = true, + bool _ignore_trailing_slash_in_path = true ) const; + + /** + * Set the directory to @p dir, leaving the filename empty. + */ + void setDirectory(const QString &dir); + + /** + * Changes the directory by descending into the given directory. + * It is assumed the current URL represents a directory. + * If @p dir starts with a "/" the + * current URL will be "protocol://host/dir" otherwise @p _dir will + * be appended to the path. @p _dir can be ".." + * This function won't strip protocols. That means that when you are in + * file:/dir/dir2/my.tgz#tar:/ and you do cd("..") you will + * still be in file:/dir/dir2/my.tgz#tar:/ + * + * @param _dir the directory to change to + * @return true if successful + */ + bool cd( const QString& _dir ); + + /** + * Returns the URL as string, with all escape sequences intact, + * encoded in a given charset. + * This is used in particular for encoding URLs in UTF-8 before using them + * in a drag and drop operation. + * Please note that the string returned by @ref url() will include + * the password of the URL. If you want to show the URL to the + * user, use @ref prettyURL(). + * + * @param _trailing This may be ( -1, 0 +1 ). -1 strips a trailing '/' from the path, +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. + * @param encoding_hint MIB of encoding to use. + * @return The complete URL, with all escape sequences intact, encoded + * in a given charset. + * @see QTextCodec::mibEnum() + * @see prettyURL() + */ + QString url( int _trailing = 0, int encoding_hint = 0) const; + + /** + * Returns the URL as string in human-friendly format. + * Example: + * <pre> + * http://localhost:8080/test.cgi?test=hello world&name=fred + * </pre> + * @param _trailing -1 to strip a trailing '/' from the path, +1 adds + * a trailing '/' if there is none yet and 0 returns the + * path unchanged. + * @return A human readable URL, with no non-necessary encodings/escaped + * characters. Password will not be shown. + * @see url() + */ + QString prettyURL( int _trailing = 0) const; + + + /** + * Returns the URL as string, escaped for HTML. + * @return A human readable URL, with no non-necessary encodings/escaped + * characters which is html encoded for safe inclusion in html or + * rich text. Password will not be shown. + */ + QString htmlURL() const; + + /** + * Returns the URL as string, escaped for HTML. + * Example: + * <pre> + * http://localhost:8080/test.cgi?test=hello world&name=fred + * </pre> + * @return A human readable URL, with no non-necessary encodings/escaped + * characters. Password will not be shown. + */ + QString prettyURL( int _trailing, AdjustementFlags _flags) const; + // ### BIC: Merge the two above + + /** + * Test to see if the KURL is empty. + * @return true if the URL is empty + **/ + bool isEmpty() const; + + /** + * This function is useful to implement the "Up" button in a file manager for example. + * @ref cd() never strips a sub-protocol. That means that if you are in + * file:/home/x.tgz#gzip:/#tar:/ and hit the up button you expect to see + * file:/home. The algorithm tries to go up on the right-most URL. If that is not + * possible it strips the right most URL. It continues stripping URLs. + * @return a URL that is a level higher + */ + KURL upURL( ) const; + + KURL& operator=( const KURL& _u ); + KURL& operator=( const QString& _url ); + KURL& operator=( const char * _url ); + KURL& operator=( const QUrl & u ); + + bool operator==( const KURL& _u ) const; + bool operator==( const QString& _u ) const; + bool operator!=( const KURL& _u ) const { return !( *this == _u ); } + bool operator!=( const QString& _u ) const { return !( *this == _u ); } + + /** + * The same as equals(), just with a less obvious name. + * Compares this url with @p u. + * @param ignore_trailing set to true to ignore trailing '/' characters. + * @return true if both urls are the same + * @see operator==. This function should be used if you want to + * ignore trailing '/' characters. + * @deprecated + */ + bool cmp( const KURL &u, bool ignore_trailing = false ) const; + + /** + * Compares this url with @p u. + * @param ignore_trailing set to true to ignore trailing '/' characters. + * @return true if both urls are the same + * @see operator==. This function should be used if you want to + * ignore trailing '/' characters. + * @since 3.1 + */ + bool equals( const KURL &u, bool ignore_trailing = false ) const; + + /** + * Checks whether the given URL is parent of this URL. + * For instance, ftp://host/dir/ is a parent of ftp://host/dir/subdir/subsubdir/. + * @return true if this url is a parent of @p u (or the same URL as @p u) + */ + bool isParentOf( const KURL& u ) const; + + /** + * Splits nested URLs like file:/home/weis/kde.tgz#gzip:/#tar:/kdebase + * A URL like http://www.kde.org#tar:/kde/README.hml#ref1 will be split in + * http://www.kde.org and tar:/kde/README.html#ref1. + * That means in turn that "#ref1" is an HTML-style reference and not a new sub URL. + * Since HTML-style references mark + * a certain position in a document this reference is appended to every URL. + * The idea behind this is that browsers, for example, only look at the first URL while + * the rest is not of interest to them. + * + * + * @param _url The URL that has to be split. + * @return An empty list on error or the list of split URLs. + * @see #hasSubURL + */ + static List split( const QString& _url ); + + /** + * Splits nested URLs like file:/home/weis/kde.tgz#gzip:/#tar:/kdebase + * A URL like http://www.kde.org#tar:/kde/README.hml#ref1 will be split in + * http://www.kde.org and tar:/kde/README.html#ref1. + * That means in turn that "#ref1" is an HTML-style reference and not a new sub URL. + * Since HTML-style references mark + * a certain position in a document this reference is appended to every URL. + * The idea behind this is that browsers, for example, only look at the first URL while + * the rest is not of interest to them. + * + * @return An empty list on error or the list of split URLs. + * + * @param _url The URL that has to be split. + * @see #hasSubURL + */ + static List split( const KURL& _url ); + + /** + * Reverses @ref #split(). Only the first URL may have a reference. This reference + * is considered to be HTML-like and is appended at the end of the resulting + * joined URL. + * @param _list the list to join + * @return the joined URL + */ + static KURL join( const List& _list ); + + /** + * Creates a KURL object from a QString representing either an absolute path + * or a real URL. Use this method instead of + * <pre> + * QString someDir = ... + * KURL url = someDir; + * </pre> + * + * Otherwise some characters (e.g. the '#') won't be encoded properly. + * @param text the string representation of the URL to convert + * @return the new KURL + * @since 3.1 + */ + static KURL fromPathOrURL( const QString& text ); + +/** + * Convenience function. + * + * Convert unicoded string to local encoding and use %-style + * encoding for all common delimiters / non-ascii characters. + * @param str String to encode (can be QString::null). + * @param encoding_hint MIB of encoding to use. + * @see QTextCodec::mibEnum() + * @return the encoded string + **/ + static QString encode_string(const QString &str, int encoding_hint = 0); + + /** + * Convenience function. + * + * Convert unicoded string to local encoding and use %-style + * encoding for all common delimiters / non-ascii characters + * as well as the slash '/'. + * @param str String to encode + * @param encoding_hint MIB of encoding to use. + * @see QTextCodec::mibEnum() + **/ + static QString encode_string_no_slash(const QString &str, int encoding_hint = 0); + + /** + * Convenience function. + * + * Decode %-style encoding and convert from local encoding to unicode. + * + * Reverse of encode_string() + * @param str String to decode (can be QString::null). + * @param encoding_hint MIB of original encoding of @p str . + * @see QTextCodec::mibEnum() + **/ + static QString decode_string(const QString &str, int encoding_hint = 0); + + /** + * Convenience function. + * + * Returns whether '_url' is likely to be a "relative" URL instead of + * an "absolute" URL. + * @param _url URL to examine + * @return true when the URL is likely to be "relative", false otherwise. + */ + static bool isRelativeURL(const QString &_url); + +#ifdef KDE_NO_COMPAT +private: +#endif + QString filename( bool _ignore_trailing_slash_in_path = true ) const + { + return fileName(_ignore_trailing_slash_in_path); + } + +protected: + void reset(); + void parse( const QString& _url, int encoding_hint = 0); + +private: + QString m_strProtocol; + QString m_strUser; + QString m_strPass; + QString m_strHost; + QString m_strPath; + QString m_strRef_encoded; + QString m_strQuery_encoded; + bool m_bIsMalformed : 1; + int freeForUse : 7; + unsigned short int m_iPort; + QString m_strPath_encoded; + + friend QDataStream & operator<< (QDataStream & s, const KURL & a); + friend QDataStream & operator>> (QDataStream & s, KURL & a); +private: + KURLPrivate* d; +}; + +/** + * Compares URLs. They are parsed, split and compared. + * Two malformed URLs with the same string representation + * are nevertheless considered to be unequal. + * That means no malformed URL equals anything else. + */ +bool urlcmp( const QString& _url1, const QString& _url2 ); + +/** + * Compares URLs. They are parsed, split and compared. + * Two malformed URLs with the same string representation + * are nevertheless considered to be unequal. + * That means no malformed URL equals anything else. + * + * @param _ignore_trailing Described in @ref KURL::cmp + * @param _ignore_ref If true, disables comparison of HTML-style references. + */ +bool urlcmp( const QString& _url1, const QString& _url2, bool _ignore_trailing, bool _ignore_ref ); + +QDataStream & operator<< (QDataStream & s, const KURL & a); +QDataStream & operator>> (QDataStream & s, KURL & a); + +#endif diff --git a/microkde/kutils/kcmultidialog.cpp b/microkde/kutils/kcmultidialog.cpp new file mode 100644 index 0000000..4136622 --- a/dev/null +++ b/microkde/kutils/kcmultidialog.cpp @@ -0,0 +1,201 @@ +/* + Copyright (c) 2000 Matthias Elter <elter@kde.org> + Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#include <qhbox.h> +#include <qvbox.h> +#include <qcursor.h> +#include <qlayout.h> + +#include <klocale.h> +#include <kglobal.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kmessagebox.h> +//US #include <klibloader.h> +#include <krun.h> +#include <kprocess.h> + +#include "kcmultidialog.h" +//US #include "kcmultidialog.moc" +//US #include "kcmoduleloader.h" + +KCMultiDialog::KCMultiDialog(const QString& baseGroup, QWidget *parent, const char *name, bool modal) + : KDialogBase(IconList, i18n("Configure"), Default |Cancel | Apply | Ok, Ok, + parent, name, modal, true), d(0L) +{ + enableButton(Apply, false); + //connect(this, SIGNAL(aboutToShowPage(QWidget *)), this, SLOT(slotAboutToShow(QWidget *))); + _baseGroup = baseGroup; + mMainWidget = new KJanusWidget( this, "JanusWidget", KJanusWidget::Tabbed ); + setMainWidget(mMainWidget ); +#ifdef DESKTOP_VERSION + resize(640,480); +#else + resize(640,480); + setMaximumSize( KMIN(KGlobal::getDesktopWidth()-5, 640), KMIN(KGlobal::getDesktopHeight()-20, 480)); + //showMaximized(); +#endif + +} + +KCMultiDialog::~KCMultiDialog() +{ +//US moduleDict.setAutoDelete(true); +} + +void KCMultiDialog::slotDefault() +{ + + int curPageIndex = mMainWidget->activePageIndex(); + + QPtrListIterator<KCModule> it(modules); + for (; it.current(); ++it) + { + if (pageIndex((QWidget *)(*it)->parent()) == curPageIndex) + { + (*it)->defaults(); + clientChanged(true); + return; + } + } + +} + +void KCMultiDialog::slotApply() +{ +qDebug("KCMultiDialog::slotApply clicked"); + + QPtrListIterator<KCModule> it(modules); + for (; it.current(); ++it) + (*it)->save(); + clientChanged(false); + + emit applyClicked(); + +} + + +void KCMultiDialog::slotOk() +{ +qDebug("KCMultiDialog::slotOk clicked"); + + QPtrListIterator<KCModule> it(modules); + for (; it.current(); ++it) + (*it)->save(); + accept(); + + emit okClicked(); +} + +void KCMultiDialog::slotHelp() +{ +/*US + KURL url( KURL("help:/"), _docPath ); + + if (url.protocol() == "help" || url.protocol() == "man" || url.protocol() == "info") { + KProcess process; + process << "khelpcenter" + << url.url(); + process.start(KProcess::DontCare); + process.detach(); + } else { + new KRun(url); + } +*/ +} + +void KCMultiDialog::clientChanged(bool state) +{ + enableButton(Apply, state); +} + +/*US +void KCMultiDialog::addModule(const QString& path, bool withfallback) +{ + kdDebug(1208) << "KCMultiDialog::addModule " << path << endl; + + KCModuleInfo info(path, _baseGroup); + + QHBox* page = addHBoxPage(info.moduleName(), info.comment(), + KGlobal::iconLoader()->loadIcon(info.icon(), KIcon::Desktop, KIcon::SizeMedium)); + if(!page) { + KCModuleLoader::unloadModule(info); + return; + } + moduleDict.insert(page, new LoadInfo(path, withfallback)); + if (modules.isEmpty()) + slotAboutToShow(page); +} +*/ +QVBox * KCMultiDialog::getNewVBoxPage( const QString & modulename ) +{ + QVBox *page = mMainWidget->addVBoxPage(modulename , QString::null,QPixmap() ); + return page; + +} +//US special method for microkde. We dop noty want to load everything dynamically. +void KCMultiDialog::addModule(KCModule* module ) //, const QString& modulename, const QString& iconname) +{ + + modules.append(module); + connect(module, SIGNAL(changed(bool)), this, SLOT(clientChanged(bool))); + + +} + +void KCMultiDialog::slotAboutToShow(QWidget *page) +{ +/*US + LoadInfo *loadInfo = moduleDict[page]; + if (!loadInfo) + return; + + QApplication::setOverrideCursor(Qt::WaitCursor); + + moduleDict.remove(page); + + KCModuleInfo info(loadInfo->path, _baseGroup); + + KCModule *module = KCModuleLoader::loadModule(info, loadInfo->withfallback); + + if (!module) + { + QApplication::restoreOverrideCursor(); + KCModuleLoader::showLastLoaderError(this); + delete loadInfo; + return; + } + + module->reparent(page,0,QPoint(0,0),true); + connect(module, SIGNAL(changed(bool)), this, SLOT(clientChanged(bool))); + //setHelp( docpath, QString::null ); + _docPath = info.docPath(); + modules.append(module); + + //KCGlobal::repairAccels( topLevelWidget() ); + + delete loadInfo; + + QApplication::restoreOverrideCursor(); +*/ + +qDebug("KCMultiDialog::slotAboutToShow not implemented"); +} diff --git a/microkde/kutils/kcmultidialog.h b/microkde/kutils/kcmultidialog.h new file mode 100644 index 0000000..63d5d42 --- a/dev/null +++ b/microkde/kutils/kcmultidialog.h @@ -0,0 +1,147 @@ +/* + Copyright (c) 2000 Matthias Elter <elter@kde.org> + Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#ifndef KCMULTIDIALOG_H +#define KCMULTIDIALOG_H + +#include <qptrlist.h> +#include <qptrdict.h> + +#include <kdialogbase.h> +#include <kjanuswidget.h> +#include <kcmodule.h> + + +/** + * A class that offers a @ref KDialogBase containing arbitrary KControl Modules + * + * @short A method that offers a @ref KDialogBase containing arbitrary + * KControl Modules. + * + * @author Matthias Elter <elter@kde.org>, Daniel Molkentin <molkentin@kde.org> + * @since 3.2 + */ +class KCMultiDialog : public KDialogBase +{ + Q_OBJECT + +public: + /** + * Constructs a new KCMultiDialog + * + * @param parent The parent Widget + * @param name The widget name + * @param baseGroup The baseGroup, if you want to call a module out of + * kcontrol, just keep "settings" + * @param modal If you pass true here, the dialog will be modal + **/ + KCMultiDialog(const QString& baseGroup = QString::fromLatin1("settings"), + QWidget *parent=0, const char *name=0, + bool modal=false); + + /** + * Destructor + **/ + virtual ~KCMultiDialog(); + + /** + * Add a module. + * + * @param module Specify the name of the module that is to be added + * to the list of modules the dialog will show. + * + * @param withfallback Try harder to load the module. Might result + * in the module appearing outside the dialog. + **/ +//US void addModule(const QString& module, bool withfallback=true); + + +//US special method for microkde. We dop noty want to load everything dynamically. + void addModule(KCModule* module );//, const QString& modulename, const QString& iconname); + QVBox* getNewVBoxPage(const QString & modulename) ; + + + +protected slots: + /** + * This slot is called when the user presses the "Default" Button + * You can reimplement it if needed. + * + * @note Make sure you call the original implementation! + **/ + virtual void slotDefault(); + + /** + * This slot is called when the user presses the "Apply" Button + * You can reimplement it if needed + * + * @note Make sure you call the original implementation! + **/ + virtual void slotApply(); + + /** + * This slot is called when the user presses the "OK" Button + * You can reimplement it if needed + * + * @note Make sure you call the original implementation! + **/ + virtual void slotOk(); + + /** + * This slot is called when the user presses the "Help" Button + * You can reimplement it if needed + * + * @note Make sure you call the original implementation! + **/ + virtual void slotHelp(); + +private slots: + + void slotAboutToShow(QWidget *); + + void clientChanged(bool state); + +private: +/*US + struct LoadInfo { + LoadInfo(const QString &_path, bool _withfallback) + : path(_path), withfallback(_withfallback) + { } + QString path; + bool withfallback; + }; +*/ + QPtrList<KCModule> modules; +/* + QPtrDict<LoadInfo> moduleDict; + QString _docPath; +*/ + QString _baseGroup; + +//US + KJanusWidget* mMainWidget; + + // For future use + class KCMultiDialogPrivate; + KCMultiDialogPrivate *d; +}; + +#endif //KCMULTIDIALOG_H diff --git a/microkde/microkde.pro b/microkde/microkde.pro new file mode 100644 index 0000000..1e9b022 --- a/dev/null +++ b/microkde/microkde.pro @@ -0,0 +1,170 @@ +TEMPLATE = lib +CONFIG += qt warn_on +#INCLUDEPATH += $(QTDIR)/include . +#DEPENDPATH += $(QTDIR)/include +INCLUDEPATH += . ../ ../kabc ./kdecore ./kdeui ./kio/kfile +#LIBS += -lqtcompat + +TARGET = microkde +DESTDIR= ../bin +DEFINES += DESKTOP_VERSION KDE_QT_ONLY +unix : { +OBJECTS_DIR = obj/unix +MOC_DIR = moc/unix +} +win32: { +DEFINES += _WIN32_ +OBJECTS_DIR = obj/win +MOC_DIR = moc/win +} +include( ../variables.pri ) + + + +HEADERS = \ +qlayoutengine_p.h \ +KDGanttMinimizeSplitter.h \ + kapplication.h \ + kaudioplayer.h \ + kcalendarsystem.h \ + kcalendarsystemgregorian.h \ + kcolorbutton.h \ + kcolordialog.h \ + kcombobox.h \ + kconfig.h \ + kdatetbl.h \ + kdebug.h \ + kdialog.h \ + kdialogbase.h \ + kdirwatch.h \ + keditlistbox.h \ + kemailsettings.h \ + kfiledialog.h \ + kfontdialog.h \ + kglobal.h \ + kglobalsettings.h \ + kiconloader.h \ + klineedit.h \ + klineeditdlg.h \ + kmessagebox.h \ + knotifyclient.h \ + kprinter.h \ + kprocess.h \ + krestrictedline.h \ + krun.h \ + ksimpleconfig.h \ + kstaticdeleter.h \ + ksystemtray.h \ + ktempfile.h \ + ktextedit.h \ + kunload.h \ + kurl.h \ + kdeui/kguiitem.h \ + kdeui/kcmodule.h \ + kdeui/kbuttonbox.h \ + kdeui/klistbox.h \ + kdeui/klistview.h \ + kdeui/kjanuswidget.h \ + kdeui/kseparator.h \ + kdeui/knuminput.h \ + kdeui/knumvalidator.h \ + kdeui/ksqueezedtextlabel.h \ + kio/job.h \ + kio/kfile/kurlrequester.h \ + kresources/resource.h \ + kresources/factory.h \ + kresources/managerimpl.h \ + kresources/manager.h \ + kresources/selectdialog.h \ + kresources/configpage.h \ + kresources/configwidget.h \ + kresources/configdialog.h \ + kresources/kcmkresources.h \ + kdecore/kmdcodec.h \ + kdecore/kconfigbase.h \ + kdecore/klocale.h \ + kdecore/kcatalogue.h \ + kdecore/ksharedptr.h \ + kdecore/kshell.h \ + kdecore/kstandarddirs.h \ + kdecore/kstringhandler.h \ + kdecore/kshortcut.h \ + kutils/kcmultidialog.h \ + kdeui/kxmlguiclient.h \ + kdeui/kstdaction.h \ + kdeui/kmainwindow.h \ + kdeui/ktoolbar.h \ + kdeui/ktoolbarbutton.h \ + kdeui/ktoolbarhandler.h \ + kdeui/kaction.h \ + kdeui/kactionclasses.h \ + kdeui/kactioncollection.h + + +# kdecore/klibloader.h \ + + +SOURCES = \ +KDGanttMinimizeSplitter.cpp \ + kapplication.cpp \ + kcalendarsystem.cpp \ + kcalendarsystemgregorian.cpp \ + kcolorbutton.cpp \ + kcolordialog.cpp \ + kconfig.cpp \ + kdatetbl.cpp \ + kdialog.cpp \ + kdialogbase.cpp \ + keditlistbox.cpp \ + kemailsettings.cpp \ + kfontdialog.cpp \ + kfiledialog.cpp \ + kglobal.cpp \ + kglobalsettings.cpp \ + kiconloader.cpp \ + kmessagebox.cpp \ + ktextedit.cpp \ + kprocess.cpp \ + krun.cpp \ + ksystemtray.cpp \ + ktempfile.cpp \ + kurl.cpp \ + kdecore/kcatalogue.cpp \ + kdecore/klocale.cpp \ + kdecore/kmdcodec.cpp \ + kdecore/kshell.cpp \ + kdecore/kstandarddirs.cpp \ + kdecore/kstringhandler.cpp \ + kdeui/kbuttonbox.cpp \ + kdeui/kcmodule.cpp \ + kdeui/kguiitem.cpp \ + kdeui/kjanuswidget.cpp \ + kdeui/klistbox.cpp \ + kdeui/klistview.cpp \ + kdeui/knuminput.cpp \ + kdeui/knumvalidator.cpp \ + kdeui/kseparator.cpp \ + kdeui/ksqueezedtextlabel.cpp \ + kio/kfile/kurlrequester.cpp \ + kresources/configpage.cpp \ + kresources/configdialog.cpp \ + kresources/configwidget.cpp \ + kresources/factory.cpp \ + kresources/kcmkresources.cpp \ + kresources/managerimpl.cpp \ + kresources/resource.cpp \ + kresources/selectdialog.cpp \ + kutils/kcmultidialog.cpp \ + kdeui/kaction.cpp \ + kdeui/kactionclasses.cpp \ + kdeui/kactioncollection.cpp \ + kdeui/kmainwindow.cpp \ + kdeui/ktoolbar.cpp \ + kdeui/ktoolbarbutton.cpp \ + kdeui/ktoolbarhandler.cpp \ + kdeui/kstdaction.cpp \ + kdeui/kxmlguiclient.cpp + + + +# kdecore/klibloader.cpp \
\ No newline at end of file diff --git a/microkde/microkde.pro.back b/microkde/microkde.pro.back new file mode 100644 index 0000000..d2889ac --- a/dev/null +++ b/microkde/microkde.pro.back @@ -0,0 +1,80 @@ +TEMPLATE = lib +CONFIG = qt warn_on release +INCLUDEPATH += $(QPEDIR)/include . ../qtcompat +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe -lqtcompat +TARGET = microkde +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc +DESTDIR=$(QPEDIR)/lib + +INTERFACES = \ + +HEADERS = \ + kapplication.h \ + kaudioplayer.h \ + kcalendarsystem.h \ + kcalendarsystemgregorian.h \ + kcolorbutton.h \ + kcolordialog.h \ + kcombobox.h \ + kconfig.h \ + kdatepicker.h \ + kdatetbl.h \ + kdebug.h \ + kdialog.h \ + kdialogbase.h \ + kdirwatch.h \ + keditlistbox.h \ + kemailsettings.h \ + kfiledialog.h \ + kfontdialog.h \ + kglobal.h \ + kglobalsettings.h \ + kiconloader.h \ + kio/job.h \ + klineedit.h \ + klineeditdlg.h \ + klistview.h \ + klocale.h \ + kmessagebox.h \ + knotifyclient.h \ + knumvalidator.h \ + kprinter.h \ + kprocess.h \ + krestrictedline.h \ + krun.h \ + kseparator.h \ + ksimpleconfig.h \ + kstandarddirs.h \ + kstaticdeleter.h \ + ksystemtray.h \ + ktempfile.h \ + ktextedit.h \ + kunload.h \ + kurlrequester.h \ + +SOURCES = \ + kapplication.cpp \ + kcalendarsystem.cpp \ + kcalendarsystemgregorian.cpp \ + kcolordialog.cpp \ + kconfig.cpp \ + kdatepicker.cpp \ + kdatetbl.cpp \ + kdialogbase.cpp \ + keditlistbox.cpp \ + kemailsettings.cpp \ + kfontdialog.cpp \ + kglobal.cpp \ + kglobalsettings.cpp \ + kiconloader.cpp \ + klocale.cpp \ + kmessagebox.cpp \ + knumvalidator.cpp \ + kprocess.cpp \ + krun.cpp \ + kstandarddirs.cpp \ + ktempfile.cpp \ + kurlrequester.cpp \ + diff --git a/microkde/microkdeE.pro b/microkde/microkdeE.pro new file mode 100644 index 0000000..8d04123 --- a/dev/null +++ b/microkde/microkdeE.pro @@ -0,0 +1,166 @@ +TEMPLATE = lib +CONFIG += qt warn_on +INCLUDEPATH += . ../qtcompat ../kabc ./kdecore ./kdeui ./kio/kfile $(QPEDIR)/include + +DEPENDPATH += $(QPEDIR)/include +LIBS += -lmicroqtcompat -L$(QPEDIR)/lib + +DEFINES += KDE_QT_ONLY + +TARGET = microkde +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR=$(QPEDIR)/lib + + +INTERFACES = \ + +HEADERS = \ +qlayoutengine_p.h \ +KDGanttMinimizeSplitter.h \ + kapplication.h \ + kaudioplayer.h \ + kcalendarsystem.h \ + kcalendarsystemgregorian.h \ + kcolorbutton.h \ + kcolordialog.h \ + kcombobox.h \ + kconfig.h \ + kdatetbl.h \ + kdebug.h \ + kdialog.h \ + kdialogbase.h \ + kdirwatch.h \ + keditlistbox.h \ + kemailsettings.h \ + kfiledialog.h \ + kfontdialog.h \ + kglobal.h \ + kglobalsettings.h \ + kiconloader.h \ + klineedit.h \ + klineeditdlg.h \ + kmessagebox.h \ + knotifyclient.h \ + kprinter.h \ + kprocess.h \ + krestrictedline.h \ + krun.h \ + ksimpleconfig.h \ + kstaticdeleter.h \ + ksystemtray.h \ + ktempfile.h \ + ktextedit.h \ + kunload.h \ + kurl.h \ + ofileselector_p.h \ + ofontselector.h \ + kdeui/kguiitem.h \ + kdeui/kaction.h \ + kdeui/kactionclasses.h \ + kdeui/kactioncollection.h \ + kdeui/kcmodule.h \ + kdeui/kstdaction.h \ + kdeui/kbuttonbox.h \ + kdeui/klistbox.h \ + kdeui/klistview.h \ + kdeui/kjanuswidget.h \ + kdeui/kseparator.h \ + kdeui/kmainwindow.h \ + kdeui/knuminput.h \ + kdeui/knumvalidator.h \ + kdeui/ksqueezedtextlabel.h \ + kdeui/ktoolbar.h \ + kdeui/ktoolbarbutton.h \ + kdeui/ktoolbarhandler.h \ + kdeui/kxmlguiclient.h \ + kio/job.h \ + kio/kfile/kurlrequester.h \ + kresources/resource.h \ + kresources/factory.h \ + kresources/managerimpl.h \ + kresources/manager.h \ + kresources/selectdialog.h \ + kresources/configpage.h \ + kresources/configwidget.h \ + kresources/configdialog.h \ + kresources/kcmkresources.h \ + kdecore/kmdcodec.h \ + kdecore/kconfigbase.h \ + kdecore/klocale.h \ + kdecore/klibloader.h \ + kdecore/kcatalogue.h \ + kdecore/ksharedptr.h \ + kdecore/kshell.h \ + kdecore/kstandarddirs.h \ + kdecore/kstringhandler.h \ + kdecore/kshortcut.h \ + kutils/kcmultidialog.h + + + + +SOURCES = \ +KDGanttMinimizeSplitter.cpp \ + kapplication.cpp \ + kcalendarsystem.cpp \ + kcalendarsystemgregorian.cpp \ + kcolorbutton.cpp \ + kcolordialog.cpp \ + kconfig.cpp \ + kdatetbl.cpp \ + kdialog.cpp \ + kdialogbase.cpp \ + keditlistbox.cpp \ + kemailsettings.cpp \ + kfontdialog.cpp \ + kfiledialog.cpp \ + kglobal.cpp \ + kglobalsettings.cpp \ + kiconloader.cpp \ + kmessagebox.cpp \ + kprocess.cpp \ + krun.cpp \ + ksystemtray.cpp \ + ktempfile.cpp \ + kurl.cpp \ + ktextedit.cpp \ + ofileselector_p.cpp \ + ofontselector.cpp \ + kdecore/kcatalogue.cpp \ + kdecore/klibloader.cpp \ + kdecore/klocale.cpp \ + kdecore/kmdcodec.cpp \ + kdecore/kshell.cpp \ + kdecore/kstandarddirs.cpp \ + kdecore/kstringhandler.cpp \ + kdeui/kaction.cpp \ + kdeui/kactionclasses.cpp \ + kdeui/kactioncollection.cpp \ + kdeui/kbuttonbox.cpp \ + kdeui/kcmodule.cpp \ + kdeui/kguiitem.cpp \ + kdeui/kjanuswidget.cpp \ + kdeui/klistbox.cpp \ + kdeui/klistview.cpp \ + kdeui/kmainwindow.cpp \ + kdeui/knuminput.cpp \ + kdeui/knumvalidator.cpp \ + kdeui/kseparator.cpp \ + kdeui/kstdaction.cpp \ + kdeui/ksqueezedtextlabel.cpp \ + kdeui/ktoolbar.cpp \ + kdeui/ktoolbarbutton.cpp \ + kdeui/ktoolbarhandler.cpp \ + kdeui/kxmlguiclient.cpp \ + kio/kfile/kurlrequester.cpp \ + kresources/configpage.cpp \ + kresources/configdialog.cpp \ + kresources/configwidget.cpp \ + kresources/factory.cpp \ + kresources/kcmkresources.cpp \ + kresources/managerimpl.cpp \ + kresources/resource.cpp \ + kresources/selectdialog.cpp \ + kutils/kcmultidialog.cpp + diff --git a/microkde/ofileselector_p.cpp b/microkde/ofileselector_p.cpp new file mode 100644 index 0000000..cf6074d --- a/dev/null +++ b/microkde/ofileselector_p.cpp @@ -0,0 +1,863 @@ +#include <qcombobox.h> +#include <qdir.h> +#include <qhbox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qlistview.h> +#include <qpopupmenu.h> +#include <qwidgetstack.h> +#include <qregexp.h> +#include <qobjectlist.h> + +/* hacky but we need to get FileSelector::filter */ +#define private public +#include <qpe/fileselector.h> +#undef private + +#include <qpe/qpeapplication.h> +#include <qpe/mimetype.h> +#include <qpe/resource.h> +#include <qpe/storage.h> + +#include "ofileselector_p.h" +//US#include "ofileselector.h" + +#include "klocale.h" + +OFileViewInterface::OFileViewInterface( OFileSelector* selector ) + : m_selector( selector ) { +} +OFileViewInterface::~OFileViewInterface() { +} +QString OFileViewInterface::name()const{ + return m_name; +} +void OFileViewInterface::setName( const QString& name ) { + m_name = name; +} +OFileSelector* OFileViewInterface::selector()const { + return m_selector; +} + +DocLnk OFileViewInterface::selectedDocument()const { + return DocLnk( selectedName() ); +} + +bool OFileViewInterface::showNew()const { + return selector()->showNew(); +} +bool OFileViewInterface::showClose()const { + return selector()->showClose(); +} +MimeTypes OFileViewInterface::mimeTypes()const { + return selector()->mimeTypes(); +} +QStringList OFileViewInterface::currentMimeType()const { + return selector()->currentMimeType(); +} +void OFileViewInterface::activate( const QString& ) { + // not implemented here +} +void OFileViewInterface::ok() { + emit selector()->ok(); +} +void OFileViewInterface::cancel() { + emit selector()->cancel(); +} +void OFileViewInterface::closeMe() { + emit selector()->closeMe(); +} +void OFileViewInterface::fileSelected( const QString& str) { + emit selector()->fileSelected( str); +} +void OFileViewInterface::fileSelected( const DocLnk& lnk) { + emit selector()->fileSelected( lnk ); +} +void OFileViewInterface::setCurrentFileName( const QString& str ) { + selector()->m_lneEdit->setText( str ); +} +QString OFileViewInterface::currentFileName()const{ + return selector()->m_lneEdit->text(); +} +QString OFileViewInterface::startDirectory()const{ + return selector()->m_startDir; +} + + +ODocumentFileView::ODocumentFileView( OFileSelector* selector ) + : OFileViewInterface( selector ) { + m_selector = 0; + setName( i18n("Documents") ); +} +ODocumentFileView::~ODocumentFileView() { + +} +QString ODocumentFileView::selectedName()const { + if (!m_selector) + return QString::null; + + return m_selector->selected()->file(); +} +QString ODocumentFileView::selectedPath()const { + return QPEApplication::documentDir(); +} +QString ODocumentFileView::directory()const { + return selectedPath(); +} +void ODocumentFileView::reread() { + if (!m_selector) + return; + + m_selector->setNewVisible( showNew() ); + m_selector->setCloseVisible( showClose() ); + m_selector->filter = currentMimeType().join(";"); + m_selector->reread(); +} +int ODocumentFileView::fileCount()const { + if (!m_selector) + return -1; + + return m_selector->fileCount(); +} + +DocLnk ODocumentFileView::selectedDocument()const { + if (!m_selector) + return DocLnk(); + DocLnk lnk = *m_selector->selected(); + return lnk; +} + +QWidget* ODocumentFileView::widget( QWidget* parent ) { + if (!m_selector ) { + m_selector = new FileSelector(currentMimeType().join(";"), parent, "fileselector", showNew(), showClose() ); + QObject::connect(m_selector, SIGNAL(fileSelected( const DocLnk& ) ), + selector(), SLOT(slotDocLnkBridge(const DocLnk&) ) ); + QObject::connect(m_selector, SIGNAL(closeMe() ), + selector(), SIGNAL(closeMe() ) ); + QObject::connect(m_selector, SIGNAL(newSelected(const DocLnk& ) ), + selector(), SIGNAL(newSelected(const DocLnk& ) ) ); + } + + return m_selector; +} + +/* + * This is the file system view used + * we use a QListView + QListViewItems for it + */ + +OFileSelectorItem::OFileSelectorItem( QListView* view, const QPixmap& pixmap, + const QString& path, const QString& date, + const QString& size, const QString& dir, + bool isLocked, bool isDir ) + : QListViewItem( view ) +{ + setPixmap(0, pixmap ); + setText(1, path ); + setText(2, size ); + setText(3, date ); + m_isDir = isDir; + m_dir = dir; + m_locked = isLocked; +} +OFileSelectorItem::~OFileSelectorItem() { + +} +bool OFileSelectorItem::isLocked()const { + return m_locked; +} +QString OFileSelectorItem::directory()const { + return m_dir; +} +bool OFileSelectorItem::isDir()const { + return m_isDir; +} +QString OFileSelectorItem::path()const { + return text( 1 ); +} +QString OFileSelectorItem::key( int id, bool )const { + QString ke; + if( id == 0 || id == 1 ){ // name + if( m_isDir ){ + ke.append("0" ); + ke.append( text(1) ); + }else{ + ke.append("1" ); + ke.append( text(1) ); + } + return ke; + }else + return text( id ); + +} + +OFileViewFileListView::OFileViewFileListView( QWidget* parent, const QString& startDir, + OFileSelector* sel) + : QWidget( parent ), m_sel( sel ) { + m_all = false; + QVBoxLayout* lay = new QVBoxLayout( this ); + m_currentDir = startDir; + + /* + * now we add a special bar + * One Button For Up + * Home + * Doc + * And a dropdown menu with FileSystems + * FUTURE: one to change dir with lineedit + * Bookmarks + * Create Dir + */ + QHBox* box = new QHBox(this ); + box->setBackgroundMode( PaletteButton ); + box->setSpacing( 0 ); + + QToolButton *btn = new QToolButton( box ); + btn->setIconSet( Resource::loadPixmap("up") ); + connect(btn, SIGNAL(clicked() ), + this, SLOT( cdUP() ) ); + + btn = new QToolButton( box ); + btn->setIconSet( Resource::loadPixmap("home") ); + connect(btn, SIGNAL(clicked() ), + this, SLOT( cdHome() ) ); + + btn = new QToolButton( box ); + btn->setIconSet( Resource::loadPixmap("DocsIcon") ); + connect(btn, SIGNAL(clicked() ), + this, SLOT(cdDoc() ) ); + + m_btnNew = new QToolButton( box ); + m_btnNew->setIconSet( Resource::loadPixmap("new") ); + connect(m_btnNew, SIGNAL(clicked() ), + this, SLOT(slotNew() ) ); + + + m_btnClose = new QToolButton( box ); + m_btnClose->setIconSet( Resource::loadPixmap("close") ); + connect(m_btnClose, SIGNAL(clicked() ), + selector(), SIGNAL(closeMe() ) ); + + btn = new QToolButton( box ); + btn->setIconSet( Resource::loadPixmap("cardmon/pcmcia") ); + + /* let's fill device parts */ + QPopupMenu* pop = new QPopupMenu(this); + connect(pop, SIGNAL( activated(int) ), + this, SLOT(slotFSActivated(int) ) ); + + StorageInfo storage; + const QList<FileSystem> &fs = storage.fileSystems(); + QListIterator<FileSystem> it(fs); + for ( ; it.current(); ++it ) { + const QString disk = (*it)->name(); + const QString path = (*it)->path(); + m_dev.insert( disk, path ); + pop->insertItem( disk ); + } + m_fsPop = pop; + + + btn->setPopup( pop ); + btn->setPopupDelay ( 0 ); + lay->addWidget( box ); + + m_view = new QListView( this ); + + m_view->installEventFilter(this); + + QPEApplication::setStylusOperation( m_view->viewport(), + QPEApplication::RightOnHold); + m_view->addColumn(" " ); + m_view->addColumn(i18n("Name"), 135 ); + m_view->addColumn(i18n("Size"), -1 ); + m_view->addColumn(i18n("Date"), 60 ); + m_view->addColumn(i18n("Mime Type"), -1 ); + + + m_view->setSorting( 1 ); + m_view->setAllColumnsShowFocus( TRUE ); + + lay->addWidget( m_view, 1000 ); + connectSlots(); +} +OFileViewFileListView::~OFileViewFileListView() { +} +void OFileViewFileListView::slotNew() { + DocLnk lnk; + emit selector()->newSelected( lnk ); +} +OFileSelectorItem* OFileViewFileListView::currentItem()const{ + QListViewItem* item = m_view->currentItem(); + if (!item ) + return 0l; + + return static_cast<OFileSelectorItem*>(item); +} +void OFileViewFileListView::reread( bool all ) { + m_view->clear(); + + if (selector()->showClose() ) + m_btnClose->show(); + else + m_btnClose->hide(); + + if (selector()->showNew() ) + m_btnNew->show(); + else + m_btnNew->hide(); + + m_mimes = selector()->currentMimeType(); + m_all = all; + + QDir dir( m_currentDir ); + if (!dir.exists() ) + return; + topLevelWidget()->setCaption( dir.path() ); + dir.setSorting( QDir::Name | QDir::DirsFirst | QDir::Reversed ); + int filter; + if (m_all ) + filter = QDir::Files | QDir::Dirs | QDir::Hidden | QDir::All; + else + filter = QDir::Files | QDir::Dirs | QDir::All; + dir.setFilter( filter ); + + // now go through all files + const QFileInfoList *list = dir.entryInfoList(); + if (!list) { + cdUP(); + return; + } + QFileInfoListIterator it( *list ); + QFileInfo *fi; + while( (fi=it.current() ) ){ + if( fi->fileName() == QString::fromLatin1("..") || fi->fileName() == QString::fromLatin1(".") ){ + ++it; + continue; + } + + /* + * It is a symlink we try to resolve it now but don't let us attack by DOS + * + */ + if( fi->isSymLink() ){ + QString file = fi->dirPath( true ) + "/" + fi->readLink(); + for( int i = 0; i<=4; i++) { // 5 tries to prevent dos + QFileInfo info( file ); + if( !info.exists() ){ + addSymlink( fi, TRUE ); + break; + }else if( info.isDir() ){ + addDir( fi, TRUE ); + break; + }else if( info.isFile() ){ + addFile( fi, TRUE ); + break; + }else if( info.isSymLink() ){ + file = info.dirPath(true ) + "/" + info.readLink() ; + break; + }else if( i == 4){ // couldn't resolve symlink add it as symlink + addSymlink( fi ); + } + } // off for loop for symlink resolving + }else if( fi->isDir() ) + addDir( fi ); + else if( fi->isFile() ) + addFile( fi ); + + ++it; + } // of while loop + m_view->sort(); + +} +int OFileViewFileListView::fileCount()const{ + return m_view->childCount(); +} +QString OFileViewFileListView::currentDir()const{ + return m_currentDir; +} +OFileSelector* OFileViewFileListView::selector() { + return m_sel; +} + +bool OFileViewFileListView::eventFilter (QObject *o, QEvent *e) { + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent *k = (QKeyEvent *)e; + if ( (k->key()==Key_Enter) || (k->key()==Key_Return)) { + slotClicked( Qt::LeftButton,m_view->currentItem(),QPoint(0,0),0); + return true; + } + } + return false; +} + + +void OFileViewFileListView::connectSlots() { + connect(m_view, SIGNAL(clicked(QListViewItem*) ), + this, SLOT(slotCurrentChanged(QListViewItem*) ) ); + connect(m_view, SIGNAL(mouseButtonClicked(int, QListViewItem*, const QPoint&, int ) ), + this, SLOT(slotClicked(int, QListViewItem*, const QPoint&, int ) ) ); +} +void OFileViewFileListView::slotCurrentChanged( QListViewItem* item) { + if (!item) + return; +#if 0 + + OFileSelectorItem *sel = static_cast<OFileSelectorItem*>(item); + + if (!sel->isDir() ) { + selector()->m_lneEdit->setText( sel->text(1) ); + // if in fileselector mode we will emit selected + if ( selector()->mode() == OFileSelector::FileSelector ) { + qWarning("slot Current Changed"); + QStringList str = QStringList::split("->", sel->text(1) ); + QString path = sel->directory() + "/" + str[0].stripWhiteSpace(); + emit selector()->fileSelected( path ); + DocLnk lnk( path ); + emit selector()->fileSelected( lnk ); + } + } +#endif +} +void OFileViewFileListView::slotClicked(int button , QListViewItem* item, const QPoint&, int ) { + if (!item || ( button != Qt::LeftButton) ) + return; + + OFileSelectorItem *sel = static_cast<OFileSelectorItem*>(item); + if (!sel->isLocked() ) { + QStringList str = QStringList::split("->", sel->text(1) ); + if (sel->isDir() ) { + m_currentDir = sel->directory() + "/" + str[0].stripWhiteSpace(); + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); + }else { // file + qWarning("slot Clicked"); + selector()->m_lneEdit->setText( str[0].stripWhiteSpace() ); + QString path = sel->directory() + "/" + str[0].stripWhiteSpace(); + emit selector()->fileSelected( path ); + DocLnk lnk( path ); + emit selector()->fileSelected( lnk ); + } + } // not locked +} +void OFileViewFileListView::addFile( QFileInfo* info, bool symlink ) { + MimeType type( info->absFilePath() ); + if (!compliesMime( type.id() ) ) + return; + + QPixmap pix = type.pixmap(); + QString dir, name; bool locked; + if ( pix.isNull() ) { + QWMatrix matrix; + QPixmap pixer(Resource::loadPixmap("UnknownDocument") ); + matrix.scale( .4, .4 ); + pix = pixer.xForm( matrix ); + } + dir = info->dirPath( true ); + locked = false; + if ( symlink ) + name = info->fileName() + " -> " + info->dirPath() + "/" + info->readLink(); + else{ + name = info->fileName(); + if ( ( (selector()->mode() == OFileSelector::Open)&& !info->isReadable() ) || + ( (selector()->mode() == OFileSelector::Save)&& !info->isWritable() ) ) { + locked = true; pix = Resource::loadPixmap("locked"); + } + } + (void)new OFileSelectorItem( m_view, pix, name, + info->lastModified().toString(), QString::number( info->size() ), + dir, locked ); +} +void OFileViewFileListView::addDir( QFileInfo* info, bool symlink ) { + bool locked = false; QString name; QPixmap pix; + + if ( ( ( selector()->mode() == OFileSelector::Open ) && !info->isReadable() ) || + ( ( selector()->mode() == OFileSelector::Save ) && !info->isWritable() ) ) { + locked = true; + if ( symlink ) + pix = Resource::loadPixmap( "symlink" ); + else + pix = Resource::loadPixmap( "lockedfolder" ); + }else + pix = symlink ? Resource::loadPixmap( "symlink") : Resource::loadPixmap("folder"); + + name = symlink ? info->fileName() + " -> " + info->dirPath(true) + "/" + info->readLink() : + info->fileName(); + + (void)new OFileSelectorItem( m_view, pix, name, + info->lastModified().toString(), + QString::number( info->size() ), + info->dirPath( true ), locked, true ); + + +} +void OFileViewFileListView::addSymlink( QFileInfo* , bool ) { + +} +void OFileViewFileListView::cdUP() { + QDir dir( m_currentDir ); + dir.cdUp(); + + if (!dir.exists() ) + m_currentDir = "/"; + else + m_currentDir = dir.absPath(); + + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); +} +void OFileViewFileListView::cdHome() { + m_currentDir = QDir::homeDirPath(); + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); +} +void OFileViewFileListView::cdDoc() { + m_currentDir = QPEApplication::documentDir(); + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); +} +void OFileViewFileListView::changeDir( const QString& dir ) { + m_currentDir = dir; + emit selector()->dirSelected( m_currentDir ); + reread( m_all ); +} +void OFileViewFileListView::slotFSActivated( int id ) { + changeDir ( m_dev[m_fsPop->text(id)] ); +} + +/* check if the mimetype in mime + * complies with the one which is current + */ +/* + * We've the mimetype of the file + * We need to get the stringlist of the current mimetype + * + * mime = image@slashjpeg + * QStringList = 'image@slash*' + * or QStringList = image/jpeg;image/png;application/x-ogg + * or QStringList = application/x-ogg;image@slash*; + * with all these mime filters it should get acceptes + * to do so we need to look if mime is contained inside + * the stringlist + * if it's contained return true + * if not ( I'm no RegExp expert at all ) we'll look if a '@slash*' + * is contained in the mimefilter and then we will + * look if both are equal until the '/' + */ +bool OFileViewFileListView::compliesMime( const QString& str) { + if (str.isEmpty() || m_mimes.isEmpty() || str.stripWhiteSpace().isEmpty() ) + return true; + + for (QStringList::Iterator it = m_mimes.begin(); it != m_mimes.end(); ++it ) { + QRegExp reg( (*it) ); + reg.setWildcard( true ); + if ( str.find( reg ) != -1 ) + return true; + + } + return false; +} +/* + * The listView giving access to the file system! + */ +class OFileViewFileSystem : public OFileViewInterface { +public: + OFileViewFileSystem( OFileSelector* ); + ~OFileViewFileSystem(); + + QString selectedName() const; + QString selectedPath() const; + + QString directory()const; + void reread(); + int fileCount()const; + + QWidget* widget( QWidget* parent ); + void activate( const QString& ); +private: + OFileViewFileListView* m_view; + bool m_all : 1; +}; +OFileViewFileSystem::OFileViewFileSystem( OFileSelector* sel) + : OFileViewInterface( sel ) { + m_view = 0; + m_all = false; +} +OFileViewFileSystem::~OFileViewFileSystem() { +} +QString OFileViewFileSystem::selectedName()const{ + if (!m_view ) + return QString::null; + + QString cFN=currentFileName(); + if (cFN.startsWith("/")) return cFN; + return m_view->currentDir() + "/" + cFN; +} +QString OFileViewFileSystem::selectedPath()const{ + return QString::null; +} +QString OFileViewFileSystem::directory()const{ + if (!m_view) + return QString::null; + + OFileSelectorItem* item = m_view->currentItem(); + if (!item ) + return QString::null; + + return QDir(item->directory() ).absPath(); +} +void OFileViewFileSystem::reread() { + if (!m_view) + return; + + m_view->reread( m_all ); +} +int OFileViewFileSystem::fileCount()const{ + if (!m_view ) + return -1; + return m_view->fileCount(); +} +QWidget* OFileViewFileSystem::widget( QWidget* parent ) { + if (!m_view ) { + m_view = new OFileViewFileListView( parent, startDirectory(), selector() ); + } + return m_view; +} +void OFileViewFileSystem::activate( const QString& str) { + m_all = (str !=i18n("Files") ); + + +} + +/* Selector */ +OFileSelector::OFileSelector( QWidget* parent, int mode, int sel, + const QString& dirName, const QString& fileName, + const MimeTypes& mimetypes, + bool showNew, bool showClose) + : QWidget( parent, "OFileSelector" ) +{ + m_current = 0; + m_shNew = showNew; + m_shClose = showClose; + m_mimeType = mimetypes; + m_startDir = dirName; + m_mode = mode; + m_selector = sel; + + initUI(); + m_lneEdit->setText( fileName ); + initMime(); + initViews(); + + QString str; + switch ( m_selector ) { + default: + case Normal: + str = i18n("Documents"); + m_cmbView->setCurrentItem( 0 ); + break; + case Extended: + str = i18n("Files"); + m_cmbView->setCurrentItem( 1 ); + break; + case ExtendedAll: + str = i18n("All Files"); + m_cmbView->setCurrentItem( 2 ); + break; + } + slotViewChange( str ); + +} +OFileSelector::OFileSelector( const QString& mimeFilter, QWidget* parent, const char* name, + bool showNew, bool showClose ) + : QWidget( parent, name ) +{ + m_current = 0; + m_shNew = showNew; + m_shClose = showClose; + m_startDir = QPEApplication::documentDir(); + + if (!mimeFilter.isEmpty() ) + m_mimeType.insert(mimeFilter, QStringList::split(";", mimeFilter ) ); + + m_mode = OFileSelector::FileSelector; + m_selector = OFileSelector::Normal; + + initUI(); + initMime(); + initViews(); + m_cmbView->setCurrentItem( 0 ); + slotViewChange( i18n("Documents") ); +} +/* + * INIT UI will set up the basic GUI + * Layout: Simple VBoxLayout + * On top a WidgetStack containing the Views... + * - List View + * - Document View + * Below we will have a Label + LineEdit + * Below we will have two ComoBoxes one for choosing the view one for + * choosing the mimetype + */ +void OFileSelector::initUI() { + QVBoxLayout* lay = new QVBoxLayout( this ); + + m_stack = new QWidgetStack( this ); + lay->addWidget( m_stack, 1000 ); + + m_nameBox = new QHBox( this ); + (void)new QLabel( i18n("Name:"), m_nameBox ); + m_lneEdit = new QLineEdit( m_nameBox ); + m_lneEdit ->installEventFilter(this); + lay->addWidget( m_nameBox ); + + m_cmbBox = new QHBox( this ); + m_cmbView = new QComboBox( m_cmbBox ); + m_cmbMime = new QComboBox( m_cmbBox ); + lay->addWidget( m_cmbBox ); +} + +/* + * This will make sure that the return key in the name edit causes dialogs to close + */ + +bool OFileSelector::eventFilter (QObject *o, QEvent *e) { + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent *k = (QKeyEvent *)e; + if ( (k->key()==Key_Enter) || (k->key()==Key_Return)) { + emit ok(); + return true; + } + } + return false; +} + +/* + * This will insert the MimeTypes into the Combo Box + * And also connect the changed signal + * + * AutoMimeTyping is disabled for now. It used to reparse a dir and then set available mimetypes + */ +void OFileSelector::initMime() { + MimeTypes::Iterator it; + for ( it = m_mimeType.begin(); it != m_mimeType.end(); ++it ) { + m_cmbMime->insertItem( it.key() ); + } + m_cmbMime->setCurrentItem( 0 ); + + connect( m_cmbMime, SIGNAL(activated(int) ), + this, SLOT(slotMimeTypeChanged() ) ); + +} +void OFileSelector::initViews() { + m_cmbView->insertItem( i18n("Documents") ); + m_cmbView->insertItem( i18n("Files") ); + m_cmbView->insertItem( i18n("All Files") ); + connect(m_cmbView, SIGNAL(activated( const QString& ) ), + this, SLOT(slotViewChange( const QString& ) ) ); + + + m_views.insert( i18n("Documents"), new ODocumentFileView(this) ); + + /* see above why add both */ + OFileViewInterface* in = new OFileViewFileSystem( this ); + m_views.insert( i18n("Files"), in ); + m_views.insert( i18n("All Files"), in ); +} +OFileSelector::~OFileSelector() { + +} + +const DocLnk* OFileSelector::selected() { + DocLnk* lnk = ¤tView()->selectedDocument() ; + return lnk; +} + +QString OFileSelector::selectedName()const{ + return currentView()->selectedName(); +} +QString OFileSelector::selectedPath()const { + return currentView()->selectedPath(); +} +QString OFileSelector::directory()const { + return currentView()->directory(); +} + +DocLnk OFileSelector::selectedDocument()const { + return currentView()->selectedDocument(); +} + +int OFileSelector::fileCount()const { + return currentView()->fileCount(); +} +void OFileSelector::reread() { + return currentView()->reread(); +} +OFileViewInterface* OFileSelector::currentView()const{ + return m_current; +} +bool OFileSelector::showNew()const { + return m_shNew; +} +bool OFileSelector::showClose()const { + return m_shClose; +} +MimeTypes OFileSelector::mimeTypes()const { + return m_mimeType; +} +int OFileSelector::mode()const{ + return m_mode; +} +int OFileSelector::selector()const{ + return m_selector; +} +QStringList OFileSelector::currentMimeType()const { + return m_mimeType[m_cmbMime->currentText()]; +} +void OFileSelector::slotMimeTypeChanged() { + reread(); +} +void OFileSelector::slotDocLnkBridge( const DocLnk& lnk) { + m_lneEdit->setText( lnk.name() ); + emit fileSelected( lnk ); + emit fileSelected( lnk.name() ); +} +void OFileSelector::slotFileBridge( const QString& str) { + DocLnk lnk( str ); + emit fileSelected( lnk ); +} +void OFileSelector::slotViewChange( const QString& view ) { + OFileViewInterface* interface = m_views[view]; + if (!interface) + return; + + interface->activate( view ); + if (m_current) + m_stack->removeWidget( m_current->widget( m_stack ) ); + + static int id = 1; + + m_stack->addWidget( interface->widget(m_stack), id ); + m_stack->raiseWidget( id ); + + interface->reread(); + m_current = interface; + + id++; +} +void OFileSelector::setNewVisible( bool b ) { + m_shNew = b; + currentView()->reread(); +} +void OFileSelector::setCloseVisible( bool b ) { + m_shClose = b; + currentView()->reread(); +} +void OFileSelector::setNameVisible( bool b ) { + if ( b ) + m_nameBox->show(); + else + m_nameBox->hide(); +} diff --git a/microkde/ofileselector_p.h b/microkde/ofileselector_p.h new file mode 100644 index 0000000..b371806 --- a/dev/null +++ b/microkde/ofileselector_p.h @@ -0,0 +1,258 @@ +#ifndef OPIE_OFILE_SELECTOR_PRIVATE_H +#define OPIE_OFILE_SELECTOR_PRIVATE_H + +//US +#pragma message("microkde/ofileselector_p.h") + +#include <qmap.h> +#include <qstringlist.h> +#include <qwidget.h> +#include <qlistview.h> + +#include <qpe/applnk.h> +#include <qpe/fileselector.h> + + +/* + * How to avoid having really two different objects + * for Extended and ExtendedAll + * The only difference is the Lister... + * a) static object? + * b) leave some object inside the OFileSelector which can be used? + * c) when switching views tell which view we want o have.. internally we can switch then + * + * I'll take c) -zecke + */ + + +/* the View Interface */ +class OFileSelector; +typedef QMap<QString, QStringList> MimeTypes; +class QFileInfo; +class QToolButton; +class OFileViewInterface { +public: + OFileViewInterface( OFileSelector* selector ); + virtual ~OFileViewInterface(); + virtual QString selectedName()const = 0; + virtual QString selectedPath()const = 0; + virtual QString directory()const = 0; + virtual void reread() = 0; + virtual int fileCount()const = 0; + virtual DocLnk selectedDocument()const; + virtual QWidget* widget( QWidget* parent) = 0; + virtual void activate( const QString& ); + QString name()const; +protected: + OFileSelector* selector()const; + void setName( const QString& ); + bool showNew()const; + bool showClose()const; + MimeTypes mimeTypes()const; + QStringList currentMimeType()const; + QString startDirectory()const; +protected: + void ok(); + void cancel(); + void closeMe(); + void fileSelected( const QString& ); + void fileSelected( const DocLnk& ); + void setCurrentFileName( const QString& ); + QString currentFileName()const; + +private: + QString m_name; + OFileSelector* m_selector; +}; + + +/* THE Document View hosting a FileSelector*/ +class ODocumentFileView : public OFileViewInterface { +public: + ODocumentFileView( OFileSelector* selector ); + ~ODocumentFileView(); + + QString selectedName() const; + QString selectedPath() const; + + QString directory() const; + void reread(); + int fileCount()const; + DocLnk selectedDocument()const; + + QWidget* widget( QWidget* parent ); + +private: + mutable FileSelector* m_selector; + +}; + +class OFileSelectorItem : public QListViewItem { +public: + OFileSelectorItem( QListView* view, const QPixmap& pixmap, + const QString& path, const QString& date, + const QString& size, const QString& mDir, + bool isLocked = false, bool isDir = false ); + ~OFileSelectorItem(); + bool isLocked()const; + bool isDir()const; + QString directory()const; + QString path()const; + QString key(int id, bool )const; + +private: + bool m_locked : 1; + bool m_isDir : 1; + QString m_dir; +}; + +class OFileViewFileListView : public QWidget { + Q_OBJECT +public: + OFileViewFileListView( QWidget* parent, const QString& dir, OFileSelector* selector ); + ~OFileViewFileListView(); + + OFileSelectorItem* currentItem()const; + void reread( bool all = false ); + int fileCount()const; + QString currentDir()const; +protected: + bool eventFilter (QObject *o, QEvent *e); +private slots: + void slotNew(); // will emit newSelected + void cdUP(); + void cdHome(); + void cdDoc(); + void changeDir( const QString& ); + void slotCurrentChanged( QListViewItem* ); + void slotClicked(int, QListViewItem*, const QPoint&, int ); + void slotFSActivated(int); + +protected: + + OFileSelector* selector(); + +private: + QMap<QString, QString> m_dev; + bool m_all : 1; + OFileSelector* m_sel; + QPopupMenu* m_fsPop; + bool compliesMime( const QString& ); + QStringList m_mimes; // used in compy mime + QString m_currentDir; + QToolButton *m_btnNew, *m_btnClose; + void connectSlots(); + void addFile( QFileInfo* info, bool symlink = FALSE ); + void addDir ( QFileInfo* info, bool symlink = FALSE ); + void addSymlink( QFileInfo* info, bool = FALSE ); + + +private: + QListView* m_view; +}; + +typedef QMap<QString, QStringList> MimeTypes; + +class OFileViewInterface; +class OFileViewFileListView; +class QLineEdit; +class QComboBox; +class QWidgetStack; +class QHBox; +class OFileSelector : public QWidget { + Q_OBJECT + friend class OFileViewInterface; + friend class OFileViewFileListView; +public: + enum Mode { Open=1, Save=2, FileSelector=4, OPEN=1, SAVE=2, FILESELECTOR=4 }; +// enum OldMode { OPEN=1, SAVE=2, FILESELECTOR = 4 }; + enum Selector { Normal = 0, Extended=1, ExtendedAll =2, Default=3, NORMAL=0,EXTENDED=1, EXTENDED_ALL =2, DEFAULT=3 }; +// enum OldSelector { NORMAL = 0, EXTENDED =1, EXTENDED_ALL = 2}; + + OFileSelector(QWidget* parent, int mode, int selector, + const QString& dirName, + const QString& fileName, + const MimeTypes& mimetypes = MimeTypes(), + bool newVisible = FALSE, bool closeVisible = FALSE ); + + OFileSelector(const QString& mimeFilter, QWidget* parent, + const char* name = 0, bool newVisible = TRUE, bool closeVisible = FALSE ); + ~OFileSelector(); + + const DocLnk* selected(); + + QString selectedName()const; + QString selectedPath()const; + QString directory()const; + + DocLnk selectedDocument()const; + + int fileCount()const; + void reread(); + + int mode()const; + int selector()const; + + + void setNewVisible( bool b ); + void setCloseVisible( bool b ); + void setNameVisible( bool b ); + +signals: + void dirSelected( const QString& ); + void fileSelected( const DocLnk& ); + void fileSelected( const QString& ); + void newSelected( const DocLnk& ); + void closeMe(); + void ok(); + void cancel(); + +/* used by the ViewInterface */ +private: + bool showNew()const; + bool showClose()const; + MimeTypes mimeTypes()const; + QStringList currentMimeType()const; + +private: + /* inits the Widgets */ + void initUI(); + /* inits the MimeType ComboBox content + connects signals and slots */ + void initMime(); + /* init the Views :) */ + void initViews(); + +private: + QLineEdit* m_lneEdit; // the LineEdit for the Name + QComboBox *m_cmbView, *m_cmbMime; // two ComboBoxes to select the View and MimeType + QWidgetStack* m_stack; // our widget stack which will contain the views + OFileViewInterface* currentView()const; // returns the currentView + OFileViewInterface* m_current; // here is the view saved + bool m_shNew : 1; // should we show New? + bool m_shClose : 1; // should we show Close? + MimeTypes m_mimeType; // list of mimetypes + + QMap<QString, OFileViewInterface*> m_views; // QString translated view name + ViewInterface Ptr + QHBox* m_nameBox; // the LineEdit + Label is hold here + QHBox* m_cmbBox; // this holds the two combo boxes + + QString m_startDir; + int m_mode; + int m_selector; + + struct Data; // used for future versions + Data *d; + +private slots: + void slotMimeTypeChanged(); + + /* will set the text of the lineedit and emit a fileChanged signal */ + void slotDocLnkBridge( const DocLnk& ); + void slotFileBridge( const QString& ); + void slotViewChange( const QString& ); + + bool eventFilter (QObject *o, QEvent *e); + +}; + +#endif diff --git a/microkde/ofontselector.cpp b/microkde/ofontselector.cpp new file mode 100644 index 0000000..c8471cc --- a/dev/null +++ b/microkde/ofontselector.cpp @@ -0,0 +1,412 @@ +/* + =. This file is part of the OPIE Project + .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org> + .>+-= + _;:, .> :=|. This library is free software; you can +.> <`_, > . <= redistribute it and/or modify it under +:`=1 )Y*s>-.-- : the terms of the GNU Library General Public +.="- .-=="i, .._ License as published by the Free Software + - . .-<_> .<> Foundation; either version 2 of the License, + ._= =} : or (at your option) any later version. + .%`+i> _;_. + .i_,=:_. -<s. This library is distributed in the hope that + + . -:. = it will be useful, but WITHOUT ANY WARRANTY; + : .. .:, . . . without even the implied warranty of + =_ + =;=|` MERCHANTABILITY or FITNESS FOR A + _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU +..}^=.= = ; Library General Public License for more +++= -. .` .: details. + : = ...= . :.=- + -. .:....=;==+<; You should have received a copy of the GNU + -_. . . )=. = Library General Public License along with + -- :-=` this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#include <qlayout.h> +#include <qlistbox.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qfont.h> +#include <qmultilineedit.h> + +#include <qpe/fontdatabase.h> + +#include "ofontselector.h" + +class OFontSelectorPrivate { +public: + QListBox * m_font_family_list; + QComboBox * m_font_style_list; + QComboBox * m_font_size_list; + QMultiLineEdit *m_preview; + + bool m_pointbug : 1; + + FontDatabase m_fdb; +}; + +namespace { + +class FontListItem : public QListBoxText { +public: + FontListItem ( const QString &t, const QStringList &styles, const QValueList<int> &sizes ) : QListBoxText ( ) + { + m_name = t; + m_styles = styles; + m_sizes = sizes; + + QString str = t; + str [0] = str [0]. upper ( ); + setText ( str ); + } + + QString family ( ) const + { + return m_name; + } + + const QStringList &styles ( ) const + { + return m_styles; + } + + const QValueList<int> &sizes ( ) const + { + return m_sizes; + } + +private: + QStringList m_styles; + QValueList<int> m_sizes; + QString m_name; +}; + + +static int findItemCB ( QComboBox *box, const QString &str ) +{ + for ( int i = 0; i < box-> count ( ); i++ ) { + if ( box-> text ( i ) == str ) + return i; + } + return -1; +} + +} +/* static same as anon. namespace */ +static int qt_version ( ) +{ + const char *qver = qVersion ( ); + + return ( qver [0] - '0' ) * 100 + ( qver [2] - '0' ) * 10 + ( qver [4] - '0' ); +} + +/** + * Constructs the Selector object + * @param withpreview If a font preview should be given + * @param parent The parent of the Font Selector + * @param name The name of the object + * @param fl WidgetFlags + */ +OFontSelector::OFontSelector ( bool withpreview, QWidget *parent, const char *name, WFlags fl ) : QWidget ( parent, name, fl ) +{ + d = new OFontSelectorPrivate ( ); + + QGridLayout *gridLayout = new QGridLayout ( this, 0, 0, 4, 4 ); + gridLayout->setRowStretch ( 4, 10 ); + + d-> m_font_family_list = new QListBox( this, "FontListBox" ); + gridLayout->addMultiCellWidget( d-> m_font_family_list, 0, 4, 0, 0 ); + connect( d-> m_font_family_list, SIGNAL( highlighted( int ) ), this, SLOT( fontFamilyClicked( int ) ) ); + + QLabel *label = new QLabel( tr( "Style" ), this ); + gridLayout->addWidget( label, 0, 1 ); + + d-> m_font_style_list = new QComboBox( this, "StyleListBox" ); + connect( d-> m_font_style_list, SIGNAL( activated( int ) ), this, SLOT( fontStyleClicked( int ) ) ); + gridLayout->addWidget( d-> m_font_style_list, 1, 1 ); + + label = new QLabel( tr( "Size" ), this ); + gridLayout->addWidget( label, 2, 1 ); + + d-> m_font_size_list = new QComboBox( this, "SizeListBox" ); + connect( d-> m_font_size_list, SIGNAL( activated( int ) ), + this, SLOT( fontSizeClicked( int ) ) ); + gridLayout->addWidget( d-> m_font_size_list, 3, 1 ); + + d-> m_pointbug = ( qt_version ( ) <= 233 ); + + if ( withpreview ) { + d-> m_preview = new QMultiLineEdit ( this, "Preview" ); + d-> m_preview-> setAlignment ( AlignCenter ); + d-> m_preview-> setWordWrap ( QMultiLineEdit::WidgetWidth ); + d-> m_preview-> setMargin ( 3 ); + d-> m_preview-> setText ( tr( "The Quick Brown Fox Jumps Over The Lazy Dog" )); + gridLayout-> addRowSpacing ( 5, 4 ); + gridLayout-> addMultiCellWidget ( d-> m_preview, 6, 6, 0, 1 ); + gridLayout-> setRowStretch ( 6, 5 ); + } + else + d-> m_preview = 0; + + loadFonts ( d-> m_font_family_list ); +} + +OFontSelector::~OFontSelector ( ) +{ + delete d; +} + +/** + * This methods tries to set the font + * @param f The wishes font + * @return success or failure + */ +bool OFontSelector::setSelectedFont ( const QFont &f ) +{ + return setSelectedFont ( f. family ( ), d-> m_fdb. styleString ( f ), f. pointSize ( ), QFont::encodingName ( f. charSet ( ))); +} + + +/** + * This is an overloaded method @see setSelectedFont + * @param familyStr The family of the font + * @param styleStr The style of the font + * @param sizeVal The size of font + * @param charset The charset to be used. Will be deprecated by QT3 + */ +bool OFontSelector::setSelectedFont ( const QString &familyStr, const QString &styleStr, int sizeVal, const QString & charset ) +{ + QString sizeStr = QString::number ( sizeVal ); + + QListBoxItem *family = d-> m_font_family_list-> findItem ( familyStr ); + if ( !family ) + family = d-> m_font_family_list-> findItem ( "Helvetica" ); + if ( !family ) + family = d-> m_font_family_list-> firstItem ( ); + d-> m_font_family_list-> setCurrentItem ( family ); + fontFamilyClicked ( d-> m_font_family_list-> index ( family )); + + int style = findItemCB ( d-> m_font_style_list, styleStr ); + if ( style < 0 ) + style = findItemCB ( d-> m_font_style_list, "Regular" ); + if ( style < 0 && d-> m_font_style_list-> count ( ) > 0 ) + style = 0; + d-> m_font_style_list-> setCurrentItem ( style ); + fontStyleClicked ( style ); + + int size = findItemCB ( d-> m_font_size_list, sizeStr ); + if ( size < 0 ) + size = findItemCB ( d-> m_font_size_list, "10" ); + if ( size < 0 && d-> m_font_size_list-> count ( ) > 0 ) + size = 0; + d-> m_font_size_list-> setCurrentItem ( size ); + fontSizeClicked ( size ); + + return (( family ) && ( style >= 0 ) && ( size >= 0 )); +} + +/** + * This method returns the name, style and size of the currently selected + * font or false if no font is selected + * @param family The font family will be written there + * @param style The style will be written there + * @param size The size will be written there + * @return success or failure + */ +bool OFontSelector::selectedFont ( QString &family, QString &style, int &size ) +{ + QString dummy; + return selectedFont ( family, style, size, dummy ); +} + + +/** + * This method does return the font family or QString::null if there is + * no font item selected + * @return the font family + */ +QString OFontSelector::fontFamily ( ) const +{ + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( )); + + return fli ? fli-> family ( ) : QString::null; +} + +/** + * This method will return the style of the font or QString::null + * @return the style of the font + */ +QString OFontSelector::fontStyle ( ) const +{ + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( )); + int fst = d-> m_font_style_list-> currentItem ( ); + + return ( fli && fst >= 0 ) ? fli-> styles ( ) [fst] : QString::null; +} + +/** + * This method will return the font size or 10 if no font size is available + */ +int OFontSelector::fontSize ( ) const +{ + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( )); + int fsi = d-> m_font_size_list-> currentItem ( ); + + return ( fli && fsi >= 0 ) ? fli-> sizes ( ) [fsi] : 10; +} + +/** + * returns the charset of the font or QString::null + */ +QString OFontSelector::fontCharSet ( ) const +{ + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( d-> m_font_family_list-> currentItem ( )); + + return fli ? d-> m_fdb. charSets ( fli-> family ( )) [0] : QString::null; +} + +/** + * Overloaded member function see above + * @see selectedFont + */ +bool OFontSelector::selectedFont ( QString &family, QString &style, int &size, QString &charset ) +{ + int ffa = d-> m_font_family_list-> currentItem ( ); + int fst = d-> m_font_style_list-> currentItem ( ); + int fsi = d-> m_font_size_list-> currentItem ( ); + + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( ffa ); + + if ( fli ) { + family = fli-> family ( ); + style = fst >= 0 ? fli-> styles ( ) [fst] : QString::null; + size = fsi >= 0 ? fli-> sizes ( ) [fsi] : 10; + charset = d-> m_fdb. charSets ( fli-> family ( )) [0]; + + return true; + } + else + return false; +} + + + + +void OFontSelector::loadFonts ( QListBox *list ) +{ + QStringList f = d-> m_fdb. families ( ); + + for ( QStringList::ConstIterator it = f. begin ( ); it != f. end ( ); ++it ) { + QValueList <int> ps = d-> m_fdb. pointSizes ( *it ); + + if ( d-> m_pointbug ) { + for ( QValueList <int>::Iterator it = ps. begin ( ); it != ps. end ( ); it++ ) + *it /= 10; + } + + list-> insertItem ( new FontListItem ( *it, d-> m_fdb. styles ( *it ), ps )); + } +} + +void OFontSelector::fontFamilyClicked ( int index ) +{ + QString oldstyle = d-> m_font_style_list-> currentText ( ); + QString oldsize = d-> m_font_size_list-> currentText ( ); + + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( index ); + + d-> m_font_style_list-> clear ( ); + d-> m_font_style_list-> insertStringList ( fli-> styles ( )); + d-> m_font_style_list-> setEnabled ( !fli-> styles ( ). isEmpty ( )); + + int i; + + i = findItemCB ( d-> m_font_style_list, oldstyle ); + if ( i < 0 ) + i = findItemCB ( d-> m_font_style_list, "Regular" ); + if (( i < 0 ) && ( d-> m_font_style_list-> count ( ) > 0 )) + i = 0; + + if ( i >= 0 ) { + d-> m_font_style_list-> setCurrentItem ( i ); + fontStyleClicked ( i ); + } + + d-> m_font_size_list-> clear ( ); + QValueList<int> sl = fli-> sizes ( ); + + for ( QValueList<int>::Iterator it = sl. begin ( ); it != sl. end ( ); ++it ) + d-> m_font_size_list-> insertItem ( QString::number ( *it )); + + i = findItemCB ( d-> m_font_size_list, oldsize ); + if ( i < 0 ) + i = findItemCB ( d-> m_font_size_list, "10" ); + if (( i < 0 ) && ( d-> m_font_size_list-> count ( ) > 0 )) + i = 0; + + if ( i >= 0 ) { + d-> m_font_size_list-> setCurrentItem ( i ); + fontSizeClicked ( i ); + } + changeFont ( ); +} + +void OFontSelector::fontStyleClicked ( int /*index*/ ) +{ + changeFont ( ); +} + +void OFontSelector::fontSizeClicked ( int /*index*/ ) +{ + changeFont ( ); +} + +void OFontSelector::changeFont ( ) +{ + QFont f = selectedFont ( ); + + if ( d-> m_preview ) + d-> m_preview-> setFont ( f ); + + emit fontSelected ( f ); +} + +/** + * Return the selected font + */ +QFont OFontSelector::selectedFont ( ) +{ + int ffa = d-> m_font_family_list-> currentItem ( ); + int fst = d-> m_font_style_list-> currentItem ( ); + int fsi = d-> m_font_size_list-> currentItem ( ); + + FontListItem *fli = (FontListItem *) d-> m_font_family_list-> item ( ffa ); + + if ( fli ) { + return d-> m_fdb. font ( fli-> family ( ), \ + fst >= 0 ? fli-> styles ( ) [fst] : QString::null, \ + fsi >= 0 ? fli-> sizes ( ) [fsi] : 10, \ + d-> m_fdb. charSets ( fli-> family ( )) [0] ); + } + else + return QFont ( ); +} + + +void OFontSelector::resizeEvent ( QResizeEvent *re ) +{ + if ( d-> m_preview ) { + d-> m_preview-> setMinimumHeight ( 1 ); + d-> m_preview-> setMaximumHeight ( 32767 ); + } + + QWidget::resizeEvent ( re ); + + if ( d-> m_preview ) + d-> m_preview-> setFixedHeight ( d-> m_preview-> height ( )); + +} diff --git a/microkde/ofontselector.h b/microkde/ofontselector.h new file mode 100644 index 0000000..b819c45 --- a/dev/null +++ b/microkde/ofontselector.h @@ -0,0 +1,96 @@ +/* + =. This file is part of the OPIE Project + .=l. Copyright (c) 2002 Robert Griebl <sandman@handhelds.org> + .>+-= + _;:, .> :=|. This library is free software; you can +.> <`_, > . <= redistribute it and/or modify it under +:`=1 )Y*s>-.-- : the terms of the GNU Library General Public +.="- .-=="i, .._ License as published by the Free Software + - . .-<_> .<> Foundation; either version 2 of the License, + ._= =} : or (at your option) any later version. + .%`+i> _;_. + .i_,=:_. -<s. This library is distributed in the hope that + + . -:. = it will be useful, but WITHOUT ANY WARRANTY; + : .. .:, . . . without even the implied warranty of + =_ + =;=|` MERCHANTABILITY or FITNESS FOR A + _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU +..}^=.= = ; Library General Public License for more +++= -. .` .: details. + : = ...= . :.=- + -. .:....=;==+<; You should have received a copy of the GNU + -_. . . )=. = Library General Public License along with + -- :-=` this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#ifndef OPIE_FONTSELECTOR_H__ +#define OPIE_FONTSELECTOR_H__ + +#include <qwidget.h> + +class QListBox; +class OFontSelectorPrivate; + +/** + * This class lets you chose a Font out of a list of Fonts. + * It can show a preview too. This selector will use all available + * fonts + * + * + * @short A widget to select a font + * @see QWidget + * @see QFont + * @author Rober Griebl + */ +class OFontSelector : public QWidget +{ + Q_OBJECT + +public: + OFontSelector ( bool withpreview, QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + virtual ~OFontSelector ( ); + + bool selectedFont ( QString &family, QString &style, int &size ); + bool selectedFont ( QString &family, QString &style, int &size, QString &charset ); + + QFont selectedFont ( ); + + bool setSelectedFont ( const QFont & ); + bool setSelectedFont ( const QString &family, const QString &style, int size, const QString &charset = 0 ); + + QString fontFamily ( ) const; + QString fontStyle ( ) const; + int fontSize ( ) const; + QString fontCharSet ( ) const; + +signals: + /** + * This signal gets emitted when a font got chosen + */ + void fontSelected ( const QFont & ); + +protected slots: + /** @internal */ + virtual void fontFamilyClicked ( int ); + /** @internal */ + virtual void fontStyleClicked ( int ); + /** @internal */ + virtual void fontSizeClicked ( int ); + +protected: + virtual void resizeEvent ( QResizeEvent *re ); + +private: + void loadFonts ( QListBox * ); + + void changeFont ( ); + +private: + OFontSelectorPrivate *d; +}; + +#endif + diff --git a/microkde/qlayoutengine_p.h b/microkde/qlayoutengine_p.h new file mode 100644 index 0000000..2d6a556 --- a/dev/null +++ b/microkde/qlayoutengine_p.h @@ -0,0 +1,111 @@ +// THIS IS A COPY OF THE FILE FOUND IN $QTDIR/src/kernel. Needed to modify qsplitter + +/**************************************************************************** +** $Id$ +** +** Internal header file. +** +** Created : 981027 +** +** Copyright (C) 1998-99 by Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QLAYOUTENGINE_P_H +#define QLAYOUTENGINE_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qlayout.cpp, qlayoutengine.cpp, qmainwindow.cpp and qsplitter.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + + +#ifndef QT_H +#include "qabstractlayout.h" +#endif // QT_H + +#ifndef QT_NO_LAYOUT +struct QLayoutStruct +{ + void initParameters() { minimumSize = sizeHint = 0; + maximumSize = QWIDGETSIZE_MAX; expansive = FALSE; empty = TRUE; } + void init() { stretch = 0; initParameters(); } + //permanent storage: + int stretch; + //parameters: + QCOORD sizeHint; + QCOORD maximumSize; + QCOORD minimumSize; + bool expansive; + bool empty; + //temporary storage: + bool done; + //result: + int pos; + int size; +}; + + +void qGeomCalc( QMemArray<QLayoutStruct> &chain, int start, int count, int pos, + int space, int spacer ); + + + +/* + Modify total maximum (max) and total expansion (exp) + when adding boxmax/boxexp. + + Expansive boxes win over non-expansive boxes. +*/ +static inline void qMaxExpCalc( QCOORD & max, bool &exp, + QCOORD boxmax, bool boxexp ) +{ + if ( exp ) { + if ( boxexp ) + max = QMAX( max, boxmax ); + } else { + if ( boxexp ) + max = boxmax; + else + max = QMIN( max, boxmax ); + } + exp = exp || boxexp; +} + +#endif //QT_NO_LAYOUT +#endif diff --git a/microkde/words.sort.txt b/microkde/words.sort.txt new file mode 100644 index 0000000..a477be7 --- a/dev/null +++ b/microkde/words.sort.txt @@ -0,0 +1,549 @@ + +{ "10 minutes", "10 Minuten", }, +{ "10th", "10." }, +{ "11th", "11." }, +{ "12 pm Format", "12 AM/PM Format" }, +{ "12th", "12." }, +{ "13th", "13." }, +{ "14th", "14." }, +{ "15th", "15." }, +{ "16th", "16." }, +{ "17th", "17." }, +{ "18th", "18." }, +{ "19th", "19." }, +{ "1 Day", "1 Tag" }, +{ "1 h", "1 Std" }, +{ "1 (Highest)", "1 (Höchster)" }, +{ "1st", "1." }, +{ "1st", "2." }, +{ "20th", "20." }, +{ "21st", "21." }, +{ "22nd", "22." }, +{ "23rd", "23." }, +{ "24:00 Hour Format", "24:00 Stunden Format" }, +{ "24th", "24." }, +{ "25th", "25." }, +{ "26th", "26." }, +{ "27th", "27." }, +{ "28th", "28." }, +{ "29th", "29." }, +{ "2nd", "2." }, +{ "30 minutes", "30 Minuten" }, +{ "30th", "30." }, +{ "31st", "31." }, +{ "3rd", "3." }, +{ "4th", "4." }, +{ "5 (lowest)", "5 (Niedrigster)" }, +{ "5th", "5." }, +{ "6th", "6." }, +{ "7th", "7." }, +{ "8th", "8." }, +{ "9th", "9." }, +{ "&Accept", "&Akzeptieren" }, +{ "Accept", "Akzeptieren" }, +{ "Accept A&ll", "A&lles Akzepieren" }, +{ "Access:", "Zugriff:" }, +{ "A corresponding event is missing in your calendar!", "Ein zugehöriges Ereignis fehlt in ihrem Kalender!" }, +{ "Actions", "Aktionen" }, +{ "Add Filter", "Filter Hinzufügen" }, +{ "&Add", "Hinzufügen" }, +{ "Add", "Hinzufügen" }, +{ "Additional email addresses:", "Zusätzliche E-Mail Adressen:" }, +{ "Additional email address:", "Zusätzliche E-Mail Adresse:" }, +{ "&Addressbook", "&Adressbuch" }, +{ "Address &Book...", "Adress&buch..." }, +{ "Agenda Size", "Agende Größe" }, +{ "Agenda Size:", "Größe der Agenda:" }, +{ "Agenda view:", "Agenda Anzeige:" }, +{ "Agenda view background color:", "Hintergrundfarbe der Agenda Anzeige:" }, +{ "All attendees", "Alle Teilnehmer" }, +{ "AllDayAgenda Height:", "Ganztagesagenda Höhe" }, +{ "Allday", "Ganztägig" }, +{ "Anonymous", "Anonym" }, +{ "Apply", "Bestätigen" }, +//{ "Appointment Time ", "" }, +{ "Apr", "Apr" }, +{ "April", "April" }, +//"Ask for every entry on conflict", "", +{ "Ask for preferences before syncing", "Vor dem Syncronisieren nachfragen" }, +{ "Ask for quit when closing KO/Pi", "Vor dem Beenden von KO/Pi nachfragen" }, +{ "Attendees", "Teilnehmer" }, +{ "Aug", "Aug" }, +{ "August", "August" }, +//"Auto Insert IMIP Replies"), +//"Auto Insert IMIP Requests"), +{ "Auto-Save", "Automatisches Abspeichern" }, +{ "Auto save delay in minutes:", "Auto Save Intervall in Minuten" }, +//"Auto Save FreeBusy Replies", "" +//"Auto Send FreeBusy Information"), +//"Auto Send Refresh"), +//"<b>Due on:</b> %1", "", +//"be added to the standard resource", "", +//"be asked which resource to use", "", +{ "Begin on:", "Starte mit:" }, +{ "Begins on: %1", "Starte mit: %1" }, +{ "<b>From:</b> %1 <b>To:</b> %2", "<b>Vom:</b> %1 <b>Zum:</b> %2" }, +{ "Bigger", "Größer" }, +{ "Biggest", "Am größten" }, +{ "Big", "Groß" }, +{ "<b>On:</b> %1", "<b>Am:</b> %1" }, +{ "<b>On:</b> %1 <b>From:S</b> %2 <b>To:</b> %3", "<b>Am:</b> %1 <b>Vom:S</b> %2 <b>Zum:</b> %3" }, +{ "<b>Original event:</b><p>", "<b>Original Ereignis:</b><p>" }, +{ " - both are modified after last sync", " - beide wurden nach der letzten Syncronisation verändert" }, +{ "Busy", "Belegt" }, +{ "&Cancel", "Abbre&chen" }, +{ "Cancel", "Abbrechen" }, +{ "Cannot delete To-Do\nwhich has children.", "Kann Todo nicht löschen,\n da noch Einträge vorhanden sind" }, +{ "Cannot delete To-Do which has children.", "Kann Todo nicht löschen, da noch Einträge vorhanden sind" }, +//"Cannot move To-Do to itself or a child of itself"), +//"Cannot purge To-Do which\nhas uncompleted children." +//"Can't generate mail:\nNo attendees defined.\n")); +{ "Can't generate mail:\nNo event selected.", "Kann e-Mail nicht erstellen:\nKein Ereignis ausgewählt." }, +{ "Categories...", "Kategorien..." }, +{ "Categories", "Kategorien" }, +{ "Category", "Kategorie" }, +{ "Center View", "Mittenansicht" }, +{ "Change", "Verändere" }, +{ "Cinema", "Kino" }, +{ "Click to add a new Todo", "Klicken, um ein neues Todo anzulegen" }, +{ "Clone Item", "Klone Eintrag" }, +{ "&Close", "S&chließen" }, +{ "Close", "Schließen" }, +{ "Close this dialog to abort deletion!", "Zum Abbrechen des Löschvorganges Dialog schließen!" }, +{ "Colors", "Farben" }, +{ "completed", "fertiggestellt" }, +{ "completed on %1", "fertiggestellt um %1" }, +{ "Complete", "Fertigstellen" }, +//{ "concatenation of dates and time", "%1 %2" }, +{ "Confirm &deletes", "Löschvogang bestätigen" }, +//"Copying succeed. Syncing not yet implemented" +//"Copy remote file to local machine..." +//{ "Could not find your attendee entry.\nPlease check the emails.")) }, +{ "Couldn't load calendar\n '%1'.", "Kann Kalender\n '%1' nicht laden." }, +{ "Counter-event Viewer", "Ereigniszähler Anzeige" }, +//{ "counter proposal event","<b>Counter-event:</b><p>" }, +{ "Daily ending hour:", "Tägl. Schlusszeit:" }, +{ "Daily starting hour:", "Tägliche Anfangszeit:" }, +{ "Daily", "Täglich" }, +{ "Date Format", "Datum Format" }, +{ "DateNavigator:(nr)" , "Datums Navigator" }, +//{ "Date Range") }, +{ "Dates: ", "Datum: " }, +{ "Date && Time", "Datum && Zeit" }, +{ "Day begins at:", "Der Tag beginnt um:" }, +{ "Days in Next-X-Days:", "Tage in den Nächsten-X-Tagen:" }, +{ "Days in What's Next:", "Tage in Was-kommt-Nun:" }, +{ "day(s)", "Tag(e)" }, +{ "Days to show in Next-X-Days view:", "Welche Tage in Nächste-X-Tagen anzeigen:" }, +{ "day", "Tag" }, +{ "Dec", "Dez" }, +{ "December", "Dezember" }, +{ "Default alarm time:", "Standard Alarm Zeit:" }, +//{ "Default appointment time:") }, +//{ "Default Calendar Format") }, +//{ "Default event color:") }, +//{ "Default export file", "calendar.html")) }, +{ "Default", "Standard" }, +//{ "Def. duration of new app.:") }, +{ "Delete All", "Lösche alles" }, +{ "Delete all selected", "Lösche alle ausgewählten" }, +//{ "delete completed To-Dos","Purge Completed") }, +//{ "delete completed To-Dos","Purge Completed") }, +{ "Delete Current", "Aktuellen löschen" }, +{ "Delete Event...", "Lösche Ereignis..." }, +{ "Delete Event", "Lösche Ereignis" }, +{ "&Delete", "Löschen" }, +{ "Delete", "Löschen" }, +{ "Delete Todo...", "Lösche Todo..." }, +{ "Delete To-Do", "Lösche Todo" }, +{ "Deleting item %d ...", "Lösche Eintrag %d..." }, +{ "Descriptions", "Beschreibungen" }, +{ "Deselect All", "Alles deselektieren" }, +{ "Details", "Details" }, +{ "Dinner", "Abendessen" }, +//{ "%d item(s) found."), mMatchedEvents.count() ) }, +//{ "%d items remaining in list."), count() ) }, +{ "Do you really want\nto close KO/Pi?", "Möchten Sie wirklich\nKO/PI verlassen?" }, +//"Do you really want\nto remote sync?\n \n" +//{ "Drop Event }, +//{ "Drop To-Do")) }, +//{ "Due Date")) }, +//{ "Due: ")+ (static_cast<Todo*>(mIncidence))->dtDueTimeStr() }, +//{ "Due Time")) }, +//{ "Due:"),timeBoxFrame) }, +{ "Duration: ", "Dauer: " }, +{ "Edit...", "Bearbeite..." }, +{ "Edit", "Bearbeite" }, +//{ "Edit Calendar Filters }, +{ "Edit Event...", "Bearbeite Ereignis..." }, +{ "Edit Event", "Bearbeite Ereignis" }, +//{ "Edit exceptions"), Ok|Cancel }, +{ "EditorBox:", "Editor Fenster:" }, +{ "Edit Recurrence Range", "Bearbeite Wiederholung" }, +//{ "&Edit..."),this,SLOT(popupEdit()))) }, +{ "Edit Todo...", "Berabeite Todo..." }, +{ "Edit To-Do", "Todo bearbeiten" }, +//{ "Email:" ) ) }, +{ "E&mail address:", "E&mail Adresse" }, +{ "(EmptyEmail)" , "(KeineEmail)" }, +{ "(EmptyName)", "(KeinName)" }, +//{ "Enable automatic saving of calendar") }, +//{ "Enable group scheduling") }, +//{ "Enable project view") }, +//{ "Enable Recurrence"), this ) }, +//{ "Enable scrollbars in month view cells") }, +//{ "Enable tooltips displaying summary of ev.") }, +//{ "End after"), rangeBox ) }, +//{ "End by:"), rangeBox ) }, +//{ "End Date")) }, +{ "End:", "Ende:" }, +//{ "End Time", "E)) }, +{ "English", "Englisch" }, +//{ "Enter filter name: }, +//{ "Error", "Fehler" }, +//{ "Error loading template file '%1'." }, +//{ "Event already exists in this calendar.") }, +{ "Event", "Ereignis" }, +{ "Event list", "Ereignis Liste" }, +//{ "Event list view uses full window") }, +//{ "Events and To-Dos that need a reply:") + "</h2>\n" }, +//{ "Events: ") + "</h2>\n" }, +//{ "Events have to be completely included"), topFrame) }, +//{ "Events"),incidenceGroup) }, +{ "Event Viewer:", "Ereignis Anzeige" }, +//{ "Event Viewer"),Ok|User1,Ok,false }, +//{ "Event will be sent to:")+"</h4>" }, +//{ "every"), this ) }, +{ "Exceptions...", "Ausnahmen..." }, +{ "Exceptions", "Ausnahmen" }, +{ "Exclude holidays", "Ohne Ferien" }, +{ "Exclude Saturdays", "Ohne Samstage" }, +//{ "Export to HTML with every save"),&(KOPrefs::instance()->mHtmlWithSave) }, +{ "Feb", "Feb" }, +{ "February", "Februar" }, +//{ "Filter disabled }, +//{ "Filter position: ") + QString::number ( mSelectionCombo->currentItem()+1 )) }, +//{ "Filter selected: }, +{ "&Find", "Finden" }, +{ "Fonts", "Zeichensätze" }, +//{ "Force take local entry always")) }, +//{ "Force take remote entry always")) }, +//{ "Form1" ) ) }, +//{ "Free Busy Object")) }, +{ "Free", "Frei" }, +{ "Friday", "Freitag" }, +{ "Fri", "Fr" }, +//{ "From: %1 To: %2 %3").arg(from).arg(to }, +//{ "From:"),rangeWidget)) }, +{ "Full &name:", "Vor- und &Nachname:" }, +//{ "Full path and file name required!"), topFrame) }, +{ "General", "Allgemein" }, +{ "German", "Deutsch" }, +{ "Gifts", "Geschenke" }, +//{ "Group Automation"),0 }, +//{ "Group Scheduling"),0 }, +{ "Help", "Hilfe" }, +{ "Hide Dates", "Daten ausblenden" }, +{ "Highlight color:" "Hervorhebungsfarbe" }, +{ "Holiday color:", "Ferien Farbe" }, +{ "hour(s)", "Stunde(n)" }, +//{ "iCalendar")) }, +//{ "If attendee is in addressbook")) }, +//{ "If organizer is in addressbook")) }, +//{ "If requested from an email in addressbook")) }, +//{ "If this counter-event is a good proposal for your event, press 'Accept'. All Attendees will then get the new version of this event }, +//{ "In %1 days: ").arg( i ) + "</font></em>"+day }, +//{ "Incomplete Todo:") + "</strong></big></big>\n" }, +{ "Information", "Information" }, +{ "Invalid search expression,\ncannot perform ", "Kann Suche nicht ausführen" }, +{ "Jan", "Jan" }, +{ "January", "Januar" }, +{ "JournalView:", "Journal Ansicht" }, +{ "Jul", "Jul" }, +{ "July", "Juli" }, +{ "Jump to date", "Springe zum Datum" }, +{ "June", "Juni" }, +{ "Jun", "Jun" }, +{ "Kids", "Kinder" }, +//{ "KMail", "KMail" }, +{ "KO/E Find ", "KO/E Suchen " }, +{ "KO/E Find: ", "KO/E Suchen: " }, +{ "KO/Pi is starting ... ", "KO/Pi startet ..." }, +{ "Language:(nyi)", "Sprache" }, +{ "Language:", "Sprache" }, +{ "Large", "Etwas mehr" }, +{ "List View:", "Listenansicht" }, +{ "Load/Save", "Laden/Speichern" }, +{ "Load Template", "Lade Vorlage" }, +{ "Locale", "Spracheinstellung" }, +{ "Local temp file:", "Lokales temp. Datei:" }, +//"Local temp file:\n " +//"Local temp file:\n..." +{ "Location: ", "Ort: " }, +{ "Location:", "Ort:" }, +{ "Mail client", "Mail Programm" }, +{ "Mail Client", "Mail Programm" }, +{ "March", "März" }, +{ "Mar", "Mär" }, +{ "May", "Mai" }, +{ "M. Bains line:", "M. Bains Linie:" }, +{ "Medium", "Medium" }, +{ "Method", "Methode" }, +{ "minute(s)", "Minute(n)" }, +{ "Monday", "Montag" }, +{ "Mon", "Mo" }, +{ "Monthly", "Monatlich" }, +{ "Month not long enough", "Monat ist nicht lang genug" }, +{ "month(s)", "Monat(e)" }, +{ "Month view:", "Monatsansicht" }, +{ "Month view uses category colors", "Monatsansicht benutzt die Kategorie Farben" }, +{ "Move &Down", "Nach unten verschieben" }, +{ "Move &Up", "Nach oben verschieben" }, +{ "Name:", "Name:" }, +{ "Name", "Name" }, +{ "\nAre you sure you want\nto delete this event?", "Sind Sie sicher, dass\n sie das Ereignis löschen möchten?" }, +{ "%n Days", "%n Tage" }, +{ "Never", "Nie" }, +{ "New event...", "Neues Ereignis..." }, +{ "New event", "Neues Ereignis" }, +{ "New Events/Todos should", "Meue Ereignisse/Todos sollten" }, +{ "&New", "&Neu" }, +{ "New", "Neu", }, +{ "New Sub-Todo...", "Neues Sub-Todo..." }, +{ "New Todo...", "Neues Todo..." }, +{ "New Todo", "Neues Todo" }, +{ "Next Alarm: ", "Nächster Alarm: ", }, +{ "&Next Day", "&Nächster Tag", }, +{ "Next days view uses full window", "Die Ansicht des nächsten Tages maximieren" }, +{ "Next month", "Nächster Monat" }, +{ "&Next Week", "&Nächste Woche" }, +{ "Next year", "Nächstes Jahr" }, +{ "Next Year", "Nächstes Jahr" }, +{ "%n h", "%n Std" }, +//"\n \nTry command on console to get more\ndetailed info about the reason.\n" +//{ "nobody@nowhere", " }, +{ "No ending date", "Kein End-Datum", }, +{ "No event, nothing to do.", "Kein Ereignis, nichts zu tun.", }, +{ "No event selected.", "Kein Ereignis selektiert" }, +//{ "No event/todo were found matching\nyour search expression.\nUse the wildcard characters\n ' * ' and ' ? ' where needed."));"KO/E Find ")) }, +{ "No", "Nein" }, +{ "No program set", "Kein Programm ausgewählt", }, +{ "Normal", "Normal" }, +{ "[No selection]", "Keine Selektion", }, +{ "No sound set", "Kein Sound ausgewählt", }, +{ "no time ", "keine Zeit ", }, +{ "no time", "keine Zeit", }, +{ "No Time", "Keine Zeit" }, +{ "November", "November" }, +{ "Nov", "Nov", }, +{ "\nThis event recurs\nover multiple dates.\n", "\nDieses Ereignis wiederholt sich an mehreren Tagen.\n" }, +//{ "occurrence(s)"), rangeBox ) }, +{ "October", "Oktober" }, +{ "Oct", "Okt", }, +//{ "O-due!", " }, +//{ "Okay, another question:\n\nDo you really want\nto erase your complete disk?\nI hope, the decision is now\na little bit easier! }, +{ "&OK", "&OK" }, +{ "Ok+Show!", "Ok+Anzeigen" }, +{ "Organizer: %1","Organizer %1" }, +{ "Organizer","Organizer" }, +//{ "Overdue To-Do:") + "</h2>\n" }, +{ "Owner: ", "Besitzer: " }, +{ "Owner:", "Besitzer:" }, +{ "<p><b>Priority:</b> %2</p>", "<p><b>Priorität:</b> %2</p>" }, +//{ "Personal Travel", }, +//{ "<p><i>%1 % completed</i></p>" }, +{ "Pick a date to display", "Wähle einen Tag zum anzeigen aus" }, +//{ "Playing '%1'").arg(fileName) }, +//{ "Playing '%1'").arg(mAlarmSound) }, +//{ "Please specify a valid due date.")) }, +//{ "Please specify a valid end date, for example '%1'." }, +//{ "Please specify a valid start date.")) }, +//{ "Please specify a valid start date, for example '%1'." }, +//{ "Please specify a valid start time.")) }, +//{ "Please specify a valid start time, for example '%1'." }, +//{ "Preferences - some settings need a restart (nr)")) }, +{ "Preferences - some settings need a restart (nr)", "Einstellungen - teilweise Neustart erforderlich" }, +{ "&Previous Day", "Vorheriger Tag" }, +{ "Previous month", "Vorheriger Monat" }, +{ "Previous Month", "Vorheriger Monat" }, +{ "&Previous Week", "Vorherige Woche" }, +{ "Previous year", "Vorheriges Jahr" }, +{ "Previous Year", "Vorheriges Jahr" }, +{ "Printing", "Drucken" }, +//{ "Prio")) }, +//{ "Priority:"), h) }, +{ "Proceed", "Weiter" }, +//{ "Purge }, +//{ "read-only") + ")</em>") }, +{ "Recur every", "Wiederh. alle" }, +{ "Recur in the month of", "Wiederh. im Monat" }, +{ "Recur on the", "Wiederh. am" }, +{ "Recur on this day", "Wiederh. am diesen Tag" }, +{ "Recurrence Range...", "Wiederholungs Zeitraum..." }, +{ "Recurrence Range", "Wiederholungs Zeitraum" }, +{ "Recurrence Rule", "Wiederholungs Regel" }, +{ "Recurrence", "Wiederholung" }, +{ "Recurs", "Wiederhole" }, +"&Reject", "Abweisen", +{ "Reminder:", "Erinnerung:" }, +//"Remote file:\n " +//"Remote file:\n..." +//{ "Remote file:"), topFrame) }, +//{ "Remote IP:"), topFrame) }, +//{ "Remote passwd:"), topFrame) }, +//{ "Remote syncing (via ssh/scp) network settings "), topFrame) }, +//{ "Remote user:"), topFrame) }, +{ "&Remove", "Entfe&rnen" }, +{ "Remove", "Entfernen" }, +{ "Request response", "Bemerkung anfordern" }, +//{ "Retrieve &Messages" ) ) }, +{ "Role:", "Rolle:" }, +{ "Role", "Rolle" }, +//{ "RSVP"),35) }, +//{ "Running '%1'").arg(fileName) }, +//{ "Running '%1'").arg(mAlarmProgram) }, +{ "Sat", "Sa" }, +{ "Saturday", "Samstag" }, +//{ "Save Template"), Ok | Cancel, Ok, parent, 0 }, +//{ "Scheduler - Incoming Messages" ) ) }, +//{ "Scheduler Mail Client"),&(KOPrefs::instance()->mIMIPScheduler) }, +//{ "Scheduler Mails Should Be"),&(KOPrefs::instance()->mIMIPSend) }, +//{ "Scheduler - Outgoing Messages" ) ) }, +{ "Search for:", "Suche nach:" }, +{ "Search In", "Suche in" }, +{ "Search", "Suche" }, +{ "Select Addresses", "Wähle Adressen" }, +{ "Select all", "Wähle alles" }, +{ "Select a month", "Wähle Monat" }, +//{ "Select a template to load:"), templates, 0, &ok ) }, +{ "Select a week", "Wähle Woche" }, +{ "Select a year", "Wähle Jahr" }, +//{ "selected emails")) }, +//{ "Select Template Name"), topFrame }, +//{ "Select the current day")) }, +//{ "Send copy to owner when mailing events") }, +{ "Send directly", "Sende direkt" }, +//{ "Sendmail")) }, +{ "&Send Messages", "&Sende Nachrichten", }, +//{ "Send to outbox")) }, +{ "Sep", "Sep" }, +{ "September", "September" }, +//{ "Set your status }, +//{ "Set Your Status")) }, +{ "Shopping", "Einkaufen" }, +{ "Short date in (WN/E) view", "Kurzdatum in (WN/E) Anzeige" }, +{ "Show Dates", "Zeige Daten" }, +//{ "Show events that recur daily in date nav.") }, +{ "Show Event...", "Zeige Ereignis..." }, +//{ "Show ev. that recur weekly in date nav.") }, +//{ "Show Marcus Bains line") }, +//{ "Show seconds on Marcus Bains line") }, +//{ "Show summary after syncing") }, +{ "Show time as:", "Zeige Zeit als" }, +{ "Show Todo...", "Zeige To-Do" }, +//{ "Show topmost todo prios in What's N.:") }, +//{ "Show topmost todo prios in What's Next:") }, +//{ "Show vertical screen (Needs restart)") }, +{ "&Show", "Zeige" }, +{ "Show...", "Zeige..." }, +{ "Show", "Zeige" }, +{ "Small", "Klein" }, +{ "Sorry", "Entschuldigung" }, +//"Sorry, the copy command failed!\nCommand was:\n" +//{ "Sort Id")) }, +{ "Start:", "Anfang:" }, +{ "Start Date", "Start Datum" }, +{ "Start Time", "Start Zeit" }, +{ "Status:", "Status:" }, +{ "Status","Status:" }, +//{ "Stretched TB", " +{ "Summaries","Zusammenfassungen" }, +{ "Summary:","Zusammenfassung:" }, +{ "Summary","Zusammenfassung" }, +{ "Sunday", "Sonntag" }, +{ "Sun", "So" }, +//{ "Sync Network"),0,0) }, +{ "Sync preferences:", "Sync Einstellungen" }, +{ "Sync Prefs", "Sync Einstellungen" }, +{ "Syncronize", "Daten abgleich" }, +//{ "Take local entry on conflict")) }, +//{ "Take newest entry on conflict")) }, +//{ "Take remote entry on conflict")) }, +//{ "Template '%1' does not contain a valid Todo." }, +//{ "Template does not contain a valid Event." }, +{ "Template...", "Vorlage..." }, +//{ "The event ends before it starts.\n }, +//{ "The event has no attendees.")) }, +//{ "The journal entries can not be\nexported to a vCalendar file.") }, +//{ "The organizer %1", " }, +//{ "The start date cannot be after the due date.")) }, +//{ " - they have the same unique ID "), topFrame) }, +{ "This day", "Dieser Tag" }, +{ "This is an experimental feature. ", "Dieses Feature ist experimentel" }, +//{ "This is a recurring event.") + "</em>") }, +{ "This item will be\npermanently deleted.", "Dieser Eintrag wird\nkomplett gelöscht." }, +{ "This item will be permanently deleted.", "Dieser Eintrag wird komplett gelöscht." }, +{ "Thu", "Do" }, +{ "Thursday", "Donnerstag" }, +{ "Time associated", "Dazugehörige Zeit" }, +{ "Time bar:", "Zeit Intervall" }, +{ "Time && Date", "Zeit und Datum" }, +{ "Time Format", "Zeit Format" }, +{ "Time Labels:", "Zeit Markierungen:" }, +{ "Time: ", "Zeit: " }, +{ "Timezone:", "Zeitzone:" }, +{ "Tiny", "Sehr klein" }, +{ "To: ", "An: " }, +{ "To:", "An:" }, +{ "Today: ", "Heute: " }, +//{ "To-Do: %1 }, +//{ "Todo due today color:") }, +//{ "To-do items:"),this) }, +//{ "Todo overdue color:") }, +//{ "Todos"),incidenceGroup) }, +{ "Todo", "Todo" }, +{ "To-do view shows completed Todos", "To-do Anzeige zeigt erledigte To-dos" }, +{ "ToDoView:", "Todo Anzeige:" }, +{ "Toggle Alarm", "Wechsle Alarm" }, +{ "Toggle Allday", "Umschalten Ganztag" }, +//{ "toggle completed To-Dos","Hide/Show Completed") }, +//{ "toggle completed To-Dos","Hide/Show Completed") }, +{ "Tomorrow: ", "Morgen: " }, +// { "Toolbar", "Zugriffsleiste" }, +{ "Tue", "Di" }, +{ "Tuesday", "Dienstag" }, +{ "Two entries are in conflict, if: ", "Zwei Einträge haben einen Konflikt, wenn:" }, +{ "Unable to find template '%1'.", "Kann Vorlage '%1' nicht finden." }, +{ "University", "Universität" }, +{ "Unknown", "Unbekannt" }, +{ "Up", "Hinauf" }, +//{ "&Use email settings from Control Center", " }, +{ "Use password (if not, ask when syncing)", "Passwort: (sonst jedesmal anfragen)" }, +{ "User defined (next page)", "Benutzer definiert (Nächste Seite)" }, +{ "User long date", "Benutz. lang. Datum" }, +{ "User short date", "Benutz. kurz. Datum" }, +//{ "vCalendar")) }, +{ "View", "Ansicht" }, +{ "View", "Anzeige" }, +{ "View Fonts", "Zeige Schriften" }, +{ "Views", "Ansichten" }, +//{ "VIP") }, +{ "Wed", "Mi" }, +{ "Wednesday", "Mittwoch" }, +{ "Week %1", "Woche %1" }, +{ "Weekly", "Wöchentlich" }, +//{ "week(s) on:"), this ) }, +{ "Week starts on Sunday", "Wochenanfang Sonntags" }, +{ "What's Next View:", "What's Next Anzeige" }, +{ "What's next ?", "Was kommt als nächstes?" }, +{ "Working Hours", "Arbeitsstunden" }, +{ "Working hours color:", "Farbe der Arbeitsstunden" }, +{ "Write back existing entries only", "Nur exisitierende Einträge zurückschreiben" }, +{ "Write back synced file", "Syncronisierte Datei zurückschreiben" }, +{ "Yearly", "Jährlich" }, +{ "year(s)", "Jahr(e)" }, +{ "Yes", "Ja" }, +{ "You have %d item(s) selected.\n", "Sie haben %d Einträge ausgewählt.\n" }, +{ "You have to restart KOrganizer for this setting to take effect.","Sie müssem Korganizer neu starten, damit diese Einstellung aktiviert wird." }, +//{ "Zoom In", "Hineinzoomen" }, +//{ "Zoom Out", "Herauszoomen" }, diff --git a/pluginopiekabc/opieaddressbook.cpp b/pluginopiekabc/opieaddressbook.cpp new file mode 100644 index 0000000..ff0ef63 --- a/dev/null +++ b/pluginopiekabc/opieaddressbook.cpp @@ -0,0 +1,33 @@ +#include "opieaddressbook.h" +#include <qstringlist.h> +#include <opie/ocontact.h> +#include <opie/orecordlist.h> +#include <stdio.h> + +using namespace KABC; + +OpieAddressBook *StdOpieAddressBook::mSelf = 0; + +OpieAddressBook::OpieAddressBook() { + access = new OContactAccess("Addressbook"); +} + +OpieAddressBook::~OpieAddressBook() { +} + + +StdOpieAddressBook::StdOpieAddressBook() { + access = new OContactAccess("Addressbook"); +} + +StdOpieAddressBook::~StdOpieAddressBook() { +} + +OpieAddressBook *StdOpieAddressBook::self() { + if ( !mSelf ) { + mSelf = new StdOpieAddressBook(); + } + return mSelf; +} + +
\ No newline at end of file diff --git a/pluginopiekabc/opieaddressbook.h b/pluginopiekabc/opieaddressbook.h new file mode 100644 index 0000000..d2a3b38 --- a/dev/null +++ b/pluginopiekabc/opieaddressbook.h @@ -0,0 +1,63 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KABC_STDADDRESSBOOK_H +#define KABC_STDADDRESSBOOK_H + +#include <opie/ocontactaccess.h> +#include "opieaddressee.h" +#include "opieaddress.h" + +namespace KABC { + +class AddressBook { + + public: + AddressBook(); + ~AddressBook(); + Addressee::List findByEmail( const QString & ); + + protected: + OContactAccess *access; +}; + + +class StdAddressBook : public AddressBook +{ + public: + /** + Return the standard addressbook object. + */ + static AddressBook *self(); + + + protected: + StdAddressBook(); + ~StdAddressBook(); + + void init( bool onlyFastResources ); + + private: + static AddressBook *mSelf; + static bool mAutomaticSave; +}; + +} +#endif diff --git a/pluginopiekabc/opieaddressbookplugin.cpp b/pluginopiekabc/opieaddressbookplugin.cpp new file mode 100644 index 0000000..0b22289 --- a/dev/null +++ b/pluginopiekabc/opieaddressbookplugin.cpp @@ -0,0 +1,71 @@ +#include <stdio.h> +#include <qwidget.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <opie/ocontact.h> +#include <opie/orecordlist.h> +#include "opieaddressbookplugin.h" +#include "opieaddressee.h" + +OpieAddressBookPlugin::OpieAddressBookPlugin() : ref(0) { + + access = new OContactAccess("OpieAddressBookPlugin"); + +} + +KABC::Addressee::List OpieAddressBookPlugin::getAddressees() { + KABC::Addressee::List results; + OContactAccess access("OpieAddressBookPlugin"); + OContactAccess::List::Iterator it; + ORecordList<OContact> accessList = access.sorted(true,0,0,0); + for(it = accessList.begin(); it != accessList.end(); ++it ) { + OpieAddressee addressee( *it ); + results.append(addressee); + } + return results; +} + +QString OpieAddressBookPlugin::name() { + return QString::QString("OpieAddressBookPlugin"); +} + + +KABC::Addressee::List OpieAddressBookPlugin::findByEmail(const QString &email) { +printf("OpieAddressBookPlugin::findByEmail: email=%s\n", email.ascii()); + KABC::Addressee::List results; + + ORecordList<OContact> accessList = access->sorted(true,0,0,0); + OContactAccess::List::Iterator it; + for(it = accessList.begin(); it != accessList.end(); ++it ) { + OContact contact = *it; + QStringList emailList = contact.emailList(); + QStringList foundEmails = emailList.grep(email,false); + if (foundEmails.count() >= 1) { + OpieAddressee a(contact); + printf("Found Contact %s\n", a.formattedName().ascii()); + results.append(a); + } + } + return results; + +} + +QRESULT OpieAddressBookPlugin::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ +printf("Start: OpieAddressBookPlugin::queryInterface\n"); + *iface = 0; + if ( uuid == IID_QUnknown ) + *iface = this; + else if ( uuid == IID_KOAddressBookInterface ) + *iface = this; + if ( *iface ) + (*iface)->addRef(); + return QS_OK; +printf("End: OpieAddressBookPlugin::queryInterface\n"); +} + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( OpieAddressBookPlugin ) +} + diff --git a/pluginopiekabc/opieaddressbookplugin.h b/pluginopiekabc/opieaddressbookplugin.h new file mode 100644 index 0000000..1ad1c15 --- a/dev/null +++ b/pluginopiekabc/opieaddressbookplugin.h @@ -0,0 +1,19 @@ +#include <qwidget.h> +#include <kabc/koaddressbookinterface.h> +#include <kabc/addressee.h> +#include <opie/ocontactaccess.h> + +struct OpieAddressBookPlugin : public KOAddressBookInterface { + + public: + + OpieAddressBookPlugin::OpieAddressBookPlugin(); + QString name(); + KABC::Addressee::List getAddressees(); + KABC::Addressee::List findByEmail(const QString &email); + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + protected: + OContactAccess *access; + ulong ref; +}; diff --git a/pluginopiekabc/opieaddressee.cpp b/pluginopiekabc/opieaddressee.cpp new file mode 100644 index 0000000..3325152 --- a/dev/null +++ b/pluginopiekabc/opieaddressee.cpp @@ -0,0 +1,21 @@ +#include <stdio.h> +#include "opieaddressee.h" + +OpieAddressee::OpieAddressee(const OContact & ocontact) { + setOContact(ocontact); +} + +OpieAddressee::OpieAddressee() { + empty = true; +} + +void OpieAddressee::setOContact(const OContact & ocontact) { + contact = ocontact; + QString id; + id.setNum(contact.uid()); + fName = contact.lastName() + ", " + contact.firstName(); + rName = contact.fullName(); + pEmail = contact.defaultEmail(); + empty = false; +} + diff --git a/pluginopiekabc/opieaddressee.h b/pluginopiekabc/opieaddressee.h new file mode 100644 index 0000000..b0e8b0d --- a/dev/null +++ b/pluginopiekabc/opieaddressee.h @@ -0,0 +1,16 @@ +#include <opie/ocontact.h> +#include <kabc/addressee.h> + +class OpieAddressee : public KABC::Addressee { + + public: + + OpieAddressee::OpieAddressee(const OContact & contact); + OpieAddressee::OpieAddressee(); + void setOContact(const OContact & contact); + + private: + OContact contact; + QString id; + bool empty; +}; diff --git a/pluginopiekabc/pluginopiekabcE.pro b/pluginopiekabc/pluginopiekabcE.pro new file mode 100644 index 0000000..52adaf1 --- a/dev/null +++ b/pluginopiekabc/pluginopiekabcE.pro @@ -0,0 +1,27 @@ +TEMPLATE = lib +CONFIG += qt warn_on release + +TARGET = opiekabc +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc +DESTDIR=$(QPEDIR)/plugins/korganizer +INCLUDEPATH += $(QPEDIR)/include ../libkabcwrap $(OPIEDIR)/include +DEFINES += +LIBS += -L$(QPEDIR)/lib +LIBS += -lmicrokabc +LIBS += -lopie +LIBS += -lqpe +LIBS += -lqte + +INTERFACES = \ + +#select_attendee_base.ui + +HEADERS = \ + opieaddressbookplugin.h \ + opieaddressee.h + +SOURCES = \ + opieaddressbookplugin.cpp \ + opieaddressee.cpp + diff --git a/pluginqtopiakabc/pluginqtopiakabcE.pro b/pluginqtopiakabc/pluginqtopiakabcE.pro new file mode 100644 index 0000000..3f40f9f --- a/dev/null +++ b/pluginqtopiakabc/pluginqtopiakabcE.pro @@ -0,0 +1,23 @@ +TEMPLATE = lib +#TEMPLATE = app +CONFIG += qt warn_on release + +TARGET = qtopiakabc +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc +DESTDIR=$(QPEDIR)/plugins/korganizer +#DESTDIR=. +INCLUDEPATH += ../libkabcwrap $(QPEDIR)/include +DEFINES += +LIBS += -lmicrokabc +LIBS += $(QTOPIALIB) +LIBS += -lqpepim +LIBS += -lqpe + +HEADERS = \ + qtopiaaddressbookplugin.h \ + qtopiaaddressee.h + +SOURCES = \ + qtopiaaddressbookplugin.cpp \ + qtopiaaddressee.cpp diff --git a/pluginqtopiakabc/qtopiaaddressbookplugin.cpp b/pluginqtopiakabc/qtopiaaddressbookplugin.cpp new file mode 100644 index 0000000..59d7881 --- a/dev/null +++ b/pluginqtopiakabc/qtopiaaddressbookplugin.cpp @@ -0,0 +1,57 @@ +#include <qwidget.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qpe/pim/contact.h> +#include <select_addressee_base.h> +#include "qtopiaaddressbookplugin.h" +#include "qtopiaaddressee.h" + +QtopiaAddressBookPlugin::QtopiaAddressBookPlugin() : ref(0) { + qDebug("QtopiaAddressBookPlugin::QtopiaAddressBookPlugin"); + access = new AddressBookAccess(); +} + +QtopiaAddressBookPlugin::~QtopiaAddressBookPlugin() { + qDebug("QtopiaAddressBookPlugin::~QtopiaAddressBookPlugin"); + delete &access; +} + +KABC::Addressee::List QtopiaAddressBookPlugin::getAddressees() { + + qDebug("Start: QtopiaAddressBookPlugin::getAddressees"); + + AddressBookIterator it(*access); + const PimContact *contact; + KABC::Addressee::List result; + + for (contact=it.toFirst(); it.current(); ++it) { + contact = it.current(); + result.append(QtopiaAddressee(*contact)); + } + + qDebug("End: QtopiaAddressBookPlugin::getAddressees"); + + return result; +} + +QString QtopiaAddressBookPlugin::name() { + return "Qtopia addressbook plugin"; +} + +QRESULT QtopiaAddressBookPlugin::queryInterface( const QUuid &uuid, QUnknownInterface **iface ) +{ + *iface = 0; + if ( uuid == IID_QUnknown ) + *iface = this; + else if ( uuid == IID_KOAddressBookInterface ) + *iface = this; + if ( *iface ) + (*iface)->addRef(); + return QS_OK; +} + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE( QtopiaAddressBookPlugin ) +} + diff --git a/pluginqtopiakabc/qtopiaaddressbookplugin.h b/pluginqtopiakabc/qtopiaaddressbookplugin.h new file mode 100644 index 0000000..d197840 --- a/dev/null +++ b/pluginqtopiakabc/qtopiaaddressbookplugin.h @@ -0,0 +1,24 @@ +#ifndef QTOPIA_ADDRESS_BOOK_PLUGIN_H +#define QTOPIA_ADDRESS_BOOK_PLUGIN_H +#include <qpe/pim/addressbookaccess.h> +#include <kabc/koaddressbookinterface.h> +#include <kabc/addressee.h> + + +class QtopiaAddressBookPlugin : public KOAddressBookInterface { + + public: + QtopiaAddressBookPlugin(); + virtual ~QtopiaAddressBookPlugin(); + QString name(); + KABC::Addressee::List getAddressees(); + QRESULT queryInterface( const QUuid&, QUnknownInterface** ); + Q_REFCOUNT + + protected: + ulong ref; + private: + AddressBookAccess *access; +}; +#endif + diff --git a/pluginqtopiakabc/qtopiaaddressee.cpp b/pluginqtopiakabc/qtopiaaddressee.cpp new file mode 100644 index 0000000..3fe85e5 --- a/dev/null +++ b/pluginqtopiakabc/qtopiaaddressee.cpp @@ -0,0 +1,20 @@ +#include "qtopiaaddressee.h" + +QtopiaAddressee::QtopiaAddressee(const PimContact & pimContact) { + setPimContact(pimContact); +} + +QtopiaAddressee::QtopiaAddressee() { + empty = true; +} + +void QtopiaAddressee::setPimContact(const PimContact &pimContact) { + id = pimContact.defaultEmail(); + fName = pimContact.lastName() + ", " + pimContact.firstName(); + rName = pimContact.fullName(); + pEmail = pimContact.defaultEmail(); + empty = false; + mails.clear(); + mails = pimContact.emailList(); +} + diff --git a/pluginqtopiakabc/qtopiaaddressee.h b/pluginqtopiakabc/qtopiaaddressee.h new file mode 100644 index 0000000..c86d6c0 --- a/dev/null +++ b/pluginqtopiakabc/qtopiaaddressee.h @@ -0,0 +1,21 @@ +#include <qpe/pim/contact.h> +#include <kabc/addressee.h> + +#ifndef QTOPIA_ADDRESSE_H +#define QTOPIA_ADDRESSE_H + +class QtopiaAddressee : public KABC::Addressee { + + public: + + QtopiaAddressee(const PimContact & pimContact); + QtopiaAddressee(); + void setPimContact(const PimContact & pimContact); + + private: + QString id; + bool empty; +}; + +#endif + diff --git a/qtcompat/qcombotableitem.cpp b/qtcompat/qcombotableitem.cpp new file mode 100644 index 0000000..348ea24 --- a/dev/null +++ b/qtcompat/qcombotableitem.cpp @@ -0,0 +1,481 @@ +/**************************************************************************** +** +** Implementation of QTable widget class +** +** Created : 000607 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the table module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +/*US +#include "qglobal.h" +#if defined(Q_CC_BOR) +// needed for qsort() because of a std namespace problem on Borland +#include "qplatformdefs.h" +#endif +*/ +#include "qcombotableitem.h" + +#include "qcombobox.h" +#include "qstyle.h" + +/*US + +#ifndef QT_NO_TABLE + +#include "qpainter.h" +#include "qlineedit.h" +#include "qcursor.h" +#include "qapplication.h" +#include "qtimer.h" +#include "qobjectlist.h" +#include "qiconset.h" +#include "qcombobox.h" +#include "qcheckbox.h" +#include "qdragobject.h" +#include "qevent.h" +#include "qlistbox.h" +#include "qstyle.h" + +#include <stdlib.h> +#include <limits.h> + +static bool qt_update_cell_widget = TRUE; + +class QM_EXPORT_TABLE QTableHeader : public QHeader +{ + friend class QTable; + Q_OBJECT + +public: + enum SectionState { + Normal, + Bold, + Selected + }; + + QTableHeader( int, QTable *t, QWidget* parent=0, const char* name=0 ); + ~QTableHeader() {}; + void addLabel( const QString &s, int size ); + void setLabel( int section, const QString & s, int size = -1 ); + void setLabel( int section, const QIconSet & iconset, const QString & s, + int size = -1 ); + void removeLabel( int section ); + + void setSectionState( int s, SectionState state ); + void setSectionStateToAll( SectionState state ); + SectionState sectionState( int s ) const; + + int sectionSize( int section ) const; + int sectionPos( int section ) const; + int sectionAt( int section ) const; + + void setSectionStretchable( int s, bool b ); + bool isSectionStretchable( int s ) const; + + void updateCache(); + +signals: + void sectionSizeChanged( int s ); + +protected: + void paintEvent( QPaintEvent *e ); + void paintSection( QPainter *p, int index, const QRect& fr ); + void mousePressEvent( QMouseEvent *e ); + void mouseMoveEvent( QMouseEvent *e ); + void mouseReleaseEvent( QMouseEvent *e ); + void mouseDoubleClickEvent( QMouseEvent *e ); + void resizeEvent( QResizeEvent *e ); + +private slots: + void doAutoScroll(); + void sectionWidthChanged( int col, int os, int ns ); + void indexChanged( int sec, int oldIdx, int newIdx ); + void updateStretches(); + void updateWidgetStretches(); + +private: + void updateSelections(); + void saveStates(); + void setCaching( bool b ); + void swapSections( int oldIdx, int newIdx, bool swapTable = TRUE ); + bool doSelection( QMouseEvent *e ); + void sectionLabelChanged( int section ); + void resizeArrays( int n ); + +private: + QMemArray<int> states, oldStates; + QMemArray<bool> stretchable; + QMemArray<int> sectionSizes, sectionPoses; + bool mousePressed; + int pressPos, startPos, endPos; + QTable *table; + QTimer *autoScrollTimer; + QWidget *line1, *line2; + bool caching; + int resizedSection; + bool isResizing; + int numStretches; + QTimer *stretchTimer, *widgetStretchTimer; + QTableHeaderPrivate *d; + +}; + +#ifdef _WS_QWS_ +# define NO_LINE_WIDGET +#endif + + + +struct QTablePrivate +{ + QTablePrivate() : hasRowSpan( FALSE ), hasColSpan( FALSE ), + redirectMouseEvent( FALSE ) + { + hiddenRows.setAutoDelete( TRUE ); + hiddenCols.setAutoDelete( TRUE ); + } + uint hasRowSpan : 1; + uint hasColSpan : 1; + uint redirectMouseEvent : 1; + QIntDict<int> hiddenRows, hiddenCols; + QTimer *geomTimer; +}; + +struct QTableHeaderPrivate +{ +#ifdef NO_LINE_WIDGET + int oldLinePos; +#endif +}; + +static bool isRowSelection( QTable::SelectionMode selMode ) +{ + return selMode == QTable::SingleRow || selMode == QTable::MultiRow; +} +*/ + + +/*! + \class QComboTableItem + \brief The QComboTableItem class provides a means of using + comboboxes in QTables. + + \ingroup advanced + \module table + + A QComboTableItem is a table item which looks and behaves like a + combobox. The advantage of using QComboTableItems rather than real + comboboxes is that a QComboTableItem uses far less resources than + real comboboxes in \l{QTable}s. When the cell has the focus it + displays a real combobox which the user can interact with. When + the cell does not have the focus the cell \e looks like a + combobox. Only text items (i.e. no pixmaps) may be used in + QComboTableItems. + + QComboTableItem items have the edit type \c WhenCurrent (see + \l{EditType}). The QComboTableItem's list of items is provided by + a QStringList passed to the constructor. + + The list of items may be changed using setStringList(). The + current item can be set with setCurrentItem() and retrieved with + currentItem(). The text of the current item can be obtained with + currentText(), and the text of a particular item can be retrieved + with text(). + + If isEditable() is TRUE the QComboTableItem will permit the user + to either choose an existing list item, or create a new list item + by entering their own text; otherwise the user may only choose one + of the existing list items. + + To populate a table cell with a QComboTableItem use + QTable::setItem(). + + QComboTableItems may be deleted with QTable::clearCell(). + + QComboTableItems can be distinguished from \l{QTableItem}s and + \l{QCheckTableItem}s using their Run Time Type Identification + number (see rtti()). + + \img qtableitems.png Table Items + + \sa QCheckTableItem QTableItem QComboBox +*/ + +QComboBox *QComboTableItem::fakeCombo = 0; +QWidget *fakeComboWidget = 0; + +/*! + Creates a combo table item for the table \a table. The combobox's + list of items is passed in the \a list argument. If \a editable is + TRUE the user may type in new list items; if \a editable is FALSE + the user may only select from the list of items provided. + + By default QComboTableItems cannot be replaced by other table + items since isReplaceable() returns FALSE by default. + + \sa QTable::clearCell() EditType +*/ + +QComboTableItem::QComboTableItem( QTable *table, const QStringList &list, bool editable ) + : QTableItem( table, WhenCurrent, "" ), entries( list ), current( 0 ), edit( editable ) +{ + setReplaceable( FALSE ); + if ( !fakeCombo ) { + fakeComboWidget = new QWidget( 0, 0 ); + fakeCombo = new QComboBox( FALSE, fakeComboWidget, 0 ); + fakeCombo->hide(); + } +} + +/*! + Sets the list items of this QComboTableItem to the strings in the + string list \a l. +*/ + +void QComboTableItem::setStringList( const QStringList &l ) +{ + entries = l; + current = 0; + if ( table()->cellWidget( row(), col() ) ) { + cb->clear(); + cb->insertStringList( entries ); + } + table()->updateCell( row(), col() ); +} + +/*! \reimp */ + +QWidget *QComboTableItem::createEditor() const +{ + // create an editor - a combobox in our case + ( (QComboTableItem*)this )->cb = new QComboBox( edit, table()->viewport(), "qt_editor_cb" ); + cb->insertStringList( entries ); + cb->setCurrentItem( current ); + QObject::connect( cb, SIGNAL( activated( int ) ), table(), SLOT( doValueChanged() ) ); + return cb; +} + +/*! \reimp */ + +void QComboTableItem::setContentFromEditor( QWidget *w ) +{ + if ( w->inherits( "QComboBox" ) ) { + QComboBox *cb = (QComboBox*)w; + entries.clear(); + for ( int i = 0; i < cb->count(); ++i ) + entries << cb->text( i ); + current = cb->currentItem(); + setText( *entries.at( current ) ); + } +} + +/*! \reimp */ + +void QComboTableItem::paint( QPainter *p, const QColorGroup &cg, + const QRect &cr, bool selected ) +{ + fakeCombo->resize( cr.width(), cr.height() ); + + QColorGroup c( cg ); + if ( selected ) { + c.setBrush( QColorGroup::Base, cg.brush( QColorGroup::Highlight ) ); + c.setColor( QColorGroup::Text, cg.highlightedText() ); + } + +/*US QStyle::SFlags flags = QStyle::Style_Default; + if(isEnabled() && table()->isEnabled()) + flags |= QStyle::Style_Enabled; +*/ +//US table()->style().drawComplexControl( QStyle::CC_ComboBox, p, fakeCombo, fakeCombo->rect(), c, flags ); + + table()->style().drawComboButton(p, fakeCombo->x(), fakeCombo->y(), fakeCombo->width(), fakeCombo->height(), c, FALSE, FALSE, (/*US isEnabled() && */table()->isEnabled()), 0); + p->save(); +/*US + QRect textR = table()->style().querySubControlMetrics(QStyle::CC_ComboBox, fakeCombo, + QStyle::SC_ComboBoxEditField); + +*/ + int align = alignment(); // alignment() changes entries +//US p->drawText( textR, wordWrap() ? ( align | WordBreak ) : align, *entries.at( current ) ); + QRect textR = QRect( fakeCombo->x()+2, fakeCombo->y(), fakeCombo->width()- 17, fakeCombo->height() ); + //qDebug("x %d -- %d wid %d -- %d ", cr.x(),fakeCombo->x(), cr.width(), fakeCombo->width() ); + p->drawText( textR, wordWrap() ? ( align | WordBreak ) : align, *entries.at( current ) ); + p->restore(); +} + +/*! + Sets the list item \a i to be the combo table item's current list + item. + + \sa currentItem() +*/ + +void QComboTableItem::setCurrentItem( int i ) +{ + QWidget *w = table()->cellWidget( row(), col() ); + if ( w && w->inherits( "QComboBox" ) ) { + ( (QComboBox*)w )->setCurrentItem( i ); + current = i; + setText( ( (QComboBox*)w )->currentText() ); + } else { + current = i; + setText( *entries.at( i ) ); + table()->updateCell( row(), col() ); + } +} + +/*! + \overload + + Sets the list item whose text is \a s to be the combo table item's + current list item. Does nothing if no list item has the text \a s. + + \sa currentItem() +*/ + +void QComboTableItem::setCurrentItem( const QString &s ) +{ + int i = entries.findIndex( s ); + if ( i != -1 ) + setCurrentItem( i ); +} + +/*! + Returns the index of the combo table item's current list item. + + \sa setCurrentItem() +*/ + +int QComboTableItem::currentItem() const +{ + QWidget *w = table()->cellWidget( row(), col() ); + if ( w && w->inherits( "QComboBox" ) ) + return ( (QComboBox*)w )->currentItem(); + return current; +} + +/*! + Returns the text of the combo table item's current list item. + + \sa currentItem() text() +*/ + +QString QComboTableItem::currentText() const +{ + QWidget *w = table()->cellWidget( row(), col() ); + if ( w && w->inherits( "QComboBox" ) ) + return ( (QComboBox*)w )->currentText(); + return *entries.at( current ); +} + +/*! + Returns the total number of list items in the combo table item. +*/ + +int QComboTableItem::count() const +{ + QWidget *w = table()->cellWidget( row(), col() ); + if ( w && w->inherits( "QComboBox" ) ) + return ( (QComboBox*)w )->count(); + return (int)entries.count(); //### size_t/int cast +} + +/*! + Returns the text of the combo's list item at index \a i. + + \sa currentText() +*/ + +QString QComboTableItem::text( int i ) const +{ + QWidget *w = table()->cellWidget( row(), col() ); + if ( w && w->inherits( "QComboBox" ) ) + return ( (QComboBox*)w )->text( i ); + return *entries.at( i ); +} + +/*! + If \a b is TRUE the combo table item can be edited, i.e. the user + may enter a new text item themselves. If \a b is FALSE the user may + may only choose one of the existing items. + + \sa isEditable() +*/ + +void QComboTableItem::setEditable( bool b ) +{ + edit = b; +} + +/*! + Returns TRUE if the user can add their own list items to the + combobox's list of items; otherwise returns FALSE. + + \sa setEditable() +*/ + +bool QComboTableItem::isEditable() const +{ + return edit; +} + +int QComboTableItem::RTTI = 1; + +/*! + \fn int QComboTableItem::rtti() const + + Returns 1. + + Make your derived classes return their own values for rtti()to + distinguish between different table item subclasses. You should + use values greater than 1000, preferably a large random number, to + allow for extensions to this class. + + + \sa QTableItem::rtti() +*/ + +int QComboTableItem::rtti() const +{ + return RTTI; +} + +/*! \reimp */ + +QSize QComboTableItem::sizeHint() const +{ + fakeCombo->insertItem( currentText() ); + fakeCombo->setCurrentItem( fakeCombo->count() - 1 ); + QSize sh = fakeCombo->sizeHint(); + fakeCombo->removeItem( fakeCombo->count() - 1 ); +//US return sh.expandedTo( QApplication::globalStrut() ); + return sh; +} + diff --git a/qtcompat/qcombotableitem.h b/qtcompat/qcombotableitem.h new file mode 100644 index 0000000..5688c1c --- a/dev/null +++ b/qtcompat/qcombotableitem.h @@ -0,0 +1,571 @@ +/**************************************************************************** +** +** Definition of QTable widget class +** +** Created : 000607 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the table module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QTCOMPAT_QCOMBOTABLEITEM_H +#define QTCOMPAT_QCOMBOTABLEITEM_H + +#include "qtable.h" +#include "qstringlist.h" + +class QComboBox; +class QWidget; +class QPainter; + +#define QM_EXPORT_TABLE Q_EXPORT + +/*US + +#ifndef QT_H +#include "qscrollview.h" +#include "qpixmap.h" +#include "qptrvector.h" +#include "qheader.h" +#include "qmemarray.h" +#include "qptrlist.h" +#include "qguardedptr.h" +#include "qshared.h" +#include "qintdict.h" +#include "qstringlist.h" +#endif // QT_H + +#ifndef QT_NO_TABLE + +#if !defined( QT_MODULE_TABLE ) || defined( QT_LICENSE_PROFESSIONAL ) || defined( QT_INTERNAL_TABLE ) +#define QM_EXPORT_TABLE +#ifndef QM_TEMPLATE_EXTERN_TABLE +# define QM_TEMPLATE_EXTERN_TABLE +#endif +#else +#define QM_EXPORT_TABLE Q_EXPORT +#define QM_TEMPLATE_EXTERN_TABLE Q_TEMPLATE_EXTERN +#endif + +class QTableHeader; +class QValidator; +class QTable; +class QPaintEvent; +class QTimer; +class QResizeEvent; +class QComboBox; +class QCheckBox; +class QDragObject; + +struct QTablePrivate; +struct QTableHeaderPrivate; + + +class QM_EXPORT_TABLE QTableSelection +{ +public: + QTableSelection(); + QTableSelection( int start_row, int start_col, int end_row, int end_col ); + void init( int row, int col ); + void expandTo( int row, int col ); + bool operator==( const QTableSelection &s ) const; + bool operator!=( const QTableSelection &s ) const { return !(operator==(s)); } + + int topRow() const { return tRow; } + int bottomRow() const { return bRow; } + int leftCol() const { return lCol; } + int rightCol() const { return rCol; } + int anchorRow() const { return aRow; } + int anchorCol() const { return aCol; } + int numRows() const; + int numCols() const; + + bool isActive() const { return active; } + bool isEmpty() const { return numRows() == 0; } + +private: + uint active : 1; + uint inited : 1; + int tRow, lCol, bRow, rCol; + int aRow, aCol; +}; + +#define Q_DEFINED_QTABLE_SELECTION +#include "qwinexport.h" + + +class QM_EXPORT_TABLE QTableItem : public Qt +{ + friend class QTable; + +public: + enum EditType { Never, OnTyping, WhenCurrent, Always }; + + QTableItem( QTable *table, EditType et ); + QTableItem( QTable *table, EditType et, const QString &text ); + QTableItem( QTable *table, EditType et, const QString &text, + const QPixmap &p ); + virtual ~QTableItem(); + + virtual QPixmap pixmap() const; + virtual QString text() const; + virtual void setPixmap( const QPixmap &p ); + virtual void setText( const QString &t ); + QTable *table() const { return t; } + + virtual int alignment() const; + virtual void setWordWrap( bool b ); + bool wordWrap() const; + + EditType editType() const; + virtual QWidget *createEditor() const; + virtual void setContentFromEditor( QWidget *w ); + virtual void setReplaceable( bool ); + bool isReplaceable() const; + + virtual QString key() const; + virtual QSize sizeHint() const; + + virtual void setSpan( int rs, int cs ); + int rowSpan() const; + int colSpan() const; + + virtual void setRow( int r ); + virtual void setCol( int c ); + int row() const; + int col() const; + + virtual void paint( QPainter *p, const QColorGroup &cg, + const QRect &cr, bool selected ); + + void updateEditor( int oldRow, int oldCol ); + + virtual void setEnabled( bool b ); + bool isEnabled() const; + + virtual int rtti() const; + static int RTTI; + +private: + QString txt; + QPixmap pix; + QTable *t; + EditType edType; + uint wordwrap : 1; + uint tcha : 1; + uint enabled : 1; + int rw, cl; + int rowspan, colspan; +#if (QT_VERSION >= 0x040000) +#error "Add a setAlignment() function in 4.0 (but no d pointer)" +#endif +}; + +#define Q_DEFINED_QTABLE_ITEM +#include "qwinexport.h" +*/ +class QM_EXPORT_TABLE QComboTableItem : public QTableItem +{ +public: + QComboTableItem( QTable *table, const QStringList &list, bool editable = FALSE ); + virtual QWidget *createEditor() const; + virtual void setContentFromEditor( QWidget *w ); + virtual void paint( QPainter *p, const QColorGroup &cg, + const QRect &cr, bool selected ); + virtual void setCurrentItem( int i ); + virtual void setCurrentItem( const QString &i ); + int currentItem() const; + QString currentText() const; + int count() const; +#if !defined(Q_NO_USING_KEYWORD) + //using QTableItem::text; +#endif + + + QString text( int i ) const; + virtual void setEditable( bool b ); + bool isEditable() const; + virtual void setStringList( const QStringList &l ); + + int rtti() const; + static int RTTI; + + QSize sizeHint() const; + +private: + QComboBox *cb; + QStringList entries; + int current; + bool edit; + static QComboBox *fakeCombo; + +}; +/*US + +class QM_EXPORT_TABLE QCheckTableItem : public QTableItem +{ +public: + QCheckTableItem( QTable *table, const QString &txt ); + void setText( const QString &t ); + virtual QWidget *createEditor() const; + virtual void setContentFromEditor( QWidget *w ); + virtual void paint( QPainter *p, const QColorGroup &cg, + const QRect &cr, bool selected ); + virtual void setChecked( bool b ); + bool isChecked() const; + + int rtti() const; + static int RTTI; + + QSize sizeHint() const; + +private: + QCheckBox *cb; + bool checked; + +}; + +class QM_EXPORT_TABLE QTable : public QScrollView +{ + Q_OBJECT + Q_ENUMS( SelectionMode FocusStyle ) + Q_PROPERTY( int numRows READ numRows WRITE setNumRows ) + Q_PROPERTY( int numCols READ numCols WRITE setNumCols ) + Q_PROPERTY( bool showGrid READ showGrid WRITE setShowGrid ) + Q_PROPERTY( bool rowMovingEnabled READ rowMovingEnabled WRITE setRowMovingEnabled ) + Q_PROPERTY( bool columnMovingEnabled READ columnMovingEnabled WRITE setColumnMovingEnabled ) + Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) + Q_PROPERTY( bool sorting READ sorting WRITE setSorting ) + Q_PROPERTY( SelectionMode selectionMode READ selectionMode WRITE setSelectionMode ) + Q_PROPERTY( FocusStyle focusStyle READ focusStyle WRITE setFocusStyle ) + Q_PROPERTY( int numSelections READ numSelections ) + + friend class QTableHeader; + friend class QComboTableItem; + friend class QCheckTableItem; + friend class QTableItem; + +public: + QTable( QWidget* parent=0, const char* name=0 ); + QTable( int numRows, int numCols, + QWidget* parent=0, const char* name=0 ); + ~QTable(); + + QHeader *horizontalHeader() const; + QHeader *verticalHeader() const; + + enum SelectionMode { Single, Multi, SingleRow, MultiRow, NoSelection }; + virtual void setSelectionMode( SelectionMode mode ); + SelectionMode selectionMode() const; + + virtual void setItem( int row, int col, QTableItem *item ); + virtual void setText( int row, int col, const QString &text ); + virtual void setPixmap( int row, int col, const QPixmap &pix ); + virtual QTableItem *item( int row, int col ) const; + virtual QString text( int row, int col ) const; + virtual QPixmap pixmap( int row, int col ) const; + virtual void clearCell( int row, int col ); + + virtual QRect cellGeometry( int row, int col ) const; + virtual int columnWidth( int col ) const; + virtual int rowHeight( int row ) const; + virtual int columnPos( int col ) const; + virtual int rowPos( int row ) const; + virtual int columnAt( int x ) const; + virtual int rowAt( int y ) const; + + virtual int numRows() const; + virtual int numCols() const; + + void updateCell( int row, int col ); + + bool eventFilter( QObject * o, QEvent * ); + + int currentRow() const { return curRow; } + int currentColumn() const { return curCol; } + void ensureCellVisible( int row, int col ); + + bool isSelected( int row, int col ) const; + bool isRowSelected( int row, bool full = FALSE ) const; + bool isColumnSelected( int col, bool full = FALSE ) const; + int numSelections() const; + QTableSelection selection( int num ) const; + virtual int addSelection( const QTableSelection &s ); + virtual void removeSelection( const QTableSelection &s ); + virtual void removeSelection( int num ); + virtual int currentSelection() const; + + void selectCells( int start_row, int start_col, int end_row, int end_col ); + void selectRow( int row ); + void selectColumn( int col ); + + bool showGrid() const; + + bool columnMovingEnabled() const; + bool rowMovingEnabled() const; + + virtual void sortColumn( int col, bool ascending = TRUE, + bool wholeRows = FALSE ); + bool sorting() const; + + virtual void takeItem( QTableItem *i ); + + virtual void setCellWidget( int row, int col, QWidget *e ); + virtual QWidget *cellWidget( int row, int col ) const; + virtual void clearCellWidget( int row, int col ); + + virtual QRect cellRect( int row, int col ) const; + + virtual void paintCell( QPainter *p, int row, int col, + const QRect &cr, bool selected ); + virtual void paintCell( QPainter *p, int row, int col, + const QRect &cr, bool selected, const QColorGroup &cg ); + virtual void paintFocus( QPainter *p, const QRect &r ); + QSize sizeHint() const; + + bool isReadOnly() const; + bool isRowReadOnly( int row ) const; + bool isColumnReadOnly( int col ) const; + + void setEnabled( bool b ); + + void repaintSelections(); + + enum FocusStyle { FollowStyle, SpreadSheet }; + virtual void setFocusStyle( FocusStyle fs ); + FocusStyle focusStyle() const; + + void updateHeaderStates(); + +public slots: + virtual void setNumRows( int r ); + virtual void setNumCols( int r ); + virtual void setShowGrid( bool b ); + virtual void hideRow( int row ); + virtual void hideColumn( int col ); + virtual void showRow( int row ); + virtual void showColumn( int col ); + + virtual void setColumnWidth( int col, int w ); + virtual void setRowHeight( int row, int h ); + + virtual void adjustColumn( int col ); + virtual void adjustRow( int row ); + + virtual void setColumnStretchable( int col, bool stretch ); + virtual void setRowStretchable( int row, bool stretch ); + bool isColumnStretchable( int col ) const; + bool isRowStretchable( int row ) const; + virtual void setSorting( bool b ); + virtual void swapRows( int row1, int row2, bool swapHeader = FALSE ); + virtual void swapColumns( int col1, int col2, bool swapHeader = FALSE ); + virtual void swapCells( int row1, int col1, int row2, int col2 ); + + virtual void setLeftMargin( int m ); + virtual void setTopMargin( int m ); + virtual void setCurrentCell( int row, int col ); + void clearSelection( bool repaint = TRUE ); + virtual void setColumnMovingEnabled( bool b ); + virtual void setRowMovingEnabled( bool b ); + + virtual void setReadOnly( bool b ); + virtual void setRowReadOnly( int row, bool ro ); + virtual void setColumnReadOnly( int col, bool ro ); + + virtual void setDragEnabled( bool b ); + bool dragEnabled() const; + + virtual void insertRows( int row, int count = 1 ); + virtual void insertColumns( int col, int count = 1 ); + virtual void removeRow( int row ); + virtual void removeRows( const QMemArray<int> &rows ); + virtual void removeColumn( int col ); + virtual void removeColumns( const QMemArray<int> &cols ); + + virtual void editCell( int row, int col, bool replace = FALSE ); + + void setRowLabels( const QStringList &labels ); + void setColumnLabels( const QStringList &labels ); + +protected: + enum EditMode { NotEditing, Editing, Replacing }; + void drawContents( QPainter *p, int cx, int cy, int cw, int ch ); + void contentsMousePressEvent( QMouseEvent* ); + void contentsMouseMoveEvent( QMouseEvent* ); + void contentsMouseDoubleClickEvent( QMouseEvent* ); + void contentsMouseReleaseEvent( QMouseEvent* ); + void contentsContextMenuEvent( QContextMenuEvent * e ); + void keyPressEvent( QKeyEvent* ); + void focusInEvent( QFocusEvent* ); + void focusOutEvent( QFocusEvent* ); + void viewportResizeEvent( QResizeEvent * ); + void showEvent( QShowEvent *e ); + void paintEvent( QPaintEvent *e ); + void setEditMode( EditMode mode, int row, int col ); +#ifndef QT_NO_DRAGANDDROP + virtual void contentsDragEnterEvent( QDragEnterEvent *e ); + virtual void contentsDragMoveEvent( QDragMoveEvent *e ); + virtual void contentsDragLeaveEvent( QDragLeaveEvent *e ); + virtual void contentsDropEvent( QDropEvent *e ); + virtual QDragObject *dragObject(); + virtual void startDrag(); +#endif + + virtual void paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch ); + virtual void activateNextCell(); + virtual QWidget *createEditor( int row, int col, bool initFromCell ) const; + virtual void setCellContentFromEditor( int row, int col ); + virtual QWidget *beginEdit( int row, int col, bool replace ); + virtual void endEdit( int row, int col, bool accept, bool replace ); + + virtual void resizeData( int len ); + virtual void insertWidget( int row, int col, QWidget *w ); + int indexOf( int row, int col ) const; + + void windowActivationChange( bool ); + bool isEditing() const; + EditMode editMode() const; + int currEditRow() const; + int currEditCol() const; + +protected slots: + virtual void columnWidthChanged( int col ); + virtual void rowHeightChanged( int row ); + virtual void columnIndexChanged( int section, int fromIndex, int toIndex ); + virtual void rowIndexChanged( int section, int fromIndex, int toIndex ); + virtual void columnClicked( int col ); + +signals: + void currentChanged( int row, int col ); + void clicked( int row, int col, int button, const QPoint &mousePos ); + void doubleClicked( int row, int col, int button, const QPoint &mousePos ); + void pressed( int row, int col, int button, const QPoint &mousePos ); + void selectionChanged(); + void valueChanged( int row, int col ); + void contextMenuRequested( int row, int col, const QPoint &pos ); +#ifndef QT_NO_DRAGANDDROP + void dropped( QDropEvent *e ); +#endif + +private slots: + void doAutoScroll(); + void doValueChanged(); + void updateGeometriesSlot(); + +private: + void contentsMousePressEventEx( QMouseEvent* ); + void drawContents( QPainter* ); + void updateGeometries(); + void repaintSelections( QTableSelection *oldSelection, + QTableSelection *newSelection, + bool updateVertical = TRUE, + bool updateHorizontal = TRUE ); + QRect rangeGeometry( int topRow, int leftCol, + int bottomRow, int rightCol, bool &optimize ); + void fixRow( int &row, int y ); + void fixCol( int &col, int x ); + + void init( int numRows, int numCols ); + QSize tableSize() const; + void repaintCell( int row, int col ); + void contentsToViewport2( int x, int y, int& vx, int& vy ); + QPoint contentsToViewport2( const QPoint &p ); + void viewportToContents2( int vx, int vy, int& x, int& y ); + QPoint viewportToContents2( const QPoint &p ); + + void updateRowWidgets( int row ); + void updateColWidgets( int col ); + bool isSelected( int row, int col, bool includeCurrent ) const; + void setCurrentCell( int row, int col, bool updateSelections ); + void fixCell( int &row, int &col, int key ); + void delayedUpdateGeometries(); + struct TableWidget + { + TableWidget( QWidget *w, int r, int c ) : wid( w ), row( r ), col ( c ) {} + QWidget *wid; + int row, col; + }; + void saveContents( QPtrVector<QTableItem> &tmp, + QPtrVector<TableWidget> &tmp2 ); + void updateHeaderAndResizeContents( QTableHeader *header, + int num, int colRow, + int width, bool &updateBefore ); + void restoreContents( QPtrVector<QTableItem> &tmp, + QPtrVector<TableWidget> &tmp2 ); + void finishContentsResze( bool updateBefore ); + +private: + QPtrVector<QTableItem> contents; + QPtrVector<QWidget> widgets; + int curRow; + int curCol; + QTableHeader *leftHeader, *topHeader; + EditMode edMode; + int editCol, editRow; + QPtrList<QTableSelection> selections; + QTableSelection *currentSel; + QTimer *autoScrollTimer; + int lastSortCol; + bool sGrid : 1; + bool mRows : 1; + bool mCols : 1; + bool asc : 1; + bool doSort : 1; + bool mousePressed : 1; + bool readOnly : 1; + bool shouldClearSelection : 1; + bool dEnabled : 1; + bool context_menu : 1; + bool drawActiveSelection : 1; + bool was_visible : 1; + SelectionMode selMode; + int pressedRow, pressedCol; + QTablePrivate *d; + QIntDict<int> roRows; + QIntDict<int> roCols; + int startDragRow; + int startDragCol; + QPoint dragStartPos; + int oldCurrentRow, oldCurrentCol; + QWidget *unused_topLeftCorner; //### remove in 4.0 + FocusStyle focusStl; + QSize unused_cachedSizeHint; // ### remove in 4.0 + +#if defined(Q_DISABLE_COPY) + QTable( const QTable & ); + QTable &operator=( const QTable & ); +#endif +}; + +#define Q_DEFINED_QTABLE +#include "qwinexport.h" +#endif // QT_NO_TABLE + +*/ +#endif // QTCOMPAT_QCOMBOTABLEITEM_H diff --git a/qtcompat/qgridview.cpp b/qtcompat/qgridview.cpp new file mode 100644 index 0000000..bee3698 --- a/dev/null +++ b/qtcompat/qgridview.cpp @@ -0,0 +1,362 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QGridView class +** +** Created: 010523 +** +** Copyright (C) 1992-2001 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + + +#include "qgridview.h" + +#ifndef QT_NO_GRIDVIEW + +#include "qpainter.h" + +/*! + \class QGridView qgridview.h + \brief The QGridView class provides an abstract base for fixed-size + grids. + + \ingroup abstractwidgets + + A grid view consists of a number of abstract cells organized in rows + and columns. The cells have a fixed size and are identified with a + row index and a column index. The top-left cell is in row 0, column + 0. The bottom-right cell is in row numRows()-1, column numCols()-1. + + You can define \l numRows, \l numCols, \l cellWidth and + \l cellHeight. Reimplement the pure virtual function paintCell() to + draw the content of a cell. + + With ensureCellVisible(), you can ensure a certain cell is + visible. With rowAt() and columnAt() you can find a cell based on + the given x- and y-coordinates. + + If you need to monitor changes to the grid's dimensions (i.e. when + numRows or numCols is changed), reimplement the dimensionChange() + change handler. + + Note: the row, column indices are always given in the order, row + (vertical offset) then column (horizontal offset). This order is the + opposite of all pixel operations, which are given in the order x + (horizontal offset), y (vertical offset). + + QGridView is a very simple abstract class based on QScrollView. It + is designed to simplify the task of drawing many cells of the same + size in a potentially scrollable canvas. If you need rows and + columns in different sizes, use a QTable instead. If you need a + simple list of items, use a QListBox. If you need to present + hierachical data use a QListView, and if you need random objects at + random positions, consider using either a QIconView or a QCanvas. + +*/ + + +/*! + Constructs a grid view. + + The \a parent, \a name and widget flag, \a f, arguments are passed to the + QScrollView constructor. +*/ +QGridView::QGridView( QWidget *parent, const char *name, WFlags f ) + :QScrollView( parent, name ,f ),nrows(5),ncols(5),cellw(12),cellh(12) +{ + viewport()->setBackgroundMode( PaletteBase ); + setBackgroundMode( PaletteBackground ); + viewport()->setFocusProxy( this ); +} + +/*! + Destroys the grid view. +*/ +QGridView::~QGridView() +{ +} + +void QGridView::updateGrid() +{ + resizeContents( ncols * cellw, nrows * cellh ); +} + +/*! \property QGridView::numRows + \brief The number of rows in the grid + + \sa numCols +*/ +void QGridView::setNumRows( int numRows ) +{ + int oldnrows = nrows; + nrows = numRows; + dimensionChange( oldnrows, ncols ); + updateGrid(); +} + +/*! \property QGridView::numCols + \brief The number of columns in the grid + + \sa numRows +*/ +void QGridView::setNumCols( int numCols ) +{ + int oldncols = ncols; + ncols = numCols; + dimensionChange( nrows, oldncols ); + updateGrid(); +} + +/*! \property QGridView::cellWidth + \brief The width of a grid column + + All columns in a grid view have the same width. + + \sa cellHeight +*/ +void QGridView::setCellWidth( int cellWidth ) +{ + cellw = cellWidth; + updateGrid(); + updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); +} + +/*! \property QGridView::cellHeight + \brief The height of a grid row + + All rows in a grid view have the same height. + + \sa cellWidth +*/ +void QGridView::setCellHeight( int cellHeight ) +{ + cellh = cellHeight; + updateGrid(); + updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); +} + +/*! + Returns the geometry of cell (\a row, \a column) in the content + coordinate system. + + \sa cellRect() + */ +QRect QGridView::cellGeometry( int row, int column ) +{ + QRect r; + if ( row >= 0 && row < nrows && column >= 0 && column < ncols ) + r.setRect( cellw * column, cellh * row, cellw, cellh ); + return r; +} + +/*! Repaints cell (\a row, \a column). + + If \a erase is TRUE, Qt erases the area of the cell before the + paintCell() call; otherwise no erasing takes place. + + \sa QWidget::repaint() + */ +void QGridView::repaintCell( int row, int column, bool erase ) +{ + QScrollView::repaintContents( cellGeometry( row, column ), erase ); +} + +/*! Updates cell (\a row, \a column). + + \sa QWidget::update() + */ +void QGridView::updateCell( int row, int column ) +{ + updateContents( cellGeometry( row, column ) ); +} + +/*! + Ensure cell (\a row, \a column) is visible, scrolling the grid view + if necessary. + */ +void QGridView::ensureCellVisible( int row, int column ) +{ + QRect r = cellGeometry( row, column ); + ensureVisible( r.x(), r.y(), r.width(), r.height() ); +} + +/*! This function fills the \a cw pixels wide and \a ch pixels high + rectangle starting at position (\a cx, \a cy) with the + background color using the painter \a p. + + paintEmptyArea() is invoked by drawContents() to erase + or fill unused areas. +*/ + +void QGridView::paintEmptyArea( QPainter *p, int cx ,int cy, int cw, int ch) +{ + if ( gridSize().width() >= contentsWidth() && gridSize().height() >= contentsHeight() ) + return; + // Region of the rect we should draw + contentsToViewport( cx, cy, cx, cy ); + QRegion reg( QRect( cx, cy, cw, ch ) ); + // Subtract the table from it + reg = reg.subtract( QRect( contentsToViewport( QPoint( 0, 0 ) ), gridSize() ) ); + + // And draw the rectangles (transformed as needed) + QArray<QRect> r = reg.rects(); + QBrush brush = colorGroup().brush( QColorGroup::Background ); + for ( int i = 0; i < (int)r.count(); ++i) + p->fillRect( r[ i ], brush ); +} + +/*!\reimp + */ +void QGridView::drawContents( QPainter *p, int cx, int cy, int cw, int ch ) +{ + int colfirst = columnAt( cx ); + int collast = columnAt( cx + cw ); + int rowfirst = rowAt( cy ); + int rowlast = rowAt( cy + ch ); + + if ( rowfirst == -1 || colfirst == -1 ) { + paintEmptyArea( p, cx, cy, cw, ch ); + return; + } + + if ( collast < 0 || collast >= ncols ) + collast = ncols-1; + if ( rowlast < 0 || rowlast >= nrows ) + rowlast = nrows-1; + + // Go through the rows + for ( int r = rowfirst; r <= rowlast; ++r ) { + // get row position and height + int rowp = r * cellh; + + // Go through the columns in the row r + // if we know from where to where, go through [colfirst, collast], + // else go through all of them + for ( int c = colfirst; c <= collast; ++c ) { + // get position and width of column c + int colp = c * cellw; + // Translate painter and draw the cell + p->translate( colp, rowp ); + paintCell( p, r, c ); + p->translate( -colp, -rowp ); + } + } + + // Paint empty rects + paintEmptyArea( p, cx, cy, cw, ch ); +} + +/*! + \reimp + + (Implemented to get rid of a compiler warning.) +*/ +void QGridView::drawContents( QPainter * ) +{ +} + +/*! \fn void QGridView::dimensionChange( int oldNumRows, int oldNumCols ) + + This change handler is called whenever any of the grid's dimensions + changes. \a oldNumRows and \a oldNumCols contain the old dimensions, + numRows() and numCols() contain the new dimensions. + */ +void QGridView::dimensionChange( int, int ) {} + + + +/*! \fn int QGridView::rowAt( int y ) const + + Returns the number of the row at position \a y. \a y must be given in + content coordinates. + + \sa columnAt() + */ + +/*! \fn int QGridView::columnAt( int x ) const + + Returns the number of the column at position \a x. \a x must be + given in content coordinates. + + \sa rowAt() + */ + +/*! + \fn void QGridView::paintCell( QPainter *p, int row, int col ) + + This pure virtual function is called to paint the single cell at + (\a row, \a col) using painter \a p. The painter must be open when + paintCell() is called and must remain open. + + The coordinate system is \link QPainter::translate() translated \endlink + so that the origin is at the top-left corner of the cell to be + painted, i.e. \e cell coordinates. Do not scale or shear the coordinate + system (or if you do, restore the transformation matrix before you + return). + + The painter is not clipped by default in order to get maximum + efficiency. If you want clipping, use + + \code + p->setClipRect( cellRect(), QPainter::CoordPainter ); + //... your drawing code + p->setClipping( FALSE ); + + \endcode + +*/ + +/*! \fn QRect QGridView::cellRect() const + + Returns the geometry of a cell in a cell's coordinate system. This + is a convenience function useful in paintCell(). It is equivalent to + QRect( 0, 0, cellWidth(), cellHeight() ). + + \sa cellGeometry() + + */ + +/*!\fn QSize QGridView::gridSize() const + + Returns the size of the grid in pixels. + + */ + +/*! + \overload + Repaints the contents. If \a erase is TRUE the + background is cleared using the background color. +*/ +void QGridView::repaintContents( bool erase ) +{ + QScrollView::repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), erase ); +} + +#endif // QT_NO_GRIDVIEW diff --git a/qtcompat/qgridview.h b/qtcompat/qgridview.h new file mode 100644 index 0000000..e9d6ca1 --- a/dev/null +++ b/qtcompat/qgridview.h @@ -0,0 +1,138 @@ +/********************************************************************** +** $Id$ +** +** Definition of QGridView class +** +** Created: 2001.05.23 +** +** Copyright (C) 1992-2001 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QGRIDVIEW_H +#define QGRIDVIEW_H + +#ifndef QT_H +#include "qscrollview.h" +#endif // QT_H + +#ifndef QT_NO_GRIDVIEW + +class QGridViewPrivate; + +class Q_EXPORT QGridView : public QScrollView +{ + Q_OBJECT + Q_PROPERTY( int numRows READ numRows WRITE setNumRows ) + Q_PROPERTY( int numCols READ numCols WRITE setNumCols ) + Q_PROPERTY( int cellWidth READ cellWidth WRITE setCellWidth ) + Q_PROPERTY( int cellHeight READ cellHeight WRITE setCellHeight ) +public: + + QGridView( QWidget *parent=0, const char *name=0, WFlags f=0 ); + ~QGridView(); + + int numRows() const; + virtual void setNumRows( int ); + int numCols() const; + virtual void setNumCols( int ); + + int cellWidth() const; + virtual void setCellWidth( int ); + int cellHeight() const; + virtual void setCellHeight( int ); + + QRect cellRect() const; + QRect cellGeometry( int row, int column ); + QSize gridSize() const; + + int rowAt( int y ) const; + int columnAt( int x ) const; + + void repaintCell( int row, int column, bool erase=TRUE ); + void updateCell( int row, int column ); + void ensureCellVisible( int row, int column ); + + void repaintContents( bool erase=TRUE ); + +protected: + virtual void paintCell( QPainter *, int row, int col ) = 0; + virtual void paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch ); + + void drawContents( QPainter *p, int cx, int cy, int cw, int ch ); + + virtual void dimensionChange( int, int ); + +private: + void drawContents( QPainter* ); + void updateGrid(); + + int nrows; + int ncols; + int cellw; + int cellh; + QGridViewPrivate* d; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QGridView( const QGridView & ); + QGridView &operator=( const QGridView & ); +#endif +}; + +inline int QGridView::cellWidth() const +{ return cellw; } + +inline int QGridView::cellHeight() const +{ return cellh; } + +inline int QGridView::rowAt( int y ) const +{ return y / cellh; } + +inline int QGridView::columnAt( int x ) const +{ return x / cellw; } + +inline int QGridView::numRows() const +{ return nrows; } + +inline int QGridView::numCols() const +{return ncols; } + +inline QRect QGridView::cellRect() const +{ return QRect( 0, 0, cellw, cellh ); } + +inline QSize QGridView::gridSize() const +{ return QSize( ncols * cellw, nrows * cellh ); } + + + +#endif // QT_NO_GRIDVIEW + + +#endif // QTABLEVIEW_H diff --git a/qtcompat/qinputdialog.cpp b/qtcompat/qinputdialog.cpp new file mode 100644 index 0000000..770b281 --- a/dev/null +++ b/qtcompat/qinputdialog.cpp @@ -0,0 +1,495 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QInputDialog class +** +** Created : 991212 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the dialogs module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qinputdialog.h" + +#include <qlayout.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qpushbutton.h> +#include <qspinbox.h> +#include <qcombobox.h> +#include <qwidgetstack.h> +#include <qvalidator.h> +#include <qapplication.h> + +class QInputDialogPrivate +{ +public: + friend class QInputDialog; + QLineEdit *lineEdit; + QSpinBox *spinBox; + QComboBox *comboBox, *editComboBox; + QPushButton *ok; + QWidgetStack *stack; + QInputDialog::Type type; +}; + +/*! + \class QInputDialog qinputdialog.h + \brief A convenience dialog to get a simple input from the user + \ingroup dialogs + + The QInputDialog is a simple dialog which can be used if you + need a simple input from the user. This can be text, a number or + an item from a list. Also a label has to be set to tell the user + what he/she should input. + + In this Qt version only the 4 static convenience functions + getText(), getInteger(), getDouble() and getItem() of QInputDialog + are available. + + Use it like this: + + \code + bool ok = FALSE; + QString text = QInputDialog::getText( tr( "Make an input" ), tr( "Please enter your name" ), QString::null, &ok, this ); + if ( ok && !text.isEmpty() ) + ;// user entered something and pressed ok + else + ;// user entered nothing or pressed cancel + \endcode + + There are more static convenience methods! + + \sa getText(), getInteger(), getDouble(), getItem() +*/ + +/*! + \enum QInputDialog::Type + + This enum type specifies the type of the dialog + (which kind of input can be done): + + <ul> + <li>\c LineEdit - A QLineEdit is used for taking the input, so a textual or + (e.g. using a QValidator) a numerical input can be done. Using lineEdit() + the QLineEdit can be accessed. + <li>\c SpinBox - A QSpinBox is used for taking the input, so a decimal + input can be done. Using spinBox() the QSpinBox can be accessed. + <li>\c ComboBox - A read-only QComboBox is used for taking the input, + so one item of a list can be chosen. Using comboBox() the QComboBox + can be accessed. + <li>\c EditableComboBox - An editable QComboBox is used for taking the input, + so either one item of a list can be chosen or a text can be entered. Using + editableComboBox() the QComboBox can be accessed. + </ul> +*/ + +/*! + Constructs the dialog. \a label is the text which is shown to the user (it should mention + to the user what he/she should input), \a parent the parent widget of the dialog, \a name + the name of it and if you set \a modal to TRUE, the dialog pops up modally, else it pops + up modeless. With \a type you specify the type of the dialog. + + \sa getText(), getInteger(), getDouble(), getItem() +*/ + +QInputDialog::QInputDialog( const QString &label, QWidget* parent, const char* name, + bool modal, Type type) + : QDialog( parent, name, modal ) +{ + if ( parent && parent->icon() &&!parent->icon()->isNull() ) + setIcon( *parent->icon() ); + else if ( qApp->mainWidget() && qApp->mainWidget()->icon() && !qApp->mainWidget()->icon()->isNull() ) + QDialog::setIcon( *qApp->mainWidget()->icon() ); + + d = new QInputDialogPrivate; + d->lineEdit = 0; + d->spinBox = 0; + d->comboBox = 0; + + QVBoxLayout *vbox = new QVBoxLayout( this, 6, 6 ); + + QLabel* l = new QLabel( label, this ); + vbox->addWidget( l ); + + d->stack = new QWidgetStack( this ); + vbox->addWidget( d->stack ); + d->lineEdit = new QLineEdit( d->stack ); + d->spinBox = new QSpinBox( d->stack ); + d->comboBox = new QComboBox( FALSE, d->stack ); + d->editComboBox = new QComboBox( TRUE, d->stack ); + + QHBoxLayout *hbox = new QHBoxLayout( 6 ); + vbox->addLayout( hbox, AlignRight ); + + d->ok = new QPushButton( tr( "&OK" ), this ); + d->ok->setDefault( TRUE ); + QPushButton *cancel = new QPushButton( tr( "&Cancel" ), this ); + + QSize bs( d->ok->sizeHint() ); + if ( cancel->sizeHint().width() > bs.width() ) + bs.setWidth( cancel->sizeHint().width() ); + + d->ok->setFixedSize( bs ); + cancel->setFixedSize( bs ); + + hbox->addWidget( new QWidget( this ) ); + hbox->addWidget( d->ok ); + hbox->addWidget( cancel ); + + connect( d->lineEdit, SIGNAL( returnPressed() ), + this, SLOT( tryAccept() ) ); + connect( d->lineEdit, SIGNAL( textChanged( const QString & ) ), + this, SLOT( textChanged( const QString & ) ) ); + + connect( d->ok, SIGNAL( clicked() ), this, SLOT( accept() ) ); + connect( cancel, SIGNAL( clicked() ), this, SLOT( reject() ) ); + +//US ToDo make size dependent of targetplatform +//US resize( QMAX( sizeHint().width(), 400 ), sizeHint().height() ); + resize( sizeHint().width(), sizeHint().height() ); + + setType( type ); +} + +/*! + Returns the line edit, which is used in the LineEdit mode +*/ + +QLineEdit *QInputDialog::lineEdit() const +{ + return d->lineEdit; +} + +/*! + Returns the spinbox, which is used in the SpinBox mode +*/ + +QSpinBox *QInputDialog::spinBox() const +{ + return d->spinBox; +} + +/*! + Returns the combobox, which is used in the ComboBox mode +*/ + +QComboBox *QInputDialog::comboBox() const +{ + return d->comboBox; +} + +/*! + Returns the combobox, which is used in the EditableComboBox mode +*/ + +QComboBox *QInputDialog::editableComboBox() const +{ + return d->editComboBox; +} + +/*! + Sets the input type of the dialog to \a t. +*/ + +void QInputDialog::setType( Type t ) +{ + switch ( t ) { + case LineEdit: + d->stack->raiseWidget( d->lineEdit ); + d->lineEdit->setFocus(); + break; + case SpinBox: + d->stack->raiseWidget( d->spinBox ); + d->spinBox->setFocus(); + break; + case ComboBox: + d->stack->raiseWidget( d->comboBox ); + d->comboBox->setFocus(); + break; + case EditableComboBox: + d->stack->raiseWidget( d->editComboBox ); + d->editComboBox->setFocus(); + break; + } + + d->type = t; +} + +/*! + Returns the input type of the dialog. + + \sa setType() +*/ + +QInputDialog::Type QInputDialog::type() const +{ + return d->type; +} + +/*! + Destructor. +*/ + +QInputDialog::~QInputDialog() +{ + delete d; +} + +/*! + Static convenience function to get a textual input from the user. \a caption is the text + which is displayed in the title bar of the dialog. \a label is the text which + is shown to the user (it should mention to the user what he/she should input), \a text + the default text which will be initially set to the line edit, \a ok a pointer to + a bool which will be (if not 0!) set to TRUE if the user pressed ok or to FALSE if the + user pressed cancel, \a parent the parent widget of the dialog and \a name + the name of it. The dialogs pops up modally! + + This method returns the text which has been entered in the line edit. + + You will use this static method like this: + + \code + bool ok = FALSE; + QString text = QInputDialog::getText( tr( "Please enter your name" ), QString::null, &ok, this ); + if ( ok && !text.isEmpty() ) + ;// user entered something and pressed ok + else + ;// user entered nothing or pressed cancel + \endcode +*/ + +QString QInputDialog::getText( const QString &caption, const QString &label, const QString &text, + bool *ok, QWidget *parent, const char *name ) +{ + return getText( caption, label, QLineEdit::Normal, text, ok, parent, name ); +} + +/*! + Like above, but accepts an a \a mode which the line edit will use to display text. + + \sa getText() +*/ + +QString QInputDialog::getText( const QString &caption, const QString &label, QLineEdit::EchoMode mode, + const QString &text, bool *ok, QWidget *parent, const char *name ) +{ + QInputDialog *dlg = new QInputDialog( label, parent, name, TRUE, LineEdit ); + dlg->setCaption( caption ); + dlg->lineEdit()->setText( text ); + dlg->lineEdit()->setEchoMode( mode ); + if ( !text.isEmpty() ) + dlg->lineEdit()->selectAll(); + + bool ok_ = FALSE; + QString result; + ok_ = dlg->exec() == QDialog::Accepted; + if ( ok ) + *ok = ok_; + if ( ok_ ) + result = dlg->lineEdit()->text(); + + delete dlg; + return result; +} + +/*! + Static convenience function to get an integral input from the user. \a caption is the text + which is displayed in the title bar of the dialog. \a label is the text which + is shown to the user (it should mention to the user what he/she should input), \a num + the default number which will be initially set to the spinbox, \a from and \a to the + range in which the entered number has to be, \a step the step in which the number can + be increased/decreased by the spinbox, \a ok a pointer to + a bool which will be (if not 0!) set to TRUE if the user pressed ok or to FALSE if the + user pressed cancel, \a parent the parent widget of the dialog and \a name + the name of it. The dialogs pops up modally! + + This method returns the number which has been entered by the user. + + You will use this static method like this: + + \code + bool ok = FALSE; + int res = QInputDialog::getInteger( tr( "Please enter a number" ), 22, 0, 1000, 2, &ok, this ); + if ( ok ) + ;// user entered something and pressed ok + else + ;// user pressed cancel + \endcode +*/ + +int QInputDialog::getInteger( const QString &caption, const QString &label, int num, int from, int to, int step, + bool *ok, QWidget *parent, const char *name ) +{ + QInputDialog *dlg = new QInputDialog( label, parent, name, TRUE, SpinBox ); + dlg->setCaption( caption ); + dlg->spinBox()->setRange( from, to ); + dlg->spinBox()->setSteps( step, 0 ); + dlg->spinBox()->setValue( num ); + + bool ok_ = FALSE; + int result; + ok_ = dlg->exec() == QDialog::Accepted; + if ( ok ) + *ok = ok_; + result = dlg->spinBox()->value(); + + delete dlg; + return result; +} + +/*! + Static convenience function to get a decimal input from the user. \a caption is the text + which is displayed in the title bar of the dialog. \a label is the text which + is shown to the user (it should mention to the user what he/she should input), \a num + the default decimal number which will be initially set to the line edit, \a from and \a to the + range in which the entered number has to be, \a decimals the number of decimal which + the number may have, \a ok a pointer to + a bool which will be (if not 0!) set to TRUE if the user pressed ok or to FALSE if the + user pressed cancel, \a parent the parent widget of the dialog and \a name + the name of it. The dialogs pops up modally! + + This method returns the number which has been entered by the user. + + You will use this static method like this: + + \code + bool ok = FALSE; + double res = QInputDialog::getDouble( tr( "Please enter a decimal number" ), 33.7, 0, 1000, 2, &ok, this ); + if ( ok ) + ;// user entered something and pressed ok + else + ;// user pressed cancel + \endcode +*/ + +double QInputDialog::getDouble( const QString &caption, const QString &label, double num, + double from, double to, int decimals, + bool *ok, QWidget *parent, const char *name ) +{ + QInputDialog *dlg = new QInputDialog( label, parent, name, TRUE, LineEdit ); + dlg->setCaption( caption ); + dlg->lineEdit()->setValidator( new QDoubleValidator( from, to, decimals, dlg->lineEdit() ) ); + dlg->lineEdit()->setText( QString::number( num, 'f', decimals ) ); + dlg->lineEdit()->selectAll(); + + bool accepted = ( dlg->exec() == QDialog::Accepted ); + if ( ok ) + *ok = accepted; + + double result = dlg->lineEdit()->text().toDouble(); + + delete dlg; + return result; +} + +/*! + Static convenience function to let the user select an item from a string list. \a caption is the text + which is displayed in the title bar of the dialog. \a label is the text which + is shown to the user (it should mention to the user what he/she should input), \a list the + string list which is inserted into the combobox, \a current the number of the item which should + be initially the current item, \a editable specifies if the combobox should be editable (if it is TRUE) + or read-only (if \a editable is FALSE), \a ok a pointer to + a bool which will be (if not 0!) set to TRUE if the user pressed ok or to FALSE if the + user pressed cancel, \a parent the parent widget of the dialog and \a name + the name of it. The dialogs pops up modally! + + This method returns the text of the current item, or if \a editable was TRUE, the current + text of the combobox. + + You will use this static method like this: + + \code + QStringList lst; + lst << "First" << "Second" << "Third" << "Fourth" << "Fifth"; + bool ok = FALSE; + QString res = QInputDialog::getItem( tr( "Please select an item" ), lst, 1, TRUE, &ok, this ); + if ( ok ) + ;// user selected an item and pressed ok + else + ;// user pressed cancel + \endcode +*/ + +QString QInputDialog::getItem( const QString &caption, const QString &label, const QStringList &list, + int current, bool editable, + bool *ok, QWidget *parent, const char *name ) +{ + QInputDialog *dlg = new QInputDialog( label, parent, name, TRUE, editable ? EditableComboBox : ComboBox ); + dlg->setCaption( caption ); + if ( editable ) { + dlg->editableComboBox()->insertStringList( list ); + dlg->editableComboBox()->setCurrentItem( current ); + } else { + dlg->comboBox()->insertStringList( list ); + dlg->comboBox()->setCurrentItem( current ); + } + + bool ok_ = FALSE; + QString result; + ok_ = dlg->exec() == QDialog::Accepted; + if ( ok ) + *ok = ok_; + if ( editable ) + result = dlg->editableComboBox()->currentText(); + else + result = dlg->comboBox()->currentText(); + + delete dlg; + return result; +} + +/*! + \internal +*/ + +void QInputDialog::textChanged( const QString &s ) +{ + bool on; + if ( d->lineEdit->validator() ) { + QString str = d->lineEdit->text(); + int index = d->lineEdit->cursorPosition(); + on = ( d->lineEdit->validator()->validate(str, index) == + QValidator::Acceptable ); + } else { + on = !s.isEmpty(); + } + d->ok->setEnabled( on ); +} + +/*! + \internal +*/ + +void QInputDialog::tryAccept() +{ + if ( !d->lineEdit->text().isEmpty() ) + accept(); +} + diff --git a/qtcompat/qinputdialog.h b/qtcompat/qinputdialog.h new file mode 100644 index 0000000..3ff5b58 --- a/dev/null +++ b/qtcompat/qinputdialog.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QInputDialog class +** +** Created : 991212 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the dialogs module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef QTCOMPAT_QINPUTDIALOG_H +#define QTCOMPAT_QINPUTDIALOG_H + +#ifndef QT_H +#include <qdialog.h> +#include <qstring.h> +#include <qlineedit.h> +#endif // QT_H + +class QInputDialogPrivate; + +class QSpinBox; +class QComboBox; + +class Q_EXPORT QInputDialog : public QDialog +{ +#if defined(_CC_MSVC_) + friend class QInputDialog; +#endif + Q_OBJECT + +private: + enum Type { LineEdit, SpinBox, ComboBox, EditableComboBox }; + + QInputDialog( const QString &label, QWidget* parent = 0, const char* name = 0, + bool modal = TRUE, Type type = LineEdit ); + ~QInputDialog(); + + QLineEdit *lineEdit() const; + QSpinBox *spinBox() const; + QComboBox *comboBox() const; + QComboBox *editableComboBox() const; + + void setType( Type t ); + Type type() const; + +public: + static QString getText( const QString &caption, const QString &label, const QString &text = QString::null, + bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); // ### merge with below in 3.0 + static QString getText( const QString &caption, const QString &label, QLineEdit::EchoMode echo, //### make default Normal in 3.0 + const QString &text = QString::null, bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); + + static int getInteger( const QString &caption, const QString &label, int num = 0, int from = -2147483647, + int to = 2147483647, + int step = 1, bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); + static double getDouble( const QString &caption, const QString &label, double num = 0, + double from = -2147483647, double to = 2147483647, + int decimals = 1, bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); + static QString getItem( const QString &caption, const QString &label, const QStringList &list, + int current = 0, bool editable = TRUE, + bool *ok = 0, QWidget *parent = 0, const char *name = 0 ); + +private slots: + void textChanged( const QString &s ); + void tryAccept(); + +private: + QInputDialogPrivate *d; + // just to avoid warnings... + friend class QInputDialogPrivate; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QInputDialog( const QInputDialog & ); + QInputDialog &operator=( const QInputDialog & ); +#endif +}; + +#endif // QTCOMPAT_QINPUTDIALOG_H diff --git a/qtcompat/qinputdialog.h.wech b/qtcompat/qinputdialog.h.wech new file mode 100644 index 0000000..47a332b --- a/dev/null +++ b/qtcompat/qinputdialog.h.wech @@ -0,0 +1,14 @@ +#ifndef MICROKDE_QINPUTDIALOG_H +#define MICROKDE_QINPUTDIALOG_H + +class QInputDialog +{ + public: + + static QString getText( const QString &, const QString & ) + { + return QString::null; + } +}; + +#endif diff --git a/qtcompat/qksplitter.h b/qtcompat/qksplitter.h new file mode 100644 index 0000000..b62c65e --- a/dev/null +++ b/qtcompat/qksplitter.h @@ -0,0 +1,23 @@ +#ifndef QTCOMPAT_QSPLITTER_H +#define QTCOMPAT_QSPLITTER_H + +#include <qwidget.h> + +class QKSplitter : public QWidget +{ + public: + enum { KeepSize }; + + QKSplitter (int, QWidget *parent=0, const char *name=0) : + QWidget( parent, name ) {} + QKSplitter( QWidget *parent=0, const char *name=0 ) : + QWidget( parent, name ) {} + + void setResizeMode( QWidget *, int ) {} + void setOpaqueResize() {} + + void setSizes (const QValueList<int> &) {} + QValueList<int> sizes() { QValueList<int> ret; return ret; } +}; + +#endif diff --git a/qtcompat/qmemarray.h b/qtcompat/qmemarray.h new file mode 100644 index 0000000..05adc6a --- a/dev/null +++ b/qtcompat/qmemarray.h @@ -0,0 +1,8 @@ +#ifndef QTCOMPAT_QMEMARRAY_H +#define QTCOMPAT_QMEMARRAY_H + +#include <qarray.h> + +#define QMemArray QArray + +#endif diff --git a/qtcompat/qpair.h b/qtcompat/qpair.h new file mode 100644 index 0000000..9518179 --- a/dev/null +++ b/qtcompat/qpair.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Definition of QPair class +** +** +** Copyright (C) 1992-2001 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QPAIR_H +#define QPAIR_H + +#ifndef QT_H +#include "qglobal.h" +#include "qdatastream.h" +#endif // QT_H + +template <class T1, class T2> +struct QPair +{ + typedef T1 first_type; + typedef T2 second_type; + + QPair() + : first( T1() ), second( T2() ) + {} + QPair( const T1& t1, const T2& t2 ) + : first( t1 ), second( t2 ) + {} + + T1 first; + T2 second; +}; + +template <class T1, class T2> +inline bool operator==( const QPair<T1, T2>& x, const QPair<T1, T2>& y ) +{ + return x.first == y.first && x.second == y.second; +} + +template <class T1, class T2> +inline bool operator<( const QPair<T1, T2>& x, const QPair<T1, T2>& y ) +{ + return x.first < y.first || + ( !( y.first < x.first ) && x.second < y.second ); +} + +template <class T1, class T2> +inline QPair<T1, T2> qMakePair( const T1& x, const T2& y ) +{ + return QPair<T1, T2>( x, y ); +} + +#ifndef QT_NO_DATASTREAM +template <class T1, class T2> +inline QDataStream& operator>>( QDataStream& s, QPair<T1, T2>& p ) +{ + s >> p.first >> p.second; + return s; +} + +template <class T1, class T2> +inline QDataStream& operator<<( QDataStream& s, const QPair<T1, T2>& p ) +{ + s << p.first << p.second; + return s; +} +#endif + +#endif diff --git a/qtcompat/qptrlist.h b/qtcompat/qptrlist.h new file mode 100644 index 0000000..8ce6868 --- a/dev/null +++ b/qtcompat/qptrlist.h @@ -0,0 +1,10 @@ +#ifndef QTCOMPAT_QPTRLIST_H +#define QTCOMPAT_QPTRLIST_H + +#include <qlist.h> + +#define QPtrList QList +#define QPtrListIterator QListIterator +#define QPtrCollection QCollection + +#endif diff --git a/qtcompat/qptrstack.h b/qtcompat/qptrstack.h new file mode 100644 index 0000000..92070b3 --- a/dev/null +++ b/qtcompat/qptrstack.h @@ -0,0 +1,9 @@ +#ifndef QTCOMPAT_QPTRSTACK_H +#define QTCOMPAT_QPTRSTACK_H + +#include <qstack.h> + +#define QPtrStack QStack +#define QPtrStackIterator QStackIterator + +#endif diff --git a/qtcompat/qptrvector.h b/qtcompat/qptrvector.h new file mode 100644 index 0000000..c869f36 --- a/dev/null +++ b/qtcompat/qptrvector.h @@ -0,0 +1,8 @@ +#ifndef QTCOMPAT_QPTRVECTOR_H +#define QTCOMPAT_QPTRVECTOR_H + +#include <qvector.h> + +#define QPtrVector QVector + +#endif diff --git a/qtcompat/qtcompat.pro b/qtcompat/qtcompat.pro new file mode 100644 index 0000000..f985bb4 --- a/dev/null +++ b/qtcompat/qtcompat.pro @@ -0,0 +1,31 @@ +TEMPLATE = lib +CONFIG += qt warn_on +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +TARGET = microqtcompat +DESTDIR=$(QPEDIR)/lib + + +INTERFACES = \ + +HEADERS = \ + qcombotableitem.h \ + qgridview.h \ + qmemarray.h \ + qptrlist.h \ + qksplitter.h \ + qptrvector.h \ + qinputdialog.h \ + qtooltipcompat.h + +# qsplitter.h + + + + +SOURCES = \ + qinputdialog.cpp \ + qcombotableitem.cpp \ + qgridview.cpp \ + qtooltipcompat.cpp + diff --git a/qtcompat/qtcompat.pro.back b/qtcompat/qtcompat.pro.back new file mode 100644 index 0000000..6da7ce0 --- a/dev/null +++ b/qtcompat/qtcompat.pro.back @@ -0,0 +1,19 @@ +TEMPLATE = lib +CONFIG = qt warn_on release +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc +DESTDIR=$(QPEDIR)/lib + +INTERFACES = \ + +HEADERS = \ + qgridview.h \ + qinputdialog.h \ + qmemarray.h \ + qptrlist.h \ + qptrvector.h \ + qsplitter.h \ + +SOURCES = \ + qgridview.cpp \ + diff --git a/qtcompat/qtooltipcompat.cpp b/qtcompat/qtooltipcompat.cpp new file mode 100644 index 0000000..a2de608 --- a/dev/null +++ b/qtcompat/qtooltipcompat.cpp @@ -0,0 +1,42 @@ + + +/****** + * + * rob's QToolTip class + * + * Apparently Sharp concluded that ToolTips were not useful on the Zaurus and + * left them out of their Qtopia. Unfortunately, QWhatsThis uses the + * QToolTips::palette(), that function returns all 0's, and that means that + * QWhatsThis windows come up with black background and black foreground. By + * re-implementing this class, QWhatsThis calls this QToolTip::palette(), and + * gets a useful result. + * + * Include this class in your own Zaurus application and QWhatsThis should work + * for you as well. + * + * The contents of this file are released without restriction to the public + * domain. + * + * Copyright (c) rob miller October, 2003 + * + *****/ +#ifdef ADD_TOOLTIP + +#include "qtooltipcompat.h" +QPalette QToolTip::palette() { + static bool init = false; + static QPalette pt; + if (! init) { // only initialise once + init=true; + //rDebug("initialising my qtt-palette()"); //rDebug() is just qDebug() with a compile switch + QColor fg = QColor(0x00,0x00,0x00); + QColor bg = QColor(0xff,0xff,0xdc); + + pt.setColor(QColorGroup::Background,bg); + pt.setBrush(QColorGroup::Foreground,fg); + } + + return pt; +} +#endif + diff --git a/qtcompat/qtooltipcompat.h b/qtcompat/qtooltipcompat.h new file mode 100644 index 0000000..4d44146 --- a/dev/null +++ b/qtcompat/qtooltipcompat.h @@ -0,0 +1,34 @@ +#ifndef QTCOMPAT_QTOOLTIP_H +#define QTCOMPAT_QTOOLTIP_H + +/****** + * + * rob's QToolTip class + * + * Apparently Sharp concluded that ToolTips were not useful on the Zaurus and + * left them out of their Qtopia. Unfortunately, QWhatsThis uses the + * QToolTips::palette(), that function returns all 0's, and that means that + * QWhatsThis windows come up with black background and black foreground. By + * re-implementing this class, QWhatsThis calls this QToolTip::palette(), and + * gets a useful result. + * + * Include this class in your own Zaurus application and QWhatsThis should work + * for you as well. + * + * The contents of this file are released without restriction to the public + * domain. + * + * Copyright (c) rob miller October, 2003 + * + *****/ +#ifdef ADD_TOOLTIP + +#include <qpalette.h> +class QToolTip: public Qt { + public: + static QPalette palette(); +}; + +#endif + +#endif diff --git a/setQtopia b/setQtopia new file mode 100755 index 0000000..a2bba93 --- a/dev/null +++ b/setQtopia @@ -0,0 +1,19 @@ +# copy this dir to /opt/Qtopia/examples/ +# Now this file should be in the path /opt/Qtopia/examples/kdepim/setQtopia +# add the following line to ~/.bashrc without leading # +# alias cq='source /opt/Qtopia/examples/kdepim/setQtopia' +# then type in terminal cq<return> to set the variables +# for compiling for the Qt virtual framebuffer on the desktop. +# It will bulid in debug mode. you can change it with the last two lines +export QPEDIR=/opt/Qtopia +export OPIEDIR=/kde_dev/opie/opie +export QTDIR=/opt/Qtopia +export PATH=$QTDIR/bin:$PATH +export TMAKEPATH=/opt/Qtopia/tmake/lib/qws/linux-generic-g++ +export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH +export PLATFORM=qtopia +export QTOPIALIB=-lqtopia +#export RELEASE_DEBUG=release +export RELEASE_DEBUG=debug + +
\ No newline at end of file diff --git a/setZaurus b/setZaurus new file mode 100644 index 0000000..f0472bd --- a/dev/null +++ b/setZaurus @@ -0,0 +1,14 @@ +# copy this dir to /opt/Qtopia/examples/ +# Now this file should be in the path /opt/Qtopia/examples/kdepim/setZaurus +# add the following line to ~/.bashrc without leading # +# alias cz='source /opt/Qtopia/examples/kdepim/setZaurus' +# then type in terminal cz<return> to set the variables +# for cross-compiling +export QPEDIR=/opt/Qtopia/sharp +export OPIEDIR=/kde_dev/opie/opie +export QTDIR=/opt/Qtopia/sharp +export PATH=$QTDIR/bin:/opt/Embedix/tools/bin:$PATH +export TMAKEPATH=/opt/Qtopia/tmake/lib/qws/linux-sharp-g++ +export PLATFORM=zaurus +export RELEASE_DEBUG=release +#export RELEASE_DEBUG=debug
\ No newline at end of file diff --git a/sharp.tmake.conf b/sharp.tmake.conf new file mode 100644 index 0000000..6c5c59f --- a/dev/null +++ b/sharp.tmake.conf @@ -0,0 +1,68 @@ +# +# $Id$ +# +# tmake configuration for linux-g++ using the arm-linux-g++ crosscompiler. +# + +TEMPLATE = app +CONFIG = qt warn_on release + +TMAKE_CC = arm-linux-gcc +TMAKE_DASHCROSS = -arm +TMAKE_CFLAGS = -pipe +TMAKE_CFLAGS_WARN_ON = -Wall -W +TMAKE_CFLAGS_WARN_OFF = -w +TMAKE_CFLAGS_RELEASE = -O2 +TMAKE_CFLAGS_DEBUG = -g +TMAKE_CFLAGS_SHLIB = -fPIC +TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses +TMAKE_CFLAGS_THREAD = -D_REENTRANT + +TMAKE_CXX = arm-linux-g++ +TMAKE_CXXFLAGS = $$TMAKE_CFLAGS -DQT_QWS_SL5XXX -DQT_QWS_CUSTOM -DQWS -fno-exceptions -fno-rtti -DADD_TOOLTIP +TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON +TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF +TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE +TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG +TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB +TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC +TMAKE_CXXFLAGS_THREAD = $$TMAKE_CFLAGS_THREAD + +TMAKE_INCDIR = +TMAKE_LIBDIR = +TMAKE_INCDIR_X11 = +TMAKE_LIBDIR_X11 = +TMAKE_INCDIR_QT = $(QTDIR)/include +TMAKE_LIBDIR_QT = $(QTDIR)/lib +TMAKE_INCDIR_QTOPIA = $(QPEDIR)/include +TMAKE_LIBDIR_QTOPIA = $(QPEDIR)/lib +TMAKE_INCDIR_OPENGL = /usr/X11R6/include +TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib + +TMAKE_LINK = arm-linux-gcc +TMAKE_LINK_SHLIB = arm-linux-gcc +TMAKE_LFLAGS = +TMAKE_LFLAGS_RELEASE = +TMAKE_LFLAGS_DEBUG = +TMAKE_LFLAGS_SHLIB = -shared +TMAKE_LFLAGS_SONAME = -Wl,-soname, +TMAKE_LFLAGS_THREAD = +TMAKE_RPATH = -Wl,-rpath, + +TMAKE_LIBS = +TMAKE_LIBS_X11 = +TMAKE_LIBS_X11SM = +TMAKE_LIBS_QT = -lqte +TMAKE_LIBS_QT_THREAD = -lqte-mt +TMAKE_LIBS_QTOPIA = -lqtopia +TMAKE_LIBS_OPENGL = +TMAKE_LIBS_THREAD = -lpthread + +TMAKE_MOC = $(QTDIR)/bin/moc +TMAKE_UIC = $(QTDIR)/bin/uic + +TMAKE_AR = arm-linux-ar cqs +TMAKE_RANLIB = + +TMAKE_TAR = tar -cf +TMAKE_GZIP = gzip -9f diff --git a/variables.pri b/variables.pri new file mode 100644 index 0000000..01fcea3 --- a/dev/null +++ b/variables.pri @@ -0,0 +1,5 @@ + +# variables settings for compilation for Linux desktop and Qt 3.x.x + +CONFIG += debug +#release @@ -0,0 +1 @@ +version = "1.9.1"; |