From 6f0e06a23515e795b75e08161487d60c9fc4f933 Mon Sep 17 00:00:00 2001 From: Naresh Mehta Date: Thu, 8 Jul 2010 05:31:41 +0200 Subject: [PATCH] Initial Commit. The packaging still does not work properly. new file: Makefile new file: addprofile.cpp new file: addprofile.h new file: addprofile.ui new file: addstep.cpp new file: addstep.h new file: addstep.ui new file: build-stamp new file: cfConfig.xml new file: config.cpp new file: config.h new file: config.xml new file: configure-stamp new file: confmanager.cpp new file: confmanager.h new file: confmgr new file: confmgr.pro new file: confmgr.pro.user new file: dbusutility.cpp new file: dbusutility.h new file: debian/README.Debian new file: debian/changelog new file: debian/compat new file: debian/confmgr-default.ex new file: debian/confmgr.doc-base.EX new file: debian/confmgr/DEBIAN/control new file: debian/confmgr/DEBIAN/md5sums new file: debian/confmgr/usr/share/doc/confmgr/README.Debian new file: debian/confmgr/usr/share/doc/confmgr/changelog.Debian.gz new file: debian/confmgr/usr/share/doc/confmgr/copyright new file: debian/control new file: debian/copyright new file: debian/cron.d.ex new file: debian/dirs new file: debian/docs new file: debian/emacsen-install.ex new file: debian/emacsen-remove.ex new file: debian/emacsen-startup.ex new file: debian/files new file: debian/init.d.ex new file: debian/manpage.1.ex new file: debian/manpage.sgml.ex new file: debian/manpage.xml.ex new file: debian/menu.ex new file: debian/postinst.ex new file: debian/postrm.ex new file: debian/preinst.ex new file: debian/prerm.ex new file: debian/rules new file: debian/watch.ex new file: main.cpp new file: mainwindow.cpp new file: mainwindow.h new file: mainwindow.ui new file: profile.cpp new file: profile.h new file: src/Makefile new file: src/addprofile.cpp new file: src/addprofile.h new file: src/addprofile.ui new file: src/addstep.cpp new file: src/addstep.h new file: src/addstep.ui new file: src/cfConfig.xml new file: src/config.cpp new file: src/config.h new file: src/config.xml new file: src/confmanager.cpp new file: src/confmanager.h new file: src/confmgr.pro new file: src/confmgr.pro.user new file: src/dbusutility.cpp new file: src/dbusutility.h new file: src/main.cpp new file: src/mainwindow.cpp new file: src/mainwindow.h new file: src/mainwindow.ui new file: src/profile.cpp new file: src/profile.h new file: src/src.pro new file: src/xmlutil.cpp new file: src/xmlutil.h new file: xmlutil.cpp new file: xmlutil.h --- Makefile | 362 +++++++++++++++++++ addprofile.cpp | 85 +++++ addprofile.h | 42 +++ addprofile.ui | 181 ++++++++++ addstep.cpp | 28 ++ addstep.h | 32 ++ addstep.ui | 177 ++++++++++ cfConfig.xml | 8 + config.cpp | 185 ++++++++++ config.h | 71 ++++ config.xml | 17 + confmanager.cpp | 200 +++++++++++ confmanager.h | 38 ++ confmgr | Bin 0 -> 150991 bytes confmgr.pro | 48 +++ confmgr.pro.user | 303 ++++++++++++++++ dbusutility.cpp | 71 ++++ dbusutility.h | 35 ++ debian/README.Debian | 6 + debian/changelog | 6 + debian/compat | 1 + debian/confmgr-default.ex | 10 + debian/confmgr.doc-base.EX | 22 ++ debian/confmgr/DEBIAN/control | 9 + debian/confmgr/DEBIAN/md5sums | 3 + debian/confmgr/usr/share/doc/confmgr/README.Debian | 6 + .../usr/share/doc/confmgr/changelog.Debian.gz | Bin 0 -> 188 bytes debian/confmgr/usr/share/doc/confmgr/copyright | 35 ++ debian/control | 12 + debian/copyright | 35 ++ debian/cron.d.ex | 4 + debian/dirs | 2 + debian/emacsen-install.ex | 45 +++ debian/emacsen-remove.ex | 15 + debian/emacsen-startup.ex | 25 ++ debian/files | 1 + debian/init.d.ex | 81 +++++ debian/manpage.1.ex | 59 ++++ debian/manpage.sgml.ex | 156 +++++++++ debian/manpage.xml.ex | 148 ++++++++ debian/menu.ex | 2 + debian/postinst.ex | 41 +++ debian/postrm.ex | 39 +++ debian/preinst.ex | 37 ++ debian/prerm.ex | 40 +++ debian/rules | 102 ++++++ debian/watch.ex | 22 ++ main.cpp | 20 ++ mainwindow.cpp | 108 ++++++ mainwindow.h | 46 +++ mainwindow.ui | 141 ++++++++ profile.cpp | 34 ++ profile.h | 49 +++ src/Makefile | 365 ++++++++++++++++++++ src/addprofile.cpp | 85 +++++ src/addprofile.h | 42 +++ src/addprofile.ui | 181 ++++++++++ src/addstep.cpp | 28 ++ src/addstep.h | 32 ++ src/addstep.ui | 177 ++++++++++ src/cfConfig.xml | 8 + src/config.cpp | 185 ++++++++++ src/config.h | 71 ++++ src/config.xml | 17 + src/confmanager.cpp | 200 +++++++++++ src/confmanager.h | 38 ++ src/confmgr.pro | 10 + src/confmgr.pro.user | 303 ++++++++++++++++ src/dbusutility.cpp | 71 ++++ src/dbusutility.h | 35 ++ src/main.cpp | 20 ++ src/mainwindow.cpp | 108 ++++++ src/mainwindow.h | 46 +++ src/mainwindow.ui | 141 ++++++++ src/profile.cpp | 34 ++ src/profile.h | 49 +++ src/src.pro | 84 +++++ src/xmlutil.cpp | 136 ++++++++ src/xmlutil.h | 79 +++++ xmlutil.cpp | 136 ++++++++ xmlutil.h | 79 +++++ 81 files changed, 6005 insertions(+) create mode 100644 Makefile create mode 100644 addprofile.cpp create mode 100644 addprofile.h create mode 100644 addprofile.ui create mode 100644 addstep.cpp create mode 100644 addstep.h create mode 100644 addstep.ui create mode 100644 build-stamp create mode 100644 cfConfig.xml create mode 100644 config.cpp create mode 100644 config.h create mode 100644 config.xml create mode 100644 configure-stamp create mode 100644 confmanager.cpp create mode 100644 confmanager.h create mode 100755 confmgr create mode 100644 confmgr.pro create mode 100644 confmgr.pro.user create mode 100644 dbusutility.cpp create mode 100644 dbusutility.h create mode 100644 debian/README.Debian create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/confmgr-default.ex create mode 100644 debian/confmgr.doc-base.EX create mode 100644 debian/confmgr/DEBIAN/control create mode 100644 debian/confmgr/DEBIAN/md5sums create mode 100644 debian/confmgr/usr/share/doc/confmgr/README.Debian create mode 100644 debian/confmgr/usr/share/doc/confmgr/changelog.Debian.gz create mode 100644 debian/confmgr/usr/share/doc/confmgr/copyright create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/cron.d.ex create mode 100644 debian/dirs create mode 100644 debian/docs create mode 100644 debian/emacsen-install.ex create mode 100644 debian/emacsen-remove.ex create mode 100644 debian/emacsen-startup.ex create mode 100644 debian/files create mode 100644 debian/init.d.ex create mode 100644 debian/manpage.1.ex create mode 100644 debian/manpage.sgml.ex create mode 100644 debian/manpage.xml.ex create mode 100644 debian/menu.ex create mode 100644 debian/postinst.ex create mode 100644 debian/postrm.ex create mode 100644 debian/preinst.ex create mode 100644 debian/prerm.ex create mode 100755 debian/rules create mode 100644 debian/watch.ex create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui create mode 100644 profile.cpp create mode 100644 profile.h create mode 100644 src/Makefile create mode 100644 src/addprofile.cpp create mode 100644 src/addprofile.h create mode 100644 src/addprofile.ui create mode 100644 src/addstep.cpp create mode 100644 src/addstep.h create mode 100644 src/addstep.ui create mode 100644 src/cfConfig.xml create mode 100644 src/config.cpp create mode 100644 src/config.h create mode 100644 src/config.xml create mode 100644 src/confmanager.cpp create mode 100644 src/confmanager.h create mode 100644 src/confmgr.pro create mode 100644 src/confmgr.pro.user create mode 100644 src/dbusutility.cpp create mode 100644 src/dbusutility.h create mode 100644 src/main.cpp create mode 100644 src/mainwindow.cpp create mode 100644 src/mainwindow.h create mode 100644 src/mainwindow.ui create mode 100644 src/profile.cpp create mode 100644 src/profile.h create mode 100644 src/src.pro create mode 100644 src/xmlutil.cpp create mode 100644 src/xmlutil.h create mode 100644 xmlutil.cpp create mode 100644 xmlutil.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e84a78b --- /dev/null +++ b/Makefile @@ -0,0 +1,362 @@ +############################################################################# +# Makefile for building: confmgr +# Generated by qmake (2.01a) (Qt 4.6.2) on: Tue Jul 6 16:19:30 2010 +# Project: confmgr.pro +# Template: app +# Command: /usr/bin/qmake -unix -o Makefile confmgr.pro +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DQT_GL_NO_SCISSOR_TEST -DQT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH=1024 -DQT_NO_DEBUG -DQT_MAEMO5_LIB -DQT_DBUS_LIB -DQT_XML_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -pipe -O3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -Wall -W -D_REENTRANT $(DEFINES) +CXXFLAGS = -pipe -O3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -Wall -W -D_REENTRANT $(DEFINES) +INCPATH = -I/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/linux-g++-maemo5 -I. -I/targets/FREMANTLE_ARMEL/usr/include/QtCore -I/targets/FREMANTLE_ARMEL/usr/include/QtGui -I/targets/FREMANTLE_ARMEL/usr/include/QtXml -I/targets/FREMANTLE_ARMEL/usr/include/QtDBus -I/targets/FREMANTLE_ARMEL/usr/include/QtMaemo5 -I/targets/FREMANTLE_ARMEL/usr/include -I. -I. +LINK = g++ +LFLAGS = -Wl,-rpath-link,/usr/lib -Wl,-O1 -Wl,--hash-style=gnu -Wl,-rpath,/usr/lib +LIBS = $(SUBLIBS) -L/usr/lib -lQtMaemo5 -L/usr/lib -L/usr/X11R6/lib -lQtDBus -lQtXml -lQtGui -lQtCore -lpthread +AR = ar cqs +RANLIB = +QMAKE = /usr/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +STRIP = strip +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = ./ + +####### Files + +SOURCES = main.cpp \ + mainwindow.cpp \ + xmlutil.cpp \ + profile.cpp \ + config.cpp \ + addprofile.cpp \ + addstep.cpp \ + dbusutility.cpp \ + confmanager.cpp moc_mainwindow.cpp \ + moc_xmlutil.cpp \ + moc_profile.cpp \ + moc_config.cpp \ + moc_addprofile.cpp \ + moc_addstep.cpp \ + moc_confmanager.cpp +OBJECTS = main.o \ + mainwindow.o \ + xmlutil.o \ + profile.o \ + config.o \ + addprofile.o \ + addstep.o \ + dbusutility.o \ + confmanager.o \ + moc_mainwindow.o \ + moc_xmlutil.o \ + moc_profile.o \ + moc_config.o \ + moc_addprofile.o \ + moc_addstep.o \ + moc_confmanager.o +DIST = /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/common/unix.conf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/common/linux.conf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/qconfig.pri \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/qt_functions.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/qt_config.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/exclusive_builds.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/default_pre.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/release.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/default_post.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/warn_on.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/qt.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/moc.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/dbusinterfaces.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/dbusadaptors.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/unix/thread.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/resources.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/uic.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/yacc.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/lex.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/include_source_dir.prf \ + confmgr.pro +QMAKE_TARGET = confmgr +DESTDIR = +TARGET = confmgr + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile $(TARGET) + +$(TARGET): ui_mainwindow.h ui_addprofile.h ui_addstep.h $(OBJECTS) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) + +Makefile: confmgr.pro /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/linux-g++-maemo5/qmake.conf /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/common/unix.conf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/common/linux.conf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/qconfig.pri \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/qt_functions.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/qt_config.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/exclusive_builds.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/default_pre.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/release.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/default_post.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/warn_on.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/qt.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/moc.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/dbusinterfaces.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/dbusadaptors.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/unix/thread.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/resources.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/uic.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/yacc.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/lex.prf \ + /targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/include_source_dir.prf \ + /usr/lib/libQtMaemo5.prl \ + /usr/lib/libQtDBus.prl \ + /usr/lib/libQtXml.prl \ + /usr/lib/libQtCore.prl \ + /usr/lib/libQtGui.prl + $(QMAKE) -unix -o Makefile confmgr.pro +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/common/unix.conf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/common/linux.conf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/qconfig.pri: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/qt_functions.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/qt_config.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/exclusive_builds.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/default_pre.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/release.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/default_post.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/warn_on.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/qt.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/moc.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/dbusinterfaces.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/dbusadaptors.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/unix/thread.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/resources.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/uic.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/yacc.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/lex.prf: +/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/features/include_source_dir.prf: +/usr/lib/libQtMaemo5.prl: +/usr/lib/libQtDBus.prl: +/usr/lib/libQtXml.prl: +/usr/lib/libQtCore.prl: +/usr/lib/libQtGui.prl: +qmake: FORCE + @$(QMAKE) -unix -o Makefile confmgr.pro + +dist: + @$(CHK_DIR_EXISTS) .tmp/confmgr1.0.0 || $(MKDIR) .tmp/confmgr1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/confmgr1.0.0/ && $(COPY_FILE) --parents mainwindow.h xmlutil.h profile.h config.h addprofile.h addstep.h dbusutility.h confmanager.h .tmp/confmgr1.0.0/ && $(COPY_FILE) --parents main.cpp mainwindow.cpp xmlutil.cpp profile.cpp config.cpp addprofile.cpp addstep.cpp dbusutility.cpp confmanager.cpp .tmp/confmgr1.0.0/ && $(COPY_FILE) --parents mainwindow.ui addprofile.ui addstep.ui .tmp/confmgr1.0.0/ && (cd `dirname .tmp/confmgr1.0.0` && $(TAR) confmgr1.0.0.tar confmgr1.0.0 && $(COMPRESS) confmgr1.0.0.tar) && $(MOVE) `dirname .tmp/confmgr1.0.0`/confmgr1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/confmgr1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: moc_mainwindow.cpp moc_xmlutil.cpp moc_profile.cpp moc_config.cpp moc_addprofile.cpp moc_addstep.cpp moc_confmanager.cpp +compiler_moc_header_clean: + -$(DEL_FILE) moc_mainwindow.cpp moc_xmlutil.cpp moc_profile.cpp moc_config.cpp moc_addprofile.cpp moc_addstep.cpp moc_confmanager.cpp +moc_mainwindow.cpp: config.h \ + profile.h \ + addprofile.h \ + addstep.h \ + confmanager.h \ + dbusutility.h \ + mainwindow.h + /usr/bin/moc $(DEFINES) $(INCPATH) mainwindow.h -o moc_mainwindow.cpp + +moc_xmlutil.cpp: profile.h \ + xmlutil.h + /usr/bin/moc $(DEFINES) $(INCPATH) xmlutil.h -o moc_xmlutil.cpp + +moc_profile.cpp: profile.h + /usr/bin/moc $(DEFINES) $(INCPATH) profile.h -o moc_profile.cpp + +moc_config.cpp: profile.h \ + config.h + /usr/bin/moc $(DEFINES) $(INCPATH) config.h -o moc_config.cpp + +moc_addprofile.cpp: addstep.h \ + profile.h \ + addprofile.h + /usr/bin/moc $(DEFINES) $(INCPATH) addprofile.h -o moc_addprofile.cpp + +moc_addstep.cpp: profile.h \ + addstep.h + /usr/bin/moc $(DEFINES) $(INCPATH) addstep.h -o moc_addstep.cpp + +moc_confmanager.cpp: profile.h \ + dbusutility.h \ + confmanager.h + /usr/bin/moc $(DEFINES) $(INCPATH) confmanager.h -o moc_confmanager.cpp + +compiler_dbus_interface_source_make_all: +compiler_dbus_interface_source_clean: +compiler_dbus_adaptor_source_make_all: +compiler_dbus_adaptor_source_clean: +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_dbus_interface_header_make_all: +compiler_dbus_interface_header_clean: +compiler_dbus_interface_moc_make_all: +compiler_dbus_interface_moc_clean: +compiler_dbus_adaptor_header_make_all: +compiler_dbus_adaptor_header_clean: +compiler_dbus_adaptor_moc_make_all: +compiler_dbus_adaptor_moc_clean: +compiler_uic_make_all: ui_mainwindow.h ui_addprofile.h ui_addstep.h +compiler_uic_clean: + -$(DEL_FILE) ui_mainwindow.h ui_addprofile.h ui_addstep.h +ui_mainwindow.h: mainwindow.ui + /usr/bin/uic mainwindow.ui -o ui_mainwindow.h + +ui_addprofile.h: addprofile.ui + /usr/bin/uic addprofile.ui -o ui_addprofile.h + +ui_addstep.h: addstep.ui + /usr/bin/uic addstep.ui -o ui_addstep.h + +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean compiler_uic_clean + +####### Compile + +main.o: main.cpp mainwindow.h \ + config.h \ + profile.h \ + addprofile.h \ + addstep.h \ + confmanager.h \ + dbusutility.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp + +mainwindow.o: mainwindow.cpp mainwindow.h \ + config.h \ + profile.h \ + addprofile.h \ + addstep.h \ + confmanager.h \ + dbusutility.h \ + ui_mainwindow.h \ + xmlutil.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o mainwindow.o mainwindow.cpp + +xmlutil.o: xmlutil.cpp xmlutil.h \ + profile.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o xmlutil.o xmlutil.cpp + +profile.o: profile.cpp profile.h \ + xmlutil.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o profile.o profile.cpp + +config.o: config.cpp config.h \ + profile.h \ + xmlutil.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o config.o config.cpp + +addprofile.o: addprofile.cpp addprofile.h \ + addstep.h \ + profile.h \ + ui_addprofile.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o addprofile.o addprofile.cpp + +addstep.o: addstep.cpp addstep.h \ + profile.h \ + ui_addstep.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o addstep.o addstep.cpp + +dbusutility.o: dbusutility.cpp dbusutility.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o dbusutility.o dbusutility.cpp + +confmanager.o: confmanager.cpp confmanager.h \ + profile.h \ + dbusutility.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o confmanager.o confmanager.cpp + +moc_mainwindow.o: moc_mainwindow.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_mainwindow.o moc_mainwindow.cpp + +moc_xmlutil.o: moc_xmlutil.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_xmlutil.o moc_xmlutil.cpp + +moc_profile.o: moc_profile.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_profile.o moc_profile.cpp + +moc_config.o: moc_config.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_config.o moc_config.cpp + +moc_addprofile.o: moc_addprofile.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_addprofile.o moc_addprofile.cpp + +moc_addstep.o: moc_addstep.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_addstep.o moc_addstep.cpp + +moc_confmanager.o: moc_confmanager.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_confmanager.o moc_confmanager.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/addprofile.cpp b/addprofile.cpp new file mode 100644 index 0000000..2292419 --- /dev/null +++ b/addprofile.cpp @@ -0,0 +1,85 @@ +#include "addprofile.h" +#include "ui_addprofile.h" +#include +#include + +AddProfile::AddProfile(QWidget *parent) : + QWidget(parent), + ui(new Ui::AddProfile) +{ + ui->setupUi(this); + connect(&mFrmAddStep, SIGNAL(StepAddedSuccessfully(Steps)), + this, SLOT(updateStepList(Steps))); + mFrmAddStep.setWindowFlags(mFrmAddStep.windowFlags() | Qt::Window); +} + +AddProfile::~AddProfile() +{ + delete ui; +} + +void AddProfile::on_addProCancel_clicked() +{ + this->close(); +} + +void AddProfile::on_addProSave_clicked() +{ + Profile p; + p.mName = ui->addProName->text(); + p.mNoOfSteps = ui->addProStepList->count(); + p.mSteps = mSteps; + emit(ProfileAddedSuccessfully(p)); + this->close(); +} + +void AddProfile::showStepsUI() +{ + mFrmAddStep.setParent(this, Qt::Window); + mFrmAddStep.clear(); + mFrmAddStep.setAttribute(Qt::WA_Maemo5StackedWindow); + mFrmAddStep.show(); +} + +void AddProfile::updateStepList(Steps step) +{ + mSteps.append(step); + QString text = "Value: " + step.value(); + text += " || Delay: " + QString::number(step.delay()); + ui->addProStepList->addItem(text); + qDebug() << "updateStepList(): Text in List: " << text; +} + +void AddProfile::on_addProRemoveStep_clicked() +{ + if(ui->addProStepList->count() <= 0 || ui->addProStepList->currentRow() < 0) + { + QMessageBox msg; + msg.setText("Please select a step first!"); + msg.exec(); + return; + } + + mSteps.removeAt(ui->addProStepList->currentRow()); + QString *pText = (QString*) ui->addProStepList->takeItem(ui->addProStepList->currentRow()); + delete pText; +} + +void AddProfile::clear() +{ + ui->addProStepList->clear(); + ui->addProName->setText(QString::null); +} + +void AddProfile::showProfile(Profile &p) +{ + ui->addProName->setText(p.mName); + for(unsigned int i = 0; i < p.mNoOfSteps; i++) + { + Steps step = p.mSteps.at(i); + QString text = "Value: " + step.value(); + text += " || Delay: " + QString::number(step.delay()); + ui->addProStepList->addItem(text); + } + this->show(); +} diff --git a/addprofile.h b/addprofile.h new file mode 100644 index 0000000..3c93004 --- /dev/null +++ b/addprofile.h @@ -0,0 +1,42 @@ +#ifndef ADDPROFILE_H +#define ADDPROFILE_H + +#include +#include +#include "addstep.h" +#include "profile.h" + +namespace Ui { + class AddProfile; +} + +class AddProfile : public QWidget +{ + Q_OBJECT + +public: + explicit AddProfile(QWidget *parent = 0); + ~AddProfile(); + + void clear(); + +public slots: + void updateStepList(Steps step); + void showProfile(Profile &p); + +private: + Ui::AddProfile *ui; + QList mSteps; + AddStep mFrmAddStep; + +signals: + void ProfileAddedSuccessfully(Profile profile); + +private slots: + void on_addProRemoveStep_clicked(); + void on_addProSave_clicked(); + void on_addProCancel_clicked(); + void showStepsUI(); +}; + +#endif // ADDPROFILE_H diff --git a/addprofile.ui b/addprofile.ui new file mode 100644 index 0000000..7ccb138 --- /dev/null +++ b/addprofile.ui @@ -0,0 +1,181 @@ + + + AddProfile + + + Qt::ApplicationModal + + + + 0 + 0 + 800 + 424 + + + + Qt::TabFocus + + + AddProfile + + + + + 560 + 140 + 211 + 141 + + + + + + + + 0 + 0 + + + + Add Step + + + + + + + + 0 + 0 + + + + Remove Step + + + + + + + + + 30 + 330 + 741 + 71 + + + + + + + + 0 + 0 + + + + Save Profile + + + + + + + + 0 + 0 + + + + Cancel Operation + + + + + + + + + 30 + 10 + 741 + 61 + + + + + + + Profile Name: + + + + + + + + + + + + 30 + 80 + 511 + 231 + + + + + + + Steps: + + + + + + + + + + + + + addProCancel + clicked() + AddProfile + close() + + + 240 + 599 + + + 239 + 319 + + + + + addProAddStep + clicked() + AddProfile + showStepsUI() + + + 151 + 483 + + + -2 + 521 + + + + + + showStepsUI() + + diff --git a/addstep.cpp b/addstep.cpp new file mode 100644 index 0000000..bc05e5f --- /dev/null +++ b/addstep.cpp @@ -0,0 +1,28 @@ +#include "addstep.h" +#include "ui_addstep.h" + +AddStep::AddStep(QWidget *parent) : + QWidget(parent), + ui(new Ui::AddStep) +{ + ui->setupUi(this); +} + +AddStep::~AddStep() +{ + delete ui; +} + +void AddStep::AddOperationStep() +{ + mStep.setDelay(ui->addStepDelay->text().toInt()); + mStep.setValue(ui->addStepValue->text()); + emit(StepAddedSuccessfully(mStep)); + this->close(); +} + +void AddStep::clear() +{ + ui->addStepDelay->setText(QString::null); + ui->addStepValue->setText(QString::null); +} diff --git a/addstep.h b/addstep.h new file mode 100644 index 0000000..f613879 --- /dev/null +++ b/addstep.h @@ -0,0 +1,32 @@ +#ifndef ADDSTEP_H +#define ADDSTEP_H + +#include +#include "profile.h" + +namespace Ui { + class AddStep; +} + +class AddStep : public QWidget +{ + Q_OBJECT + +public: + explicit AddStep(QWidget *parent = 0); + ~AddStep(); + + void clear(); + +signals: + void StepAddedSuccessfully(Steps step); + +public slots: + void AddOperationStep(); + +private: + Ui::AddStep *ui; + Steps mStep; +}; + +#endif // ADDSTEP_H diff --git a/addstep.ui b/addstep.ui new file mode 100644 index 0000000..9582a99 --- /dev/null +++ b/addstep.ui @@ -0,0 +1,177 @@ + + + AddStep + + + Qt::ApplicationModal + + + + 0 + 0 + 800 + 424 + + + + AddStep + + + + + 30 + 170 + 741 + 71 + + + + + + + Value: + + + + + + + Qt::ImhDigitsOnly + + + + + + + + + 31 + 250 + 281 + 71 + + + + + + + Delay: + + + + + + + Qt::ImhDigitsOnly + + + + + + + Seconds + + + + + + + + + 30 + 330 + 741 + 71 + + + + + + + + 0 + 0 + + + + Add Step + + + + + + + + 0 + 0 + + + + Cancel Operation + + + + + + + + + 30 + 9 + 741 + 151 + + + + + + + The Value field is a phone number or DTMF tones. Include characters like *, + or # in the Value as and when they are required. The Delay in seconds shows the time allowed to lapse before dialing the corresponding value. The first step typically has 0 delay with the conference number as a value. + + + true + + + + + + + + + + btnCancel + clicked() + AddStep + close() + + + 240 + 169 + + + 239 + 100 + + + + + btnaddStep + clicked() + AddStep + AddOperationStep() + + + 143 + 133 + + + 74 + 199 + + + + + + AddOperationStep() + + diff --git a/build-stamp b/build-stamp new file mode 100644 index 0000000..e69de29 diff --git a/cfConfig.xml b/cfConfig.xml new file mode 100644 index 0000000..dfa1740 --- /dev/null +++ b/cfConfig.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/config.cpp b/config.cpp new file mode 100644 index 0000000..76dc12f --- /dev/null +++ b/config.cpp @@ -0,0 +1,185 @@ +#include "config.h" +#include "profile.h" +#include "xmlutil.h" + +#include +#include + +/* + TODO: Create backup & restore functions for the backup configuration files. + Today it only writes a backup when the removeAllProfiles() is called. + */ + +Config::Config(QObject *parent) : + QObject(parent) +{ + confFile.setFileName(CONFIG_FILE); + noOfProfiles = 0; + profileList.clear(); +} + +bool Config::openConfig() +{ + int stopLoops = 0; + qDebug() << "Opening the Config file"; + + processAgain: + bool bOpenResult = confFile.open(QIODevice::ReadWrite | QIODevice::Text); + if(bOpenResult) + { + QString errorMsg; + int errorLine, errorColumn; + bOpenResult = domDoc.setContent(&confFile, &errorMsg, + &errorLine, &errorColumn); + if(!bOpenResult) + { + qDebug() << "Error while setContent on Line: " << errorLine + << "Column: " << errorColumn << endl + << "Error Text: " << errorMsg; +// return bOpenResult; + confFile.write(DEFAULT_XML); + closeConfig(); + if(0 == stopLoops) + { + stopLoops++; + goto processAgain; + } + } + + QDomNode node = domDoc.namedItem(PROFILE_TAG); + if(node.isNull()) + { + qDebug() << "Probably first use of config! Creating Profiles Tag"; + QDomElement el = Xmlutil::addElement(domDoc, domDoc, PROFILE_TAG); + // noOfProfiles should be 0, initialized in CTOR... + el.setAttribute(NO_OF_PROFILE_ATTR, noOfProfiles); + return true; + } + + // Now load the whole config file in memory! + qDebug() << "Trying to load the whole config now..."; + bOpenResult = readAllProfiles(); + } + return bOpenResult; +} + +bool Config::closeConfig() +{ + bool bResult = confFile.flush(); + confFile.close(); + return bResult; +} + +int Config::addProfile(const Profile &p) +{ + int error = 0; + QDomElement el = domDoc.namedItem(PROFILE_TAG).toElement(); + Xmlutil::generateProfileXML(p, &error, &domDoc, &el); + if(!error) + { + noOfProfiles++; + updateNoOfProfiles(); + profileList.append(p); + } + qDebug() << "AddProfile(): " << error << "\tXMLString is: " << endl << domDoc.toString(); + return error; +} + +void Config::updateNoOfProfiles() +{ + QDomElement el = domDoc.namedItem(PROFILE_TAG).toElement(); + el.setAttribute(NO_OF_PROFILE_ATTR, noOfProfiles); +} + +int Config::removeProfile(const Profile &p) +{ + QDomElement elem = domDoc.namedItem(PROFILE_TAG).toElement(); + QDomElement el = elem.firstChildElement(); + qDebug() << el.text(); + for(int i = 0; i < noOfProfiles; i++) + { + QString name = el.attribute(NAME_ATTR); + + qDebug() << "Name is: " << name; + if(p.mName == name) + { + if(!el.parentNode().removeChild(el).isNull()) + { + noOfProfiles--; + updateNoOfProfiles(); + profileList.removeAt(i); + qDebug() << "RemoveChild okay!"; + } + break; + } + el = el.nextSiblingElement(); + } + return 0; +} + +void Config::flushConfig() +{ + confFile.flush(); +} + +bool Config::readAllProfiles() +{ + // Point to the PROFILE_TAG node->element + QDomElement el = domDoc.namedItem(PROFILE_TAG).toElement(); + noOfProfiles = el.attribute(NO_OF_PROFILE_ATTR).toInt(); + + qDebug() << "Number of profiles in config is: " << noOfProfiles; + + if(noOfProfiles > 0) + { + QDomElement childEl = el.firstChildElement(); + for(int i = 0; i < noOfProfiles; i++) + { + Profile p; + QString dummy; dummy.clear(); + if(!Xmlutil::degenerateProfileXML(dummy, p, &childEl)) + { + profileList.append(p); + qDebug() << "Profile added to ProfileList..."; + } + else + { + qDebug() << "Profile not added, returning false"; + return false; + } + childEl = childEl.nextSiblingElement(); + } + } + return true; +} + +bool Config::writeAllProfiles() +{ + // Stupid hack to dump all the document data into the config file... + bool bResult = closeConfig(); + QDir dir(CONFIG_DIR); + bResult = dir.remove(CONFIG_FILE); + + bResult = confFile.open(QIODevice::WriteOnly | QIODevice::Text); + + // No need to do set content since document data is always updated... + qint64 error = confFile.write(domDoc.toByteArray()); + flushConfig(); + if( -1 == error) + return false; + return true; +} + +bool Config::removeAllProfiles() +{ + // Create a backup file just in case... + profileList.clear(); + QDir dir(CONFIG_DIR); + bool bResult = dir.remove(BACKUP_CONFIG_FILE); + bResult = confFile.copy(BACKUP_CONFIG_FILE); + // Essentially just delete the whole file and re-open + bResult = closeConfig(); + bResult = dir.remove(CONFIG_FILE); + bResult = openConfig(); + return bResult; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..7b5e232 --- /dev/null +++ b/config.h @@ -0,0 +1,71 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include +#include +#include +#include "profile.h" + +#define APPLICATION_NAME "ConfManager" +//#define CONFIG_DIR "/apps/Maemo/" APPLICATION_NAME "/" + +// For test only! +#define CONFIG_DIR "./" + +#define CONFIG_FILE CONFIG_DIR "cfConfig.xml" +#define BACKUP_CONFIG_FILE CONFIG_DIR "cfConfig.bak" + +#define DEFAULT_XML "\r\n\r\n" + +class Config : public QObject +{ + Q_OBJECT +public: + explicit Config(QObject *parent = 0); + + // Close the config file + ~Config() { closeConfig(); } + + // Return 0 if everything okay else a negative integer + int addProfile(const Profile &p); + int removeProfile(const Profile &p); + + // Write back all the changes to the disk + void flushConfig(); + + // Read all the profiles from config file + bool readAllProfiles(); + // Writes all the profiles from the list to the config file + // Similar to flushConfig(), flushConfig will internally call + // writeAllProfiles() + bool writeAllProfiles(); + // Similar to deletion of config file. Never to be used! + bool removeAllProfiles(); + + // get-set for noOfProfiles + void setNoOfProfiles(const int &no) { noOfProfiles = no; } + int getNoOfProfiles() { return noOfProfiles; } + + QList profileList; + + bool openConfig(); + + // Called by flush and + bool closeConfig(); + +private: + + void updateNoOfProfiles(); + + QFile confFile; + QDomDocument domDoc; + int noOfProfiles; + +signals: + +public slots: + +}; + +#endif // CONFIG_H diff --git a/config.xml b/config.xml new file mode 100644 index 0000000..e176ed6 --- /dev/null +++ b/config.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/configure-stamp b/configure-stamp new file mode 100644 index 0000000..e69de29 diff --git a/confmanager.cpp b/confmanager.cpp new file mode 100644 index 0000000..4acbe45 --- /dev/null +++ b/confmanager.cpp @@ -0,0 +1,200 @@ +#include "confmanager.h" +#include +#include + +confManager::confManager(QObject *parent) : + QObject(parent) +{ + mProfileSet = false; + mInStep = 0; +} + +void confManager::setProfile(Profile &p) +{ + mInStep = 0; + mProfileInUse = p; + mProfileSet = true; +} + +void confManager::continueSendDTMF() +{ + // We have now waited for the required period of seconds + // Lets send the DTMF now + Steps step = mProfileInUse.mSteps.at(mInStep); + + // Increment the steps as we want to point to the next one + mInStep++; + + QList argsToSend; + argsToSend.append(step.value()); + + bool status = mDBusUtility.sendMethodCall(CSD_SERVICE, CSD_CALL_PATH, CSD_CALL_INTERFACE, + QString("SendDTMF"),argsToSend); + + if(!status) + { + qDebug() << "Unable to send DTMF code."; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + + // Check if we are over with the sequence or we need to continue + if(mInStep > mProfileInUse.mNoOfSteps) + { + StopCallMonitors(); + return; + } + + step = mProfileInUse.mSteps.at(mInStep); + QTimer *timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, SIGNAL(timeout()), this, SLOT(sendDTMF(const QDBusMessage &))); + timer->start(step.delay()); +} + +void confManager::sendDTMF(const QDBusMessage &dBusMessage) +{ + QList listArguments = dBusMessage.arguments(); + bool audioConnected = listArguments.first().toBool(); + + if(mInStep > mProfileInUse.mNoOfSteps) + { + StopCallMonitors(); + return; + } + + Steps step = mProfileInUse.mSteps.at(mInStep); + + if (audioConnected) + { + qDebug() << "Audio Connected..."; + //Wait for specified delay in the step + QTimer *timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, SIGNAL(timeout()), this, SLOT(continueSendDTMF())); + timer->start(step.delay()); + } +} + +void confManager::StartCallMonitors() +{ + QDBusConnection connection = mDBusUtility.getConnection(); + /* Declare the slot to be executed when a call is picked up by other party (Audio connection established). + We need this to confirm whether a call went though successfully. + */ + bool status = connection.connect(QString(""), CSD_CALL_INSTANCE_PATH, CSD_CALL_INSTANCE_INTERFACE, + QString("AudioConnect"),this, SLOT(sendDTMF(const QDBusMessage&))); + + if(!status) + { + qDebug() << "Failed to connect to Dbus signal AudioConnect in interface "<< CSD_CALL_INSTANCE_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + + qDebug() << "Successfully connected to Dbus signal AudioConnect in interface "<< CSD_CALL_INSTANCE_INTERFACE; + + /* Declare the slot to be executed when the call is terminated (due to connection errors etc). + We need this to avoid sending DTMF code on wrong calls. + */ + status = connection.connect(QString(""), CSD_CALL_INSTANCE_PATH, CSD_CALL_INSTANCE_INTERFACE, + QString("Terminated"),this, SLOT(StopCallMonitors())); + + if(!status) + { + qDebug() << "Failed to connect to Dbus signal Terminated in interface "<< CSD_CALL_INSTANCE_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + + qDebug() << "Successfully connected to Dbus signal Terminated in interface "<< CSD_CALL_INSTANCE_INTERFACE; + + /* Declare the slot to be executed when a call is received + (before we can place the call to calling card number). + It is extremely rare that somebody should get a call within these few seconds. + In any case, we need this to avoid sending DTMF code on the received call. + + Btw - I don't care for the incoming number here. If anyone is calling the user before we can send DTMF code, + then we stop sending the DTMF code even if user does not respond to the call. + */ + + status = connection.connect(QString(""), CSD_CALL_PATH, CSD_CALL_INTERFACE, + QString("Coming"),this, SLOT(StopCallMonitors())); + + if(!status) + { + qDebug() << "Failed to connect to Dbus signal Coming in interface" << CSD_CALL_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + qDebug() << "Successfully connected to Dbus signal Coming in interface" << CSD_CALL_INTERFACE; +} + +void confManager::StopCallMonitors() +{ + mInStep = 0; + mProfileSet = false; + + QDBusConnection connection = mDBusUtility.getConnection(); + + // Disconnect the slot for audio connection status + bool status = connection.disconnect(QString(""), CSD_CALL_INSTANCE_PATH, CSD_CALL_INSTANCE_INTERFACE, + QString("AudioConnect"),this, SLOT(sendDTMF(const QDBusMessage&))); + + if(!status) + { + qDebug() << "Failed to disconnect from Dbus signal AudioConnect in interface" << CSD_CALL_INSTANCE_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + qDebug() << "Successfully disconnected from Dbus signal AudioConnect in interface "<< CSD_CALL_INSTANCE_INTERFACE; + + // Disconnect the slot for monitoring terminated calls + status = connection.disconnect(QString(""), CSD_CALL_INSTANCE_PATH, CSD_CALL_INSTANCE_INTERFACE, + QString("Terminated"),this, SLOT(StopCallMonitors())); + + if(!status) + { + qDebug() << "Failed to disconnect from Dbus signal Terminated in interface" << CSD_CALL_INSTANCE_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + qDebug() << "Successfully disconnected from Dbus signal Terminated in interface "<< CSD_CALL_INSTANCE_INTERFACE; + + // Disconnect the slot for monitoring incoming calls + status = connection.disconnect(QString(""), CSD_CALL_PATH, CSD_CALL_INTERFACE, + QString("Coming"),this, SLOT(StopCallMonitors())); + + if(!status) + { + qDebug() << "Failed to disconnect from Dbus signal Coming in interface" << CSD_CALL_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + qDebug() << "Successfully disconnected from Dbus signal Coming in interface" << CSD_CALL_INTERFACE; +} + +void confManager::startConference() +{ + if(!mProfileSet) + { + qDebug() << "Please set the profile to use with Conference Manager first!"; + return; + } + //Assume that the first number is always a phone number... + Steps step = mProfileInUse.mSteps.at(mInStep); + mInStep++; + QList sendArgs; + sendArgs.append(step.value()); + sendArgs.append(0); + bool status = mDBusUtility.sendMethodCall(CSD_SERVICE, CSD_CALL_PATH, CSD_CALL_INTERFACE, + QString("CreateWith"), sendArgs); + if(!status) + { + QString error = "Error while dialing: " + mDBusUtility.getErrorMessage(); + qDebug() << error; + mDBusUtility.displayNotification(error); + return; + } + StartCallMonitors(); +} diff --git a/confmanager.h b/confmanager.h new file mode 100644 index 0000000..5e86bba --- /dev/null +++ b/confmanager.h @@ -0,0 +1,38 @@ +#ifndef CONFMANAGER_H +#define CONFMANAGER_H + +#include "profile.h" +#include "dbusutility.h" + +#define CSD_CALL_BUS_NAME "com.nokia.csd.Call" +#define CSD_CALL_INTERFACE "com.nokia.csd.Call" +#define CSD_CALL_INSTANCE_INTERFACE "com.nokia.csd.Call.Instance" +#define CSD_CALL_CONFERENCE "com.nokia.csd.Call.Conference" +#define CSD_CALL_PATH "/com/nokia/csd/call" +#define CSD_CALL_INSTANCE_PATH "/com/nokia/csd/call/1" +#define CSD_CALL_SERVICE "com.nokia.csd.Call" +#define CSD_SERVICE "com.nokia.csd" + +class confManager : public QObject +{ + Q_OBJECT +public: + explicit confManager(QObject *parent = 0); + + void setProfile(Profile &p); + void startConference(); + +private: + void sendDTMF(const QDBusMessage &dBusMessage); + void StartCallMonitors(); + void StopCallMonitors(); + void continueSendDTMF(); + +private: + Profile mProfileInUse; + bool mProfileSet; + DbusUtility mDBusUtility; + unsigned int mInStep; +}; + +#endif // CONFMANAGER_H diff --git a/confmgr b/confmgr new file mode 100755 index 0000000000000000000000000000000000000000..dddcc7236f0882dfa573c32d8365e95a66c44418 GIT binary patch literal 150991 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

Uvr#>)I@+OP>@#^-s9Cxlgpz_b*ZlbWdhv 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 rb<*Qsaj#V!=bogBW5aDKY + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + System + + + + ProjectExplorer.Project.Target.0 + + Maemo + Qt4ProjectManager.Target.MaemoDeviceTarget + 0 + 0 + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + + + Qt4ProjectManager.MaemoPackageCreationStep + + false + /usr/local/bin/confmgr + + + 3 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Qt for Fremantle PR1.2 Devices (Nokia Qt SDK) Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /home/naresh/Documents/dev/maemo/confmgr-build-maemo + 3 + 9 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + + + Qt4ProjectManager.MaemoPackageCreationStep + + true + /usr/local/bin/confmgr + + + 3 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Qt for Fremantle PR1.2 Devices (Nokia Qt SDK) Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /home/naresh/Documents/dev/maemo/confmgr-build-maemo + 3 + 9 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + + + Qt4ProjectManager.MaemoPackageCreationStep + + false + /usr/local/bin/confmgr + + + 3 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Maemo Qt4.5 Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /home/naresh/Documents/dev/maemo/confmgr-build-maemo + 8 + 9 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + + + Qt4ProjectManager.MaemoPackageCreationStep + + true + + + + 3 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Maemo Qt4.5 Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /home/naresh/Documents/dev/maemo/confmgr-build-maemo + 8 + 9 + true + + 4 + + confmgr.pro + New Maemo Run Configuration + Qt4ProjectManager.MaemoRunConfiguration + + + 9 + + 2010-07-04T02:11:42 + + + 1 + + + + ProjectExplorer.Project.Target.1 + + Qt Simulator + Qt4ProjectManager.Target.QtSimulatorTarget + 0 + 0 + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /home/naresh/Documents/dev/maemo/confmgr-build-simulator + 2 + 0 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /home/naresh/Documents/dev/maemo/confmgr-build-simulator + 2 + 0 + true + + 2 + + confmgr + Qt4ProjectManager.Qt4RunConfiguration + 2 + + confmgr.pro + false + false + + false + false + + + 1 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 4 + + diff --git a/dbusutility.cpp b/dbusutility.cpp new file mode 100644 index 0000000..7412667 --- /dev/null +++ b/dbusutility.cpp @@ -0,0 +1,71 @@ +/* +@version: 0.1 +@author: Sudheer K. +@license: GNU General Public License +*/ + +#include "dbusutility.h" +#include +#include + + +//Construction is available in the header file due to a peculiar issue with systemBus() function. + + +//Destructor for Dbus Utility object. +DbusUtility::~DbusUtility(){ + this->connection.disconnectFromBus(this->connection.baseService()); + qDebug() << "Disconnected from system bus"; +} + +QDBusConnection DbusUtility::getConnection(){ + if (!this->connection.isConnected()){ + qDebug() << "Not connected to Dbus"; + } + return this->connection; +} + +void DbusUtility::setConnection(QDBusConnection connection){ + this->connection = connection; +} + +//Utility method to send a dbus signal. +bool DbusUtility::sendSignal(QString strPath,QString strInterface,QString strName){ + QDBusMessage dbusSignal = QDBusMessage::createSignal(strPath,strInterface,strName); + bool status = DbusUtility::connection.send(dbusSignal); + return status; +} + +//Utility method to call a dbus method with parameters +bool DbusUtility::sendMethodCall(QString strService,QString strPath, + QString strInterface,QString strMethodName, + QList & arguments){ + QDBusMessage dbusMethodCall = QDBusMessage::createMethodCall(strService,strPath,strInterface,strMethodName); + dbusMethodCall.setArguments(arguments); + bool status = DbusUtility::connection.send(dbusMethodCall); + return status; +} + +//Utility method to display a notification (Orange sliding banner in Maemo) with custom message +bool DbusUtility::displayNotification(QString strMessage){ + QList arguments; + arguments.append(strMessage); + + bool status = this->sendMethodCall(NOTIFICATION_SERVICE, + NOTIFICATION_PATH, + NOTIFICATION_INTERFACE, + QString("SystemNoteInfoprint"), + arguments); + return status; +} + + +//Utility method to retrieve the last dbus error +QString DbusUtility::getErrorMessage(){ + QString strErrorMessage; + QDBusError dbusError = this->connection.lastError(); + if (dbusError.isValid()){ + strErrorMessage = qPrintable(dbusError.message()); + } + return strErrorMessage; +} diff --git a/dbusutility.h b/dbusutility.h new file mode 100644 index 0000000..0fb0a10 --- /dev/null +++ b/dbusutility.h @@ -0,0 +1,35 @@ +/* +@version: 0.1 +@author: Sudheer K. +@license: GNU General Public License +*/ + +#ifndef DBUSUTILITY_H +#define DBUSUTILITY_H + +#include +#include + +#define NOTIFICATION_SERVICE "org.freedesktop.Notifications" +#define NOTIFICATION_PATH "/org/freedesktop/Notifications" +#define NOTIFICATION_INTERFACE "org.freedesktop.Notifications" + +class DbusUtility +{ +protected: + QDBusConnection connection; +public: + DbusUtility():connection(QDBusConnection::systemBus()) + {} + ~DbusUtility(); + QDBusConnection getConnection(); + void setConnection(QDBusConnection connection); + bool sendSignal(QString strPath,QString strInterface,QString strName); + bool sendMethodCall(QString strService,QString strPath, + QString strInterface,QString strMethodName, + QList & arguments); + bool displayNotification(QString strMessage); + QString getErrorMessage(); +}; + +#endif // DBUSUTILITY_H diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..967f739 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,6 @@ +confmgr for Debian +------------------ + + + + -- Naresh Mehta Mon, 5 Jul 2010 15:23:39 +0200 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..69dfe24 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +confmgr (0.1-1) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- Naresh Mehta Mon, 5 Jul 2010 15:23:39 +0200 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/confmgr-default.ex b/debian/confmgr-default.ex new file mode 100644 index 0000000..9a7ff58 --- /dev/null +++ b/debian/confmgr-default.ex @@ -0,0 +1,10 @@ +# Defaults for confmgr initscript +# sourced by /etc/init.d/confmgr +# installed at /etc/default/confmgr by the maintainer scripts + +# +# This is a POSIX shell fragment +# + +# Additional options that are passed to the Daemon. +DAEMON_OPTS="" diff --git a/debian/confmgr.doc-base.EX b/debian/confmgr.doc-base.EX new file mode 100644 index 0000000..4f535d3 --- /dev/null +++ b/debian/confmgr.doc-base.EX @@ -0,0 +1,22 @@ +Document: confmgr +Title: Debian confmgr Manual +Author: +Abstract: This manual describes what confmgr is + and how it can be used to + manage online manuals on Debian systems. +Section: unknown + +Format: debiandoc-sgml +Files: /usr/share/doc/confmgr/confmgr.sgml.gz + +Format: postscript +Files: /usr/share/doc/confmgr/confmgr.ps.gz + +Format: text +Files: /usr/share/doc/confmgr/confmgr.text.gz + +Format: HTML +Index: /usr/share/doc/confmgr/html/index.html +Files: /usr/share/doc/confmgr/html/*.html + + diff --git a/debian/confmgr/DEBIAN/control b/debian/confmgr/DEBIAN/control new file mode 100644 index 0000000..fffb1e4 --- /dev/null +++ b/debian/confmgr/DEBIAN/control @@ -0,0 +1,9 @@ +Package: confmgr +Version: 0.1-1 +Section: unknown +Priority: extra +Architecture: i386 +Installed-Size: 44 +Maintainer: Naresh Mehta +Description: Conference calling at your fingertips + Conference Manager makes dialing a conference call a single click operation. All you need to do is create your desired profiles using the easy to use GUI and add the relevant steps as required by the conference provider. You can use unlimited profiles. All the profiles are stored in an easy to use XML file which can be edited outside the environment if needed. Future versions will also include integration with phonebook to get the conference numbers automatically. diff --git a/debian/confmgr/DEBIAN/md5sums b/debian/confmgr/DEBIAN/md5sums new file mode 100644 index 0000000..5ea8b93 --- /dev/null +++ b/debian/confmgr/DEBIAN/md5sums @@ -0,0 +1,3 @@ +28df2b19218f8caf6f2d894495abc955 usr/share/doc/confmgr/README.Debian +54b6b5a17189968bdbff4d2ae6c3d06c usr/share/doc/confmgr/changelog.Debian.gz +868ece277a756bf4394033b6e295c97b usr/share/doc/confmgr/copyright diff --git a/debian/confmgr/usr/share/doc/confmgr/README.Debian b/debian/confmgr/usr/share/doc/confmgr/README.Debian new file mode 100644 index 0000000..967f739 --- /dev/null +++ b/debian/confmgr/usr/share/doc/confmgr/README.Debian @@ -0,0 +1,6 @@ +confmgr for Debian +------------------ + + + + -- Naresh Mehta Mon, 5 Jul 2010 15:23:39 +0200 diff --git a/debian/confmgr/usr/share/doc/confmgr/changelog.Debian.gz b/debian/confmgr/usr/share/doc/confmgr/changelog.Debian.gz new file mode 100644 index 0000000000000000000000000000000000000000..db59fd167b1459d86b08a1848b3566ee699bfec8 GIT binary patch literal 188 zcmV;t07L&DiwFqe+%Zf717m1mZf9j|Z)YwIR>+LE@@Q{|=gq9{R qx7n|*f2EFUpf&mk6u1Y4j0+A?R9Rl-B@R5}oUsq2GQ$_R000193{w68 literal 0 HcmV?d00001 diff --git a/debian/confmgr/usr/share/doc/confmgr/copyright b/debian/confmgr/usr/share/doc/confmgr/copyright new file mode 100644 index 0000000..a090127 --- /dev/null +++ b/debian/confmgr/usr/share/doc/confmgr/copyright @@ -0,0 +1,35 @@ +This package was debianized by Naresh Mehta on +Mon, 5 Jul 2010 15:23:39 +0200. + +It was downloaded from + +Upstream Author: + +Copyright: + +License: + + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + +The Debian packaging is (C) 2010, Naresh Mehta and +is licensed under the GPL, see above. + + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..186ab8c --- /dev/null +++ b/debian/control @@ -0,0 +1,12 @@ +Source: confmgr +Section: unknown +Priority: extra +Maintainer: Naresh Mehta +Build-Depends: debhelper (>= 5), libqt4-dev (>= 4.6.1) +Standards-Version: 3.7.2 + +Package: confmgr +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Conference calling at your fingertips + Conference Manager makes dialing a conference call a single click operation. All you need to do is create your desired profiles using the easy to use GUI and add the relevant steps as required by the conference provider. You can use unlimited profiles. All the profiles are stored in an easy to use XML file which can be edited outside the environment if needed. Future versions will also include integration with phonebook to get the conference numbers automatically. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..a090127 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,35 @@ +This package was debianized by Naresh Mehta on +Mon, 5 Jul 2010 15:23:39 +0200. + +It was downloaded from + +Upstream Author: + +Copyright: + +License: + + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + +The Debian packaging is (C) 2010, Naresh Mehta and +is licensed under the GPL, see above. + + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. diff --git a/debian/cron.d.ex b/debian/cron.d.ex new file mode 100644 index 0000000..26eff40 --- /dev/null +++ b/debian/cron.d.ex @@ -0,0 +1,4 @@ +# +# Regular cron jobs for the confmgr package +# +0 4 * * * root confmgr_maintenance diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..ca882bb --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e69de29 diff --git a/debian/emacsen-install.ex b/debian/emacsen-install.ex new file mode 100644 index 0000000..6ff4c16 --- /dev/null +++ b/debian/emacsen-install.ex @@ -0,0 +1,45 @@ +#! /bin/sh -e +# /usr/lib/emacsen-common/packages/install/confmgr + +# Written by Jim Van Zandt , borrowing heavily +# from the install scripts for gettext by Santiago Vila +# and octave by Dirk Eddelbuettel . + +FLAVOR=$1 +PACKAGE=confmgr + +if [ ${FLAVOR} = emacs ]; then exit 0; fi + +echo install/${PACKAGE}: Handling install for emacsen flavor ${FLAVOR} + +#FLAVORTEST=`echo $FLAVOR | cut -c-6` +#if [ ${FLAVORTEST} = xemacs ] ; then +# SITEFLAG="-no-site-file" +#else +# SITEFLAG="--no-site-file" +#fi +FLAGS="${SITEFLAG} -q -batch -l path.el -f batch-byte-compile" + +ELDIR=/usr/share/emacs/site-lisp/${PACKAGE} +ELCDIR=/usr/share/${FLAVOR}/site-lisp/${PACKAGE} + +# Install-info-altdir does not actually exist. +# Maybe somebody will write it. +if test -x /usr/sbin/install-info-altdir; then + echo install/${PACKAGE}: install Info links for ${FLAVOR} + install-info-altdir --quiet --section "" "" --dirname=${FLAVOR} /usr/info/${PACKAGE}.info.gz +fi + +install -m 755 -d ${ELCDIR} +cd ${ELDIR} +FILES=`echo *.el` +cp ${FILES} ${ELCDIR} +cd ${ELCDIR} + +cat << EOF > path.el +(setq load-path (cons "." load-path) byte-compile-warnings nil) +EOF +${FLAVOR} ${FLAGS} ${FILES} +rm -f *.el path.el + +exit 0 diff --git a/debian/emacsen-remove.ex b/debian/emacsen-remove.ex new file mode 100644 index 0000000..95f0ff6 --- /dev/null +++ b/debian/emacsen-remove.ex @@ -0,0 +1,15 @@ +#!/bin/sh -e +# /usr/lib/emacsen-common/packages/remove/confmgr + +FLAVOR=$1 +PACKAGE=confmgr + +if [ ${FLAVOR} != emacs ]; then + if test -x /usr/sbin/install-info-altdir; then + echo remove/${PACKAGE}: removing Info links for ${FLAVOR} + install-info-altdir --quiet --remove --dirname=${FLAVOR} /usr/info/confmgr.info.gz + fi + + echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR} + rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE} +fi diff --git a/debian/emacsen-startup.ex b/debian/emacsen-startup.ex new file mode 100644 index 0000000..13b8943 --- /dev/null +++ b/debian/emacsen-startup.ex @@ -0,0 +1,25 @@ +;; -*-emacs-lisp-*- +;; +;; Emacs startup file, e.g. /etc/emacs/site-start.d/50confmgr.el +;; for the Debian confmgr package +;; +;; Originally contributed by Nils Naumann +;; Modified by Dirk Eddelbuettel +;; Adapted for dh-make by Jim Van Zandt + +;; The confmgr package follows the Debian/GNU Linux 'emacsen' policy and +;; byte-compiles its elisp files for each 'emacs flavor' (emacs19, +;; xemacs19, emacs20, xemacs20...). The compiled code is then +;; installed in a subdirectory of the respective site-lisp directory. +;; We have to add this to the load-path: +(let ((package-dir (concat "/usr/share/" + (symbol-name flavor) + "/site-lisp/confmgr"))) +;; If package-dir does not exist, the confmgr package must have +;; removed but not purged, and we should skip the setup. + (when (file-directory-p package-dir) + (setq load-path (cons package-dir load-path)) + (autoload 'confmgr-mode "confmgr-mode" + "Major mode for editing confmgr files." t) + (add-to-list 'auto-mode-alist '("\\.confmgr$" . confmgr-mode)))) + diff --git a/debian/files b/debian/files new file mode 100644 index 0000000..8ed3324 --- /dev/null +++ b/debian/files @@ -0,0 +1 @@ +confmgr_0.1-1_i386.deb unknown extra diff --git a/debian/init.d.ex b/debian/init.d.ex new file mode 100644 index 0000000..4d44816 --- /dev/null +++ b/debian/init.d.ex @@ -0,0 +1,81 @@ +#! /bin/sh +# +# skeleton example file to build /etc/init.d/ scripts. +# This file should be used to construct scripts for /etc/init.d. +# +# Written by Miquel van Smoorenburg . +# Modified for Debian +# by Ian Murdock . +# +# Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl +# + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/sbin/confmgr +NAME=confmgr +DESC=confmgr + +test -x $DAEMON || exit 0 + +# Include confmgr defaults if available +if [ -f /etc/default/confmgr ] ; then + . /etc/default/confmgr +fi + +set -e + +case "$1" in + start) + echo -n "Starting $DESC: " + start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ + --exec $DAEMON -- $DAEMON_OPTS + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \ + --exec $DAEMON + echo "$NAME." + ;; + #reload) + # + # If the daemon can reload its config files on the fly + # for example by sending it SIGHUP, do it here. + # + # If the daemon responds to changes in its config file + # directly anyway, make this a do-nothing entry. + # + # echo "Reloading $DESC configuration files." + # start-stop-daemon --stop --signal 1 --quiet --pidfile \ + # /var/run/$NAME.pid --exec $DAEMON + #;; + force-reload) + # + # If the "reload" option is implemented, move the "force-reload" + # option to the "reload" entry above. If not, "force-reload" is + # just the same as "restart" except that it does nothing if the + # daemon isn't already running. + # check wether $DAEMON is running. If so, restart + start-stop-daemon --stop --test --quiet --pidfile \ + /var/run/$NAME.pid --exec $DAEMON \ + && $0 restart \ + || exit 0 + ;; + restart) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --pidfile \ + /var/run/$NAME.pid --exec $DAEMON + sleep 1 + start-stop-daemon --start --quiet --pidfile \ + /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS + echo "$NAME." + ;; + *) + N=/etc/init.d/$NAME + # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/debian/manpage.1.ex b/debian/manpage.1.ex new file mode 100644 index 0000000..745a619 --- /dev/null +++ b/debian/manpage.1.ex @@ -0,0 +1,59 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH CONFMGR SECTION "July 5, 2010" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +confmgr \- program to do something +.SH SYNOPSIS +.B confmgr +.RI [ options ] " files" ... +.br +.B bar +.RI [ options ] " files" ... +.SH DESCRIPTION +This manual page documents briefly the +.B confmgr +and +.B bar +commands. +.PP +.\" TeX users may be more comfortable with the \fB\fP and +.\" \fI\fP escape sequences to invode bold face and italics, +.\" respectively. +\fBconfmgr\fP is a program that... +.SH OPTIONS +These programs follow the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +For a complete description, see the Info files. +.TP +.B \-h, \-\-help +Show summary of options. +.TP +.B \-v, \-\-version +Show version of program. +.SH SEE ALSO +.BR bar (1), +.BR baz (1). +.br +The programs are documented fully by +.IR "The Rise and Fall of a Fooish Bar" , +available via the Info system. +.SH AUTHOR +confmgr was written by . +.PP +This manual page was written by Naresh Mehta , +for the Debian project (but may be used by others). diff --git a/debian/manpage.sgml.ex b/debian/manpage.sgml.ex new file mode 100644 index 0000000..3fa2ece --- /dev/null +++ b/debian/manpage.sgml.ex @@ -0,0 +1,156 @@ + manpage.1'. You may view + the manual page with: `docbook-to-man manpage.sgml | nroff -man | + less'. A typical entry in a Makefile or Makefile.am is: + +manpage.1: manpage.sgml + docbook-to-man $< > $@ + + + The docbook-to-man binary is found in the docbook-to-man package. + Please remember that if you create the nroff version in one of the + debian/rules file targets (such as build), you will need to include + docbook-to-man in your Build-Depends control field. + + --> + + + FIRSTNAME"> + SURNAME"> + + July 5, 2010"> + + SECTION"> + naresh@naresh.se"> + + CONFMGR"> + + + Debian"> + GNU"> + GPL"> +]> + + + +

+ &dhemail; +
+ + &dhfirstname; + &dhsurname; + + + 2003 + &dhusername; + + &dhdate; + + + &dhucpackage; + + &dhsection; + + + &dhpackage; + + program to do something + + + + &dhpackage; + + + + + + + + DESCRIPTION + + This manual page documents briefly the + &dhpackage; and bar + commands. + + This manual page was written for the &debian; distribution + because the original program does not have a manual page. + Instead, it has documentation in the &gnu; + Info format; see below. + + &dhpackage; is a program that... + + + + OPTIONS + + These programs follow the usual &gnu; command line syntax, + with long options starting with two dashes (`-'). A summary of + options is included below. For a complete description, see the + Info files. + + + + + + + + Show summary of options. + + + + + + + + Show version of program. + + + + + + SEE ALSO + + bar (1), baz (1). + + The programs are documented fully by The Rise and + Fall of a Fooish Bar available via the + Info system. + + + AUTHOR + + This manual page was written by &dhusername; &dhemail; for + the &debian; system (but may be used by others). Permission is + granted to copy, distribute and/or modify this document under + the terms of the &gnu; General Public License, Version 2 any + later version published by the Free Software Foundation. + + + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL. + + + + + + + + diff --git a/debian/manpage.xml.ex b/debian/manpage.xml.ex new file mode 100644 index 0000000..6572f61 --- /dev/null +++ b/debian/manpage.xml.ex @@ -0,0 +1,148 @@ + +.
will be generated. You may view the +manual page with: nroff -man .
| less'. A +typical entry in a Makefile or Makefile.am is: + +DB2MAN=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/\ +manpages/docbook.xsl +XP=xsltproc -''-nonet + +manpage.1: manpage.dbk + $(XP) $(DB2MAN) $< + +The xsltproc binary is found in the xsltproc package. The +XSL files are in docbook-xsl. Please remember that if you +create the nroff version in one of the debian/rules file +targets (such as build), you will need to include xsltproc +and docbook-xsl in your Build-Depends control field. + +--> + + + FIRSTNAME"> + SURNAME"> + + July 5, 2010"> + + SECTION"> + naresh@naresh.se"> + + CONFMGR"> + + + Debian"> + GNU"> + GPL"> +]> + + + +
+ &dhemail; +
+ + &dhfirstname; + &dhsurname; + + + 2003 + &dhusername; + + &dhdate; +
+ + &dhucpackage; + + &dhsection; + + + &dhpackage; + + program to do something + + + + &dhpackage; + + + + + + + + DESCRIPTION + + This manual page documents briefly the + &dhpackage; and bar + commands. + + This manual page was written for the &debian; distribution + because the original program does not have a manual page. + Instead, it has documentation in the &gnu; + Info format; see below. + + &dhpackage; is a program that... + + + + OPTIONS + + These programs follow the usual &gnu; command line syntax, + with long options starting with two dashes (`-'). A summary of + options is included below. For a complete description, see the + Info files. + + + + + + + + Show summary of options. + + + + + + + + Show version of program. + + + + + + SEE ALSO + + bar (1), baz (1). + + The programs are documented fully by The Rise and + Fall of a Fooish Bar available via the + Info system. + + + AUTHOR + + This manual page was written by &dhusername; &dhemail; for + the &debian; system (but may be used by others). Permission is + granted to copy, distribute and/or modify this document under + the terms of the &gnu; General Public License, Version 2 any + later version published by the Free Software Foundation. + + + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL. + + + +
+ diff --git a/debian/menu.ex b/debian/menu.ex new file mode 100644 index 0000000..cf94c35 --- /dev/null +++ b/debian/menu.ex @@ -0,0 +1,2 @@ +?package(confmgr):needs="X11|text|vc|wm" section="Apps/see-menu-manual"\ + title="confmgr" command="/usr/bin/confmgr" diff --git a/debian/postinst.ex b/debian/postinst.ex new file mode 100644 index 0000000..727537d --- /dev/null +++ b/debian/postinst.ex @@ -0,0 +1,41 @@ +#!/bin/sh +# postinst script for confmgr +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/debian/postrm.ex b/debian/postrm.ex new file mode 100644 index 0000000..6eeb1de --- /dev/null +++ b/debian/postrm.ex @@ -0,0 +1,39 @@ +#!/bin/sh +# postrm script for confmgr +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/debian/preinst.ex b/debian/preinst.ex new file mode 100644 index 0000000..41de04a --- /dev/null +++ b/debian/preinst.ex @@ -0,0 +1,37 @@ +#!/bin/sh +# preinst script for confmgr +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `install' +# * `install' +# * `upgrade' +# * `abort-upgrade' +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/debian/prerm.ex b/debian/prerm.ex new file mode 100644 index 0000000..abdd20e --- /dev/null +++ b/debian/prerm.ex @@ -0,0 +1,40 @@ +#!/bin/sh +# prerm script for confmgr +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..3adfc4c --- /dev/null +++ b/debian/rules @@ -0,0 +1,102 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +APPNAME := confmgr + +builddir: + mkdir -p builddir + +builddir/Makefile: builddir + cd builddir && qmake-qt4 PREFIX=/usr ../$(APPNAME).pro + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + qmake confmgr.pro + + touch configure-stamp + + +build: build-stamp + +build-stamp: builddir/Makefile + dh_testdir + + # Add here commands to compile the package. + cd builddir && $(MAKE) + #docbook-to-man debian/confmgr.sgml > confmgr.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + # Add here commands to clean up after the build process. + rm -rf builddir + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/confmgr. + cd builddir && $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/$(APPNAME) install + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples + dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip --dbg-package=confmgr-dbg + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/debian/watch.ex b/debian/watch.ex new file mode 100644 index 0000000..95b8208 --- /dev/null +++ b/debian/watch.ex @@ -0,0 +1,22 @@ +# Example watch control file for uscan +# Rename this file to "watch" and then you can run the "uscan" command +# to check for upstream updates and more. +# See uscan(1) for format + +# Compulsory line, this is a version 3 file +version=3 + +# Uncomment to examine a Webpage +# +#http://www.example.com/downloads.php confmgr-(.*)\.tar\.gz + +# Uncomment to examine a Webserver directory +#http://www.example.com/pub/confmgr-(.*)\.tar\.gz + +# Uncommment to examine a FTP server +#ftp://ftp.example.com/pub/confmgr-(.*)\.tar\.gz debian uupdate + +# Uncomment to find new files on sourceforge, for debscripts >= 2.9 +# http://sf.net/confmgr/confmgr-(.*)\.tar\.gz + + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..d6a9241 --- /dev/null +++ b/main.cpp @@ -0,0 +1,20 @@ +#include +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; +#if defined(Q_WS_S60) + w.showMaximized(); +/* +#elseif defined(Q_WS_MAEMO_5) + w.setPortraitMode(); + w.showMaximized(); +*/ +#else + w.show(); +#endif + + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..1afe99a --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,108 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "xmlutil.h" +#include +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + connect(&mFrmAddProfile, SIGNAL(ProfileAddedSuccessfully(Profile)), + this, SLOT(updateProfileList(Profile))); + Initialize(); +} + +MainWindow::~MainWindow() +{ + mConfig.writeAllProfiles(); + mConfig.closeConfig(); + delete ui; +} + +void MainWindow::Initialize() +{ + mConfig.openConfig(); + for(int i = 0; i < mConfig.getNoOfProfiles(); i++) + { + Profile p = mConfig.profileList.at(i); + QString text = "Name: " + p.mName + " || Steps: " + QString::number(p.mNoOfSteps); + ui->mainProfileList->addItem(text); + } + ui->centralWidget->setAttribute(Qt::WA_Maemo5StackedWindow); + mFrmAddProfile.setWindowFlags(mFrmAddProfile.windowFlags() | Qt::Window); +} + +void MainWindow::on_mainPBAdd_clicked() +{ + bIsProfileEdited = false; + mFrmAddProfile.setParent(this, Qt::Window); + mFrmAddProfile.clear(); + mFrmAddProfile.setAttribute(Qt::WA_Maemo5StackedWindow); + mFrmAddProfile.show(); +} + +void MainWindow::updateProfileList(Profile p) +{ + if(bIsProfileEdited) + { + // Delete previous profile and write this new one + QString *pText = (QString *) ui->mainProfileList->takeItem(ui->mainProfileList->currentRow()); + delete pText; + mConfig.removeProfile(p); + } + qDebug() << Xmlutil::generateProfileXML(p); + mConfig.addProfile(p); + QString text = "Name: " + p.mName + " || Steps: " + QString::number(p.mNoOfSteps); + ui->mainProfileList->addItem(text); +} + +void MainWindow::on_mainPBDelete_clicked() +{ + if(ui->mainProfileList->count() <= 0 || ui->mainProfileList->currentRow() < 0) + { + QMessageBox msg; + msg.setText("Please select a profile first!"); + msg.exec(); + return; + } + + Profile p = mConfig.profileList.at(ui->mainProfileList->currentRow()); + qDebug() << "Profile to be deleted: " << endl << Xmlutil::generateProfileXML(p); + QString *pText = (QString *) ui->mainProfileList->takeItem(ui->mainProfileList->currentRow()); + delete pText; + mConfig.removeProfile(p); +} + +void MainWindow::on_btnmainStartConference_clicked() +{ + if(ui->mainProfileList->count() <= 0 || ui->mainProfileList->currentRow() < 0) + { + QMessageBox msg; + msg.setText("Please select a profile first!"); + msg.exec(); + return; + } + Profile p = mConfig.profileList.at(ui->mainProfileList->currentRow()); + qDebug() << "Profile To Dial: " << endl << Xmlutil::generateProfileXML(p); + mConfMgr.setProfile(p); + mConfMgr.startConference(); +} + +void MainWindow::on_mainPBEditProfile_clicked() +{ + if(ui->mainProfileList->count() <= 0 || ui->mainProfileList->currentRow() < 0) + { + QMessageBox msg; + msg.setText("Please select a profile first!"); + msg.exec(); + return; + } + bIsProfileEdited = true; + Profile p = mConfig.profileList.at(ui->mainProfileList->currentRow()); + qDebug() << "Profile to be Edited: " << endl << Xmlutil::generateProfileXML(p); + mFrmAddProfile.setParent(this, Qt::Window); + mFrmAddProfile.setAttribute(Qt::WA_Maemo5StackedWindow); + mFrmAddProfile.showProfile(p); +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..7ba7612 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,46 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "config.h" +#include "addprofile.h" +#include "confmanager.h" + +namespace Ui { + class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +#if defined(Q_WS_MAEMO_5) + void setPortraitMode() { setAttribute(Qt::WA_Maemo5PortraitOrientation, true); } +#endif + + void Initialize(); + +public slots: + void updateProfileList(Profile p); + +private: + Ui::MainWindow *ui; + Config mConfig; + AddProfile mFrmAddProfile; + bool bIsProfileEdited; + confManager mConfMgr; + QMenuBar *pMenu; + +private slots: + void on_mainPBEditProfile_clicked(); + void on_btnmainStartConference_clicked(); + void on_mainPBDelete_clicked(); + void on_mainPBAdd_clicked(); +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..10fbdcb --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,141 @@ + + + MainWindow + + + + 0 + 0 + 800 + 424 + + + + Conference Manager + + + + + + 30 + 260 + 351 + 141 + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + Start Conference + + + + + + + + 0 + 0 + + + + Add Profile + + + + + + + + + 25 + 4 + 751 + 241 + + + + + + + 420 + 260 + 351 + 141 + + + + + + + + 0 + 0 + + + + Edit Profile + + + + + + + + 0 + 0 + + + + Delete Profile + + + + + + + + 0 + 0 + + + + Exit + + + + + + + + + + + + mainPBQuit + clicked() + MainWindow + close() + + + 411 + 440 + + + 399 + 239 + + + + + diff --git a/profile.cpp b/profile.cpp new file mode 100644 index 0000000..273f4dc --- /dev/null +++ b/profile.cpp @@ -0,0 +1,34 @@ +#include "profile.h" +#include "xmlutil.h" +#include +#include + +Profile::Profile(QObject *parent) : + QObject(parent) +{ + mSteps.clear(); + mNoOfSteps = 0; +} + +Profile::Profile(const Profile &p) +{ + *this = p; +} + +Profile::~Profile() +{ + mSteps.clear(); +} + +Profile& Profile::operator =(const Profile &p) +{ + if(this != &p) + { + mXMLString = p.mXMLString; + mName = p.mName; + mNoOfSteps = p.mNoOfSteps; + mSteps.clear(); + mSteps = p.mSteps; + } + return *this; +} diff --git a/profile.h b/profile.h new file mode 100644 index 0000000..377fb0d --- /dev/null +++ b/profile.h @@ -0,0 +1,49 @@ +#ifndef PROFILE_H +#define PROFILE_H + +#include +#include + +class Steps +{ +public: + Steps() { } + Steps(const QString &value, const int &delay) : mValue(value), mDelay(delay) {} + ~Steps() { } + + // Getters... + QString value() { return mValue; } + int delay() { return mDelay; } + + // Setters... + void setValue(const QString &value) { mValue = value; } + void setDelay(const int &delay) { mDelay = delay; } + +private: + QString mValue; + int mDelay; +}; + +class Profile : public QObject +{ + Q_OBJECT +public: + explicit Profile(QObject *parent = 0); + Profile(const Profile &p); + ~Profile(); + + Profile& operator=(const Profile &p); + + QList mSteps; + + QString mXMLString; + QString mName; + unsigned int mNoOfSteps; // assumed number of steps no more then 255 and always positive! + +signals: + +public slots: + +}; + +#endif // PROFILE_H diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..27fb321 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,365 @@ +############################################################################# +# Makefile for building: confmgr +# Generated by qmake (2.01a) (Qt 4.6.2) on: Sat Jul 3 23:40:14 2010 +# Project: confmgr.pro +# Template: app +# Command: /usr/bin/qmake -unix -o Makefile confmgr.pro +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DQT_NO_DEBUG -DQT_MAEMO5_LIB -DQT_DBUS_LIB -DQT_XML_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) +CXXFLAGS = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) +INCPATH = -I/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/linux-g++ -I. -I/targets/FREMANTLE_X86/usr/include/QtCore -I/targets/FREMANTLE_X86/usr/include/QtGui -I/targets/FREMANTLE_X86/usr/include/QtXml -I/targets/FREMANTLE_X86/usr/include/QtDBus -I/targets/FREMANTLE_X86/usr/include/QtMaemo5 -I/targets/FREMANTLE_X86/usr/include -I. -I. +LINK = g++ +LFLAGS = -Wl,-O1 -Wl,-rpath,/usr/lib +LIBS = $(SUBLIBS) -L/usr/lib -lQtMaemo5 -L/usr/lib -L/usr/X11R6/lib -lQtDBus -lQtXml -lQtGui -lQtCore -lpthread +AR = ar cqs +RANLIB = +QMAKE = /usr/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +STRIP = strip +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = ./ + +####### Files + +SOURCES = main.cpp \ + mainwindow.cpp \ + xmlutil.cpp \ + profile.cpp \ + config.cpp \ + addprofile.cpp \ + addstep.cpp \ + dbusutility.cpp \ + confmanager.cpp moc_mainwindow.cpp \ + moc_xmlutil.cpp \ + moc_profile.cpp \ + moc_config.cpp \ + moc_addprofile.cpp \ + moc_addstep.cpp \ + moc_confmanager.cpp +OBJECTS = main.o \ + mainwindow.o \ + xmlutil.o \ + profile.o \ + config.o \ + addprofile.o \ + addstep.o \ + dbusutility.o \ + confmanager.o \ + moc_mainwindow.o \ + moc_xmlutil.o \ + moc_profile.o \ + moc_config.o \ + moc_addprofile.o \ + moc_addstep.o \ + moc_confmanager.o +DIST = /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/common/g++.conf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/common/unix.conf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/common/linux.conf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/qconfig.pri \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/qt_functions.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/qt_config.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/exclusive_builds.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/default_pre.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/release.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/default_post.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/warn_on.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/qt.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/moc.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/dbusinterfaces.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/dbusadaptors.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/unix/thread.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/resources.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/uic.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/yacc.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/lex.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/include_source_dir.prf \ + confmgr.pro +QMAKE_TARGET = confmgr +DESTDIR = +TARGET = confmgr + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile $(TARGET) + +$(TARGET): ui_mainwindow.h ui_addprofile.h ui_addstep.h $(OBJECTS) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) + +Makefile: confmgr.pro /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/linux-g++/qmake.conf /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/common/g++.conf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/common/unix.conf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/common/linux.conf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/qconfig.pri \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/qt_functions.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/qt_config.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/exclusive_builds.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/default_pre.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/release.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/default_post.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/warn_on.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/qt.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/moc.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/dbusinterfaces.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/dbusadaptors.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/unix/thread.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/resources.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/uic.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/yacc.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/lex.prf \ + /targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/include_source_dir.prf \ + /usr/lib/libQtMaemo5.prl \ + /usr/lib/libQtDBus.prl \ + /usr/lib/libQtXml.prl \ + /usr/lib/libQtCore.prl \ + /usr/lib/libQtGui.prl + $(QMAKE) -unix -o Makefile confmgr.pro +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/common/g++.conf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/common/unix.conf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/common/linux.conf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/qconfig.pri: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/qt_functions.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/qt_config.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/exclusive_builds.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/default_pre.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/release.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/default_post.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/warn_on.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/qt.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/moc.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/dbusinterfaces.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/dbusadaptors.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/unix/thread.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/resources.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/uic.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/yacc.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/lex.prf: +/targets/FREMANTLE_X86/usr/share/qt4/mkspecs/features/include_source_dir.prf: +/usr/lib/libQtMaemo5.prl: +/usr/lib/libQtDBus.prl: +/usr/lib/libQtXml.prl: +/usr/lib/libQtCore.prl: +/usr/lib/libQtGui.prl: +qmake: FORCE + @$(QMAKE) -unix -o Makefile confmgr.pro + +dist: + @$(CHK_DIR_EXISTS) .tmp/confmgr1.0.0 || $(MKDIR) .tmp/confmgr1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/confmgr1.0.0/ && $(COPY_FILE) --parents mainwindow.h xmlutil.h profile.h config.h addprofile.h addstep.h dbusutility.h confmanager.h .tmp/confmgr1.0.0/ && $(COPY_FILE) --parents main.cpp mainwindow.cpp xmlutil.cpp profile.cpp config.cpp addprofile.cpp addstep.cpp dbusutility.cpp confmanager.cpp .tmp/confmgr1.0.0/ && $(COPY_FILE) --parents mainwindow.ui addprofile.ui addstep.ui .tmp/confmgr1.0.0/ && (cd `dirname .tmp/confmgr1.0.0` && $(TAR) confmgr1.0.0.tar confmgr1.0.0 && $(COMPRESS) confmgr1.0.0.tar) && $(MOVE) `dirname .tmp/confmgr1.0.0`/confmgr1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/confmgr1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: moc_mainwindow.cpp moc_xmlutil.cpp moc_profile.cpp moc_config.cpp moc_addprofile.cpp moc_addstep.cpp moc_confmanager.cpp +compiler_moc_header_clean: + -$(DEL_FILE) moc_mainwindow.cpp moc_xmlutil.cpp moc_profile.cpp moc_config.cpp moc_addprofile.cpp moc_addstep.cpp moc_confmanager.cpp +moc_mainwindow.cpp: config.h \ + profile.h \ + addprofile.h \ + addstep.h \ + confmanager.h \ + dbusutility.h \ + mainwindow.h + /usr/bin/moc $(DEFINES) $(INCPATH) mainwindow.h -o moc_mainwindow.cpp + +moc_xmlutil.cpp: profile.h \ + xmlutil.h + /usr/bin/moc $(DEFINES) $(INCPATH) xmlutil.h -o moc_xmlutil.cpp + +moc_profile.cpp: profile.h + /usr/bin/moc $(DEFINES) $(INCPATH) profile.h -o moc_profile.cpp + +moc_config.cpp: profile.h \ + config.h + /usr/bin/moc $(DEFINES) $(INCPATH) config.h -o moc_config.cpp + +moc_addprofile.cpp: addstep.h \ + profile.h \ + addprofile.h + /usr/bin/moc $(DEFINES) $(INCPATH) addprofile.h -o moc_addprofile.cpp + +moc_addstep.cpp: profile.h \ + addstep.h + /usr/bin/moc $(DEFINES) $(INCPATH) addstep.h -o moc_addstep.cpp + +moc_confmanager.cpp: profile.h \ + dbusutility.h \ + confmanager.h + /usr/bin/moc $(DEFINES) $(INCPATH) confmanager.h -o moc_confmanager.cpp + +compiler_dbus_interface_source_make_all: +compiler_dbus_interface_source_clean: +compiler_dbus_adaptor_source_make_all: +compiler_dbus_adaptor_source_clean: +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_dbus_interface_header_make_all: +compiler_dbus_interface_header_clean: +compiler_dbus_interface_moc_make_all: +compiler_dbus_interface_moc_clean: +compiler_dbus_adaptor_header_make_all: +compiler_dbus_adaptor_header_clean: +compiler_dbus_adaptor_moc_make_all: +compiler_dbus_adaptor_moc_clean: +compiler_uic_make_all: ui_mainwindow.h ui_addprofile.h ui_addstep.h +compiler_uic_clean: + -$(DEL_FILE) ui_mainwindow.h ui_addprofile.h ui_addstep.h +ui_mainwindow.h: mainwindow.ui + /usr/bin/uic mainwindow.ui -o ui_mainwindow.h + +ui_addprofile.h: addprofile.ui + /usr/bin/uic addprofile.ui -o ui_addprofile.h + +ui_addstep.h: addstep.ui + /usr/bin/uic addstep.ui -o ui_addstep.h + +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean compiler_uic_clean + +####### Compile + +main.o: main.cpp mainwindow.h \ + config.h \ + profile.h \ + addprofile.h \ + addstep.h \ + confmanager.h \ + dbusutility.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp + +mainwindow.o: mainwindow.cpp mainwindow.h \ + config.h \ + profile.h \ + addprofile.h \ + addstep.h \ + confmanager.h \ + dbusutility.h \ + ui_mainwindow.h \ + xmlutil.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o mainwindow.o mainwindow.cpp + +xmlutil.o: xmlutil.cpp xmlutil.h \ + profile.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o xmlutil.o xmlutil.cpp + +profile.o: profile.cpp profile.h \ + xmlutil.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o profile.o profile.cpp + +config.o: config.cpp config.h \ + profile.h \ + xmlutil.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o config.o config.cpp + +addprofile.o: addprofile.cpp addprofile.h \ + addstep.h \ + profile.h \ + ui_addprofile.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o addprofile.o addprofile.cpp + +addstep.o: addstep.cpp addstep.h \ + profile.h \ + ui_addstep.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o addstep.o addstep.cpp + +dbusutility.o: dbusutility.cpp dbusutility.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o dbusutility.o dbusutility.cpp + +confmanager.o: confmanager.cpp confmanager.h \ + profile.h \ + dbusutility.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o confmanager.o confmanager.cpp + +moc_mainwindow.o: moc_mainwindow.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_mainwindow.o moc_mainwindow.cpp + +moc_xmlutil.o: moc_xmlutil.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_xmlutil.o moc_xmlutil.cpp + +moc_profile.o: moc_profile.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_profile.o moc_profile.cpp + +moc_config.o: moc_config.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_config.o moc_config.cpp + +moc_addprofile.o: moc_addprofile.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_addprofile.o moc_addprofile.cpp + +moc_addstep.o: moc_addstep.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_addstep.o moc_addstep.cpp + +moc_confmanager.o: moc_confmanager.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_confmanager.o moc_confmanager.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/src/addprofile.cpp b/src/addprofile.cpp new file mode 100644 index 0000000..2292419 --- /dev/null +++ b/src/addprofile.cpp @@ -0,0 +1,85 @@ +#include "addprofile.h" +#include "ui_addprofile.h" +#include +#include + +AddProfile::AddProfile(QWidget *parent) : + QWidget(parent), + ui(new Ui::AddProfile) +{ + ui->setupUi(this); + connect(&mFrmAddStep, SIGNAL(StepAddedSuccessfully(Steps)), + this, SLOT(updateStepList(Steps))); + mFrmAddStep.setWindowFlags(mFrmAddStep.windowFlags() | Qt::Window); +} + +AddProfile::~AddProfile() +{ + delete ui; +} + +void AddProfile::on_addProCancel_clicked() +{ + this->close(); +} + +void AddProfile::on_addProSave_clicked() +{ + Profile p; + p.mName = ui->addProName->text(); + p.mNoOfSteps = ui->addProStepList->count(); + p.mSteps = mSteps; + emit(ProfileAddedSuccessfully(p)); + this->close(); +} + +void AddProfile::showStepsUI() +{ + mFrmAddStep.setParent(this, Qt::Window); + mFrmAddStep.clear(); + mFrmAddStep.setAttribute(Qt::WA_Maemo5StackedWindow); + mFrmAddStep.show(); +} + +void AddProfile::updateStepList(Steps step) +{ + mSteps.append(step); + QString text = "Value: " + step.value(); + text += " || Delay: " + QString::number(step.delay()); + ui->addProStepList->addItem(text); + qDebug() << "updateStepList(): Text in List: " << text; +} + +void AddProfile::on_addProRemoveStep_clicked() +{ + if(ui->addProStepList->count() <= 0 || ui->addProStepList->currentRow() < 0) + { + QMessageBox msg; + msg.setText("Please select a step first!"); + msg.exec(); + return; + } + + mSteps.removeAt(ui->addProStepList->currentRow()); + QString *pText = (QString*) ui->addProStepList->takeItem(ui->addProStepList->currentRow()); + delete pText; +} + +void AddProfile::clear() +{ + ui->addProStepList->clear(); + ui->addProName->setText(QString::null); +} + +void AddProfile::showProfile(Profile &p) +{ + ui->addProName->setText(p.mName); + for(unsigned int i = 0; i < p.mNoOfSteps; i++) + { + Steps step = p.mSteps.at(i); + QString text = "Value: " + step.value(); + text += " || Delay: " + QString::number(step.delay()); + ui->addProStepList->addItem(text); + } + this->show(); +} diff --git a/src/addprofile.h b/src/addprofile.h new file mode 100644 index 0000000..3c93004 --- /dev/null +++ b/src/addprofile.h @@ -0,0 +1,42 @@ +#ifndef ADDPROFILE_H +#define ADDPROFILE_H + +#include +#include +#include "addstep.h" +#include "profile.h" + +namespace Ui { + class AddProfile; +} + +class AddProfile : public QWidget +{ + Q_OBJECT + +public: + explicit AddProfile(QWidget *parent = 0); + ~AddProfile(); + + void clear(); + +public slots: + void updateStepList(Steps step); + void showProfile(Profile &p); + +private: + Ui::AddProfile *ui; + QList mSteps; + AddStep mFrmAddStep; + +signals: + void ProfileAddedSuccessfully(Profile profile); + +private slots: + void on_addProRemoveStep_clicked(); + void on_addProSave_clicked(); + void on_addProCancel_clicked(); + void showStepsUI(); +}; + +#endif // ADDPROFILE_H diff --git a/src/addprofile.ui b/src/addprofile.ui new file mode 100644 index 0000000..7ccb138 --- /dev/null +++ b/src/addprofile.ui @@ -0,0 +1,181 @@ + + + AddProfile + + + Qt::ApplicationModal + + + + 0 + 0 + 800 + 424 + + + + Qt::TabFocus + + + AddProfile + + + + + 560 + 140 + 211 + 141 + + + + + + + + 0 + 0 + + + + Add Step + + + + + + + + 0 + 0 + + + + Remove Step + + + + + + + + + 30 + 330 + 741 + 71 + + + + + + + + 0 + 0 + + + + Save Profile + + + + + + + + 0 + 0 + + + + Cancel Operation + + + + + + + + + 30 + 10 + 741 + 61 + + + + + + + Profile Name: + + + + + + + + + + + + 30 + 80 + 511 + 231 + + + + + + + Steps: + + + + + + + + + + + + + addProCancel + clicked() + AddProfile + close() + + + 240 + 599 + + + 239 + 319 + + + + + addProAddStep + clicked() + AddProfile + showStepsUI() + + + 151 + 483 + + + -2 + 521 + + + + + + showStepsUI() + + diff --git a/src/addstep.cpp b/src/addstep.cpp new file mode 100644 index 0000000..bc05e5f --- /dev/null +++ b/src/addstep.cpp @@ -0,0 +1,28 @@ +#include "addstep.h" +#include "ui_addstep.h" + +AddStep::AddStep(QWidget *parent) : + QWidget(parent), + ui(new Ui::AddStep) +{ + ui->setupUi(this); +} + +AddStep::~AddStep() +{ + delete ui; +} + +void AddStep::AddOperationStep() +{ + mStep.setDelay(ui->addStepDelay->text().toInt()); + mStep.setValue(ui->addStepValue->text()); + emit(StepAddedSuccessfully(mStep)); + this->close(); +} + +void AddStep::clear() +{ + ui->addStepDelay->setText(QString::null); + ui->addStepValue->setText(QString::null); +} diff --git a/src/addstep.h b/src/addstep.h new file mode 100644 index 0000000..f613879 --- /dev/null +++ b/src/addstep.h @@ -0,0 +1,32 @@ +#ifndef ADDSTEP_H +#define ADDSTEP_H + +#include +#include "profile.h" + +namespace Ui { + class AddStep; +} + +class AddStep : public QWidget +{ + Q_OBJECT + +public: + explicit AddStep(QWidget *parent = 0); + ~AddStep(); + + void clear(); + +signals: + void StepAddedSuccessfully(Steps step); + +public slots: + void AddOperationStep(); + +private: + Ui::AddStep *ui; + Steps mStep; +}; + +#endif // ADDSTEP_H diff --git a/src/addstep.ui b/src/addstep.ui new file mode 100644 index 0000000..9582a99 --- /dev/null +++ b/src/addstep.ui @@ -0,0 +1,177 @@ + + + AddStep + + + Qt::ApplicationModal + + + + 0 + 0 + 800 + 424 + + + + AddStep + + + + + 30 + 170 + 741 + 71 + + + + + + + Value: + + + + + + + Qt::ImhDigitsOnly + + + + + + + + + 31 + 250 + 281 + 71 + + + + + + + Delay: + + + + + + + Qt::ImhDigitsOnly + + + + + + + Seconds + + + + + + + + + 30 + 330 + 741 + 71 + + + + + + + + 0 + 0 + + + + Add Step + + + + + + + + 0 + 0 + + + + Cancel Operation + + + + + + + + + 30 + 9 + 741 + 151 + + + + + + + The Value field is a phone number or DTMF tones. Include characters like *, + or # in the Value as and when they are required. The Delay in seconds shows the time allowed to lapse before dialing the corresponding value. The first step typically has 0 delay with the conference number as a value. + + + true + + + + + + + + + + btnCancel + clicked() + AddStep + close() + + + 240 + 169 + + + 239 + 100 + + + + + btnaddStep + clicked() + AddStep + AddOperationStep() + + + 143 + 133 + + + 74 + 199 + + + + + + AddOperationStep() + + diff --git a/src/cfConfig.xml b/src/cfConfig.xml new file mode 100644 index 0000000..dfa1740 --- /dev/null +++ b/src/cfConfig.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..76dc12f --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,185 @@ +#include "config.h" +#include "profile.h" +#include "xmlutil.h" + +#include +#include + +/* + TODO: Create backup & restore functions for the backup configuration files. + Today it only writes a backup when the removeAllProfiles() is called. + */ + +Config::Config(QObject *parent) : + QObject(parent) +{ + confFile.setFileName(CONFIG_FILE); + noOfProfiles = 0; + profileList.clear(); +} + +bool Config::openConfig() +{ + int stopLoops = 0; + qDebug() << "Opening the Config file"; + + processAgain: + bool bOpenResult = confFile.open(QIODevice::ReadWrite | QIODevice::Text); + if(bOpenResult) + { + QString errorMsg; + int errorLine, errorColumn; + bOpenResult = domDoc.setContent(&confFile, &errorMsg, + &errorLine, &errorColumn); + if(!bOpenResult) + { + qDebug() << "Error while setContent on Line: " << errorLine + << "Column: " << errorColumn << endl + << "Error Text: " << errorMsg; +// return bOpenResult; + confFile.write(DEFAULT_XML); + closeConfig(); + if(0 == stopLoops) + { + stopLoops++; + goto processAgain; + } + } + + QDomNode node = domDoc.namedItem(PROFILE_TAG); + if(node.isNull()) + { + qDebug() << "Probably first use of config! Creating Profiles Tag"; + QDomElement el = Xmlutil::addElement(domDoc, domDoc, PROFILE_TAG); + // noOfProfiles should be 0, initialized in CTOR... + el.setAttribute(NO_OF_PROFILE_ATTR, noOfProfiles); + return true; + } + + // Now load the whole config file in memory! + qDebug() << "Trying to load the whole config now..."; + bOpenResult = readAllProfiles(); + } + return bOpenResult; +} + +bool Config::closeConfig() +{ + bool bResult = confFile.flush(); + confFile.close(); + return bResult; +} + +int Config::addProfile(const Profile &p) +{ + int error = 0; + QDomElement el = domDoc.namedItem(PROFILE_TAG).toElement(); + Xmlutil::generateProfileXML(p, &error, &domDoc, &el); + if(!error) + { + noOfProfiles++; + updateNoOfProfiles(); + profileList.append(p); + } + qDebug() << "AddProfile(): " << error << "\tXMLString is: " << endl << domDoc.toString(); + return error; +} + +void Config::updateNoOfProfiles() +{ + QDomElement el = domDoc.namedItem(PROFILE_TAG).toElement(); + el.setAttribute(NO_OF_PROFILE_ATTR, noOfProfiles); +} + +int Config::removeProfile(const Profile &p) +{ + QDomElement elem = domDoc.namedItem(PROFILE_TAG).toElement(); + QDomElement el = elem.firstChildElement(); + qDebug() << el.text(); + for(int i = 0; i < noOfProfiles; i++) + { + QString name = el.attribute(NAME_ATTR); + + qDebug() << "Name is: " << name; + if(p.mName == name) + { + if(!el.parentNode().removeChild(el).isNull()) + { + noOfProfiles--; + updateNoOfProfiles(); + profileList.removeAt(i); + qDebug() << "RemoveChild okay!"; + } + break; + } + el = el.nextSiblingElement(); + } + return 0; +} + +void Config::flushConfig() +{ + confFile.flush(); +} + +bool Config::readAllProfiles() +{ + // Point to the PROFILE_TAG node->element + QDomElement el = domDoc.namedItem(PROFILE_TAG).toElement(); + noOfProfiles = el.attribute(NO_OF_PROFILE_ATTR).toInt(); + + qDebug() << "Number of profiles in config is: " << noOfProfiles; + + if(noOfProfiles > 0) + { + QDomElement childEl = el.firstChildElement(); + for(int i = 0; i < noOfProfiles; i++) + { + Profile p; + QString dummy; dummy.clear(); + if(!Xmlutil::degenerateProfileXML(dummy, p, &childEl)) + { + profileList.append(p); + qDebug() << "Profile added to ProfileList..."; + } + else + { + qDebug() << "Profile not added, returning false"; + return false; + } + childEl = childEl.nextSiblingElement(); + } + } + return true; +} + +bool Config::writeAllProfiles() +{ + // Stupid hack to dump all the document data into the config file... + bool bResult = closeConfig(); + QDir dir(CONFIG_DIR); + bResult = dir.remove(CONFIG_FILE); + + bResult = confFile.open(QIODevice::WriteOnly | QIODevice::Text); + + // No need to do set content since document data is always updated... + qint64 error = confFile.write(domDoc.toByteArray()); + flushConfig(); + if( -1 == error) + return false; + return true; +} + +bool Config::removeAllProfiles() +{ + // Create a backup file just in case... + profileList.clear(); + QDir dir(CONFIG_DIR); + bool bResult = dir.remove(BACKUP_CONFIG_FILE); + bResult = confFile.copy(BACKUP_CONFIG_FILE); + // Essentially just delete the whole file and re-open + bResult = closeConfig(); + bResult = dir.remove(CONFIG_FILE); + bResult = openConfig(); + return bResult; +} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..7b5e232 --- /dev/null +++ b/src/config.h @@ -0,0 +1,71 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include +#include +#include +#include "profile.h" + +#define APPLICATION_NAME "ConfManager" +//#define CONFIG_DIR "/apps/Maemo/" APPLICATION_NAME "/" + +// For test only! +#define CONFIG_DIR "./" + +#define CONFIG_FILE CONFIG_DIR "cfConfig.xml" +#define BACKUP_CONFIG_FILE CONFIG_DIR "cfConfig.bak" + +#define DEFAULT_XML "\r\n\r\n" + +class Config : public QObject +{ + Q_OBJECT +public: + explicit Config(QObject *parent = 0); + + // Close the config file + ~Config() { closeConfig(); } + + // Return 0 if everything okay else a negative integer + int addProfile(const Profile &p); + int removeProfile(const Profile &p); + + // Write back all the changes to the disk + void flushConfig(); + + // Read all the profiles from config file + bool readAllProfiles(); + // Writes all the profiles from the list to the config file + // Similar to flushConfig(), flushConfig will internally call + // writeAllProfiles() + bool writeAllProfiles(); + // Similar to deletion of config file. Never to be used! + bool removeAllProfiles(); + + // get-set for noOfProfiles + void setNoOfProfiles(const int &no) { noOfProfiles = no; } + int getNoOfProfiles() { return noOfProfiles; } + + QList profileList; + + bool openConfig(); + + // Called by flush and + bool closeConfig(); + +private: + + void updateNoOfProfiles(); + + QFile confFile; + QDomDocument domDoc; + int noOfProfiles; + +signals: + +public slots: + +}; + +#endif // CONFIG_H diff --git a/src/config.xml b/src/config.xml new file mode 100644 index 0000000..e176ed6 --- /dev/null +++ b/src/config.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/confmanager.cpp b/src/confmanager.cpp new file mode 100644 index 0000000..4acbe45 --- /dev/null +++ b/src/confmanager.cpp @@ -0,0 +1,200 @@ +#include "confmanager.h" +#include +#include + +confManager::confManager(QObject *parent) : + QObject(parent) +{ + mProfileSet = false; + mInStep = 0; +} + +void confManager::setProfile(Profile &p) +{ + mInStep = 0; + mProfileInUse = p; + mProfileSet = true; +} + +void confManager::continueSendDTMF() +{ + // We have now waited for the required period of seconds + // Lets send the DTMF now + Steps step = mProfileInUse.mSteps.at(mInStep); + + // Increment the steps as we want to point to the next one + mInStep++; + + QList argsToSend; + argsToSend.append(step.value()); + + bool status = mDBusUtility.sendMethodCall(CSD_SERVICE, CSD_CALL_PATH, CSD_CALL_INTERFACE, + QString("SendDTMF"),argsToSend); + + if(!status) + { + qDebug() << "Unable to send DTMF code."; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + + // Check if we are over with the sequence or we need to continue + if(mInStep > mProfileInUse.mNoOfSteps) + { + StopCallMonitors(); + return; + } + + step = mProfileInUse.mSteps.at(mInStep); + QTimer *timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, SIGNAL(timeout()), this, SLOT(sendDTMF(const QDBusMessage &))); + timer->start(step.delay()); +} + +void confManager::sendDTMF(const QDBusMessage &dBusMessage) +{ + QList listArguments = dBusMessage.arguments(); + bool audioConnected = listArguments.first().toBool(); + + if(mInStep > mProfileInUse.mNoOfSteps) + { + StopCallMonitors(); + return; + } + + Steps step = mProfileInUse.mSteps.at(mInStep); + + if (audioConnected) + { + qDebug() << "Audio Connected..."; + //Wait for specified delay in the step + QTimer *timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, SIGNAL(timeout()), this, SLOT(continueSendDTMF())); + timer->start(step.delay()); + } +} + +void confManager::StartCallMonitors() +{ + QDBusConnection connection = mDBusUtility.getConnection(); + /* Declare the slot to be executed when a call is picked up by other party (Audio connection established). + We need this to confirm whether a call went though successfully. + */ + bool status = connection.connect(QString(""), CSD_CALL_INSTANCE_PATH, CSD_CALL_INSTANCE_INTERFACE, + QString("AudioConnect"),this, SLOT(sendDTMF(const QDBusMessage&))); + + if(!status) + { + qDebug() << "Failed to connect to Dbus signal AudioConnect in interface "<< CSD_CALL_INSTANCE_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + + qDebug() << "Successfully connected to Dbus signal AudioConnect in interface "<< CSD_CALL_INSTANCE_INTERFACE; + + /* Declare the slot to be executed when the call is terminated (due to connection errors etc). + We need this to avoid sending DTMF code on wrong calls. + */ + status = connection.connect(QString(""), CSD_CALL_INSTANCE_PATH, CSD_CALL_INSTANCE_INTERFACE, + QString("Terminated"),this, SLOT(StopCallMonitors())); + + if(!status) + { + qDebug() << "Failed to connect to Dbus signal Terminated in interface "<< CSD_CALL_INSTANCE_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + + qDebug() << "Successfully connected to Dbus signal Terminated in interface "<< CSD_CALL_INSTANCE_INTERFACE; + + /* Declare the slot to be executed when a call is received + (before we can place the call to calling card number). + It is extremely rare that somebody should get a call within these few seconds. + In any case, we need this to avoid sending DTMF code on the received call. + + Btw - I don't care for the incoming number here. If anyone is calling the user before we can send DTMF code, + then we stop sending the DTMF code even if user does not respond to the call. + */ + + status = connection.connect(QString(""), CSD_CALL_PATH, CSD_CALL_INTERFACE, + QString("Coming"),this, SLOT(StopCallMonitors())); + + if(!status) + { + qDebug() << "Failed to connect to Dbus signal Coming in interface" << CSD_CALL_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + qDebug() << "Successfully connected to Dbus signal Coming in interface" << CSD_CALL_INTERFACE; +} + +void confManager::StopCallMonitors() +{ + mInStep = 0; + mProfileSet = false; + + QDBusConnection connection = mDBusUtility.getConnection(); + + // Disconnect the slot for audio connection status + bool status = connection.disconnect(QString(""), CSD_CALL_INSTANCE_PATH, CSD_CALL_INSTANCE_INTERFACE, + QString("AudioConnect"),this, SLOT(sendDTMF(const QDBusMessage&))); + + if(!status) + { + qDebug() << "Failed to disconnect from Dbus signal AudioConnect in interface" << CSD_CALL_INSTANCE_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + qDebug() << "Successfully disconnected from Dbus signal AudioConnect in interface "<< CSD_CALL_INSTANCE_INTERFACE; + + // Disconnect the slot for monitoring terminated calls + status = connection.disconnect(QString(""), CSD_CALL_INSTANCE_PATH, CSD_CALL_INSTANCE_INTERFACE, + QString("Terminated"),this, SLOT(StopCallMonitors())); + + if(!status) + { + qDebug() << "Failed to disconnect from Dbus signal Terminated in interface" << CSD_CALL_INSTANCE_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + qDebug() << "Successfully disconnected from Dbus signal Terminated in interface "<< CSD_CALL_INSTANCE_INTERFACE; + + // Disconnect the slot for monitoring incoming calls + status = connection.disconnect(QString(""), CSD_CALL_PATH, CSD_CALL_INTERFACE, + QString("Coming"),this, SLOT(StopCallMonitors())); + + if(!status) + { + qDebug() << "Failed to disconnect from Dbus signal Coming in interface" << CSD_CALL_INTERFACE; + QString error = "DBus Error: " + mDBusUtility.getErrorMessage(); + mDBusUtility.displayNotification(error); + } + qDebug() << "Successfully disconnected from Dbus signal Coming in interface" << CSD_CALL_INTERFACE; +} + +void confManager::startConference() +{ + if(!mProfileSet) + { + qDebug() << "Please set the profile to use with Conference Manager first!"; + return; + } + //Assume that the first number is always a phone number... + Steps step = mProfileInUse.mSteps.at(mInStep); + mInStep++; + QList sendArgs; + sendArgs.append(step.value()); + sendArgs.append(0); + bool status = mDBusUtility.sendMethodCall(CSD_SERVICE, CSD_CALL_PATH, CSD_CALL_INTERFACE, + QString("CreateWith"), sendArgs); + if(!status) + { + QString error = "Error while dialing: " + mDBusUtility.getErrorMessage(); + qDebug() << error; + mDBusUtility.displayNotification(error); + return; + } + StartCallMonitors(); +} diff --git a/src/confmanager.h b/src/confmanager.h new file mode 100644 index 0000000..5e86bba --- /dev/null +++ b/src/confmanager.h @@ -0,0 +1,38 @@ +#ifndef CONFMANAGER_H +#define CONFMANAGER_H + +#include "profile.h" +#include "dbusutility.h" + +#define CSD_CALL_BUS_NAME "com.nokia.csd.Call" +#define CSD_CALL_INTERFACE "com.nokia.csd.Call" +#define CSD_CALL_INSTANCE_INTERFACE "com.nokia.csd.Call.Instance" +#define CSD_CALL_CONFERENCE "com.nokia.csd.Call.Conference" +#define CSD_CALL_PATH "/com/nokia/csd/call" +#define CSD_CALL_INSTANCE_PATH "/com/nokia/csd/call/1" +#define CSD_CALL_SERVICE "com.nokia.csd.Call" +#define CSD_SERVICE "com.nokia.csd" + +class confManager : public QObject +{ + Q_OBJECT +public: + explicit confManager(QObject *parent = 0); + + void setProfile(Profile &p); + void startConference(); + +private: + void sendDTMF(const QDBusMessage &dBusMessage); + void StartCallMonitors(); + void StopCallMonitors(); + void continueSendDTMF(); + +private: + Profile mProfileInUse; + bool mProfileSet; + DbusUtility mDBusUtility; + unsigned int mInStep; +}; + +#endif // CONFMANAGER_H diff --git a/src/confmgr.pro b/src/confmgr.pro new file mode 100644 index 0000000..2e8df6a --- /dev/null +++ b/src/confmgr.pro @@ -0,0 +1,10 @@ +QMAKEVERSION = $$[QMAKE_VERSION] +ISQT4 = $$find(QMAKEVERSION, ^[2-9]) +isEmpty( ISQT4 ) { +error("Use the qmake include with Qt4.4 or greater, on Debian that is +qmake-qt4"); +} + +TEMPLATE = subdirs +SUBDIRS = src + diff --git a/src/confmgr.pro.user b/src/confmgr.pro.user new file mode 100644 index 0000000..5c6201b --- /dev/null +++ b/src/confmgr.pro.user @@ -0,0 +1,303 @@ + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + System + + + + ProjectExplorer.Project.Target.0 + + Maemo + Qt4ProjectManager.Target.MaemoDeviceTarget + 0 + 0 + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + + + Qt4ProjectManager.MaemoPackageCreationStep + + false + /usr/local/bin/confmgr + + + 3 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Qt for Fremantle PR1.2 Devices (Nokia Qt SDK) Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /home/naresh/Documents/dev/maemo/confmgr-build-maemo + 3 + 9 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + + + Qt4ProjectManager.MaemoPackageCreationStep + + true + /usr/local/bin/confmgr + + + 3 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Qt for Fremantle PR1.2 Devices (Nokia Qt SDK) Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /home/naresh/Documents/dev/maemo/confmgr-build-maemo + 3 + 9 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + + + Qt4ProjectManager.MaemoPackageCreationStep + + false + /usr/local/bin/confmgr + + + 3 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Maemo Qt4.5 Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /home/naresh/Documents/dev/maemo/confmgr-build-maemo + 8 + 9 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + + + Qt4ProjectManager.MaemoPackageCreationStep + + true + + + + 3 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Maemo Qt4.5 Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /home/naresh/Documents/dev/maemo/confmgr-build-maemo + 8 + 9 + true + + 4 + + confmgr.pro + New Maemo Run Configuration + Qt4ProjectManager.MaemoRunConfiguration + + + 9 + + 2010-07-04T02:11:42 + + + 1 + + + + ProjectExplorer.Project.Target.1 + + Qt Simulator + Qt4ProjectManager.Target.QtSimulatorTarget + 0 + 0 + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /home/naresh/Documents/dev/maemo/confmgr-build-simulator + 2 + 0 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /home/naresh/Documents/dev/maemo/confmgr-build-simulator + 2 + 0 + true + + 2 + + confmgr + Qt4ProjectManager.Qt4RunConfiguration + 2 + + confmgr.pro + false + false + + false + false + + + 1 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 4 + + diff --git a/src/dbusutility.cpp b/src/dbusutility.cpp new file mode 100644 index 0000000..7412667 --- /dev/null +++ b/src/dbusutility.cpp @@ -0,0 +1,71 @@ +/* +@version: 0.1 +@author: Sudheer K. +@license: GNU General Public License +*/ + +#include "dbusutility.h" +#include +#include + + +//Construction is available in the header file due to a peculiar issue with systemBus() function. + + +//Destructor for Dbus Utility object. +DbusUtility::~DbusUtility(){ + this->connection.disconnectFromBus(this->connection.baseService()); + qDebug() << "Disconnected from system bus"; +} + +QDBusConnection DbusUtility::getConnection(){ + if (!this->connection.isConnected()){ + qDebug() << "Not connected to Dbus"; + } + return this->connection; +} + +void DbusUtility::setConnection(QDBusConnection connection){ + this->connection = connection; +} + +//Utility method to send a dbus signal. +bool DbusUtility::sendSignal(QString strPath,QString strInterface,QString strName){ + QDBusMessage dbusSignal = QDBusMessage::createSignal(strPath,strInterface,strName); + bool status = DbusUtility::connection.send(dbusSignal); + return status; +} + +//Utility method to call a dbus method with parameters +bool DbusUtility::sendMethodCall(QString strService,QString strPath, + QString strInterface,QString strMethodName, + QList & arguments){ + QDBusMessage dbusMethodCall = QDBusMessage::createMethodCall(strService,strPath,strInterface,strMethodName); + dbusMethodCall.setArguments(arguments); + bool status = DbusUtility::connection.send(dbusMethodCall); + return status; +} + +//Utility method to display a notification (Orange sliding banner in Maemo) with custom message +bool DbusUtility::displayNotification(QString strMessage){ + QList arguments; + arguments.append(strMessage); + + bool status = this->sendMethodCall(NOTIFICATION_SERVICE, + NOTIFICATION_PATH, + NOTIFICATION_INTERFACE, + QString("SystemNoteInfoprint"), + arguments); + return status; +} + + +//Utility method to retrieve the last dbus error +QString DbusUtility::getErrorMessage(){ + QString strErrorMessage; + QDBusError dbusError = this->connection.lastError(); + if (dbusError.isValid()){ + strErrorMessage = qPrintable(dbusError.message()); + } + return strErrorMessage; +} diff --git a/src/dbusutility.h b/src/dbusutility.h new file mode 100644 index 0000000..0fb0a10 --- /dev/null +++ b/src/dbusutility.h @@ -0,0 +1,35 @@ +/* +@version: 0.1 +@author: Sudheer K. +@license: GNU General Public License +*/ + +#ifndef DBUSUTILITY_H +#define DBUSUTILITY_H + +#include +#include + +#define NOTIFICATION_SERVICE "org.freedesktop.Notifications" +#define NOTIFICATION_PATH "/org/freedesktop/Notifications" +#define NOTIFICATION_INTERFACE "org.freedesktop.Notifications" + +class DbusUtility +{ +protected: + QDBusConnection connection; +public: + DbusUtility():connection(QDBusConnection::systemBus()) + {} + ~DbusUtility(); + QDBusConnection getConnection(); + void setConnection(QDBusConnection connection); + bool sendSignal(QString strPath,QString strInterface,QString strName); + bool sendMethodCall(QString strService,QString strPath, + QString strInterface,QString strMethodName, + QList & arguments); + bool displayNotification(QString strMessage); + QString getErrorMessage(); +}; + +#endif // DBUSUTILITY_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..d6a9241 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,20 @@ +#include +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; +#if defined(Q_WS_S60) + w.showMaximized(); +/* +#elseif defined(Q_WS_MAEMO_5) + w.setPortraitMode(); + w.showMaximized(); +*/ +#else + w.show(); +#endif + + return a.exec(); +} diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp new file mode 100644 index 0000000..1afe99a --- /dev/null +++ b/src/mainwindow.cpp @@ -0,0 +1,108 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "xmlutil.h" +#include +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + connect(&mFrmAddProfile, SIGNAL(ProfileAddedSuccessfully(Profile)), + this, SLOT(updateProfileList(Profile))); + Initialize(); +} + +MainWindow::~MainWindow() +{ + mConfig.writeAllProfiles(); + mConfig.closeConfig(); + delete ui; +} + +void MainWindow::Initialize() +{ + mConfig.openConfig(); + for(int i = 0; i < mConfig.getNoOfProfiles(); i++) + { + Profile p = mConfig.profileList.at(i); + QString text = "Name: " + p.mName + " || Steps: " + QString::number(p.mNoOfSteps); + ui->mainProfileList->addItem(text); + } + ui->centralWidget->setAttribute(Qt::WA_Maemo5StackedWindow); + mFrmAddProfile.setWindowFlags(mFrmAddProfile.windowFlags() | Qt::Window); +} + +void MainWindow::on_mainPBAdd_clicked() +{ + bIsProfileEdited = false; + mFrmAddProfile.setParent(this, Qt::Window); + mFrmAddProfile.clear(); + mFrmAddProfile.setAttribute(Qt::WA_Maemo5StackedWindow); + mFrmAddProfile.show(); +} + +void MainWindow::updateProfileList(Profile p) +{ + if(bIsProfileEdited) + { + // Delete previous profile and write this new one + QString *pText = (QString *) ui->mainProfileList->takeItem(ui->mainProfileList->currentRow()); + delete pText; + mConfig.removeProfile(p); + } + qDebug() << Xmlutil::generateProfileXML(p); + mConfig.addProfile(p); + QString text = "Name: " + p.mName + " || Steps: " + QString::number(p.mNoOfSteps); + ui->mainProfileList->addItem(text); +} + +void MainWindow::on_mainPBDelete_clicked() +{ + if(ui->mainProfileList->count() <= 0 || ui->mainProfileList->currentRow() < 0) + { + QMessageBox msg; + msg.setText("Please select a profile first!"); + msg.exec(); + return; + } + + Profile p = mConfig.profileList.at(ui->mainProfileList->currentRow()); + qDebug() << "Profile to be deleted: " << endl << Xmlutil::generateProfileXML(p); + QString *pText = (QString *) ui->mainProfileList->takeItem(ui->mainProfileList->currentRow()); + delete pText; + mConfig.removeProfile(p); +} + +void MainWindow::on_btnmainStartConference_clicked() +{ + if(ui->mainProfileList->count() <= 0 || ui->mainProfileList->currentRow() < 0) + { + QMessageBox msg; + msg.setText("Please select a profile first!"); + msg.exec(); + return; + } + Profile p = mConfig.profileList.at(ui->mainProfileList->currentRow()); + qDebug() << "Profile To Dial: " << endl << Xmlutil::generateProfileXML(p); + mConfMgr.setProfile(p); + mConfMgr.startConference(); +} + +void MainWindow::on_mainPBEditProfile_clicked() +{ + if(ui->mainProfileList->count() <= 0 || ui->mainProfileList->currentRow() < 0) + { + QMessageBox msg; + msg.setText("Please select a profile first!"); + msg.exec(); + return; + } + bIsProfileEdited = true; + Profile p = mConfig.profileList.at(ui->mainProfileList->currentRow()); + qDebug() << "Profile to be Edited: " << endl << Xmlutil::generateProfileXML(p); + mFrmAddProfile.setParent(this, Qt::Window); + mFrmAddProfile.setAttribute(Qt::WA_Maemo5StackedWindow); + mFrmAddProfile.showProfile(p); +} diff --git a/src/mainwindow.h b/src/mainwindow.h new file mode 100644 index 0000000..7ba7612 --- /dev/null +++ b/src/mainwindow.h @@ -0,0 +1,46 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "config.h" +#include "addprofile.h" +#include "confmanager.h" + +namespace Ui { + class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +#if defined(Q_WS_MAEMO_5) + void setPortraitMode() { setAttribute(Qt::WA_Maemo5PortraitOrientation, true); } +#endif + + void Initialize(); + +public slots: + void updateProfileList(Profile p); + +private: + Ui::MainWindow *ui; + Config mConfig; + AddProfile mFrmAddProfile; + bool bIsProfileEdited; + confManager mConfMgr; + QMenuBar *pMenu; + +private slots: + void on_mainPBEditProfile_clicked(); + void on_btnmainStartConference_clicked(); + void on_mainPBDelete_clicked(); + void on_mainPBAdd_clicked(); +}; + +#endif // MAINWINDOW_H diff --git a/src/mainwindow.ui b/src/mainwindow.ui new file mode 100644 index 0000000..10fbdcb --- /dev/null +++ b/src/mainwindow.ui @@ -0,0 +1,141 @@ + + + MainWindow + + + + 0 + 0 + 800 + 424 + + + + Conference Manager + + + + + + 30 + 260 + 351 + 141 + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + Start Conference + + + + + + + + 0 + 0 + + + + Add Profile + + + + + + + + + 25 + 4 + 751 + 241 + + + + + + + 420 + 260 + 351 + 141 + + + + + + + + 0 + 0 + + + + Edit Profile + + + + + + + + 0 + 0 + + + + Delete Profile + + + + + + + + 0 + 0 + + + + Exit + + + + + + + + + + + + mainPBQuit + clicked() + MainWindow + close() + + + 411 + 440 + + + 399 + 239 + + + + + diff --git a/src/profile.cpp b/src/profile.cpp new file mode 100644 index 0000000..273f4dc --- /dev/null +++ b/src/profile.cpp @@ -0,0 +1,34 @@ +#include "profile.h" +#include "xmlutil.h" +#include +#include + +Profile::Profile(QObject *parent) : + QObject(parent) +{ + mSteps.clear(); + mNoOfSteps = 0; +} + +Profile::Profile(const Profile &p) +{ + *this = p; +} + +Profile::~Profile() +{ + mSteps.clear(); +} + +Profile& Profile::operator =(const Profile &p) +{ + if(this != &p) + { + mXMLString = p.mXMLString; + mName = p.mName; + mNoOfSteps = p.mNoOfSteps; + mSteps.clear(); + mSteps = p.mSteps; + } + return *this; +} diff --git a/src/profile.h b/src/profile.h new file mode 100644 index 0000000..377fb0d --- /dev/null +++ b/src/profile.h @@ -0,0 +1,49 @@ +#ifndef PROFILE_H +#define PROFILE_H + +#include +#include + +class Steps +{ +public: + Steps() { } + Steps(const QString &value, const int &delay) : mValue(value), mDelay(delay) {} + ~Steps() { } + + // Getters... + QString value() { return mValue; } + int delay() { return mDelay; } + + // Setters... + void setValue(const QString &value) { mValue = value; } + void setDelay(const int &delay) { mDelay = delay; } + +private: + QString mValue; + int mDelay; +}; + +class Profile : public QObject +{ + Q_OBJECT +public: + explicit Profile(QObject *parent = 0); + Profile(const Profile &p); + ~Profile(); + + Profile& operator=(const Profile &p); + + QList mSteps; + + QString mXMLString; + QString mName; + unsigned int mNoOfSteps; // assumed number of steps no more then 255 and always positive! + +signals: + +public slots: + +}; + +#endif // PROFILE_H diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..de119e6 --- /dev/null +++ b/src/src.pro @@ -0,0 +1,84 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2010-06-23T14:10:47 +# +#------------------------------------------------- + +QT += core gui +QT += xml maemo5 dbus + +TARGET = confmgr +TEMPLATE = app + + +SOURCES += main.cpp\ + mainwindow.cpp \ + xmlutil.cpp \ + profile.cpp \ + config.cpp \ + addprofile.cpp \ + addstep.cpp \ + dbusutility.cpp \ + confmanager.cpp + +HEADERS += mainwindow.h \ + xmlutil.h \ + profile.h \ + config.h \ + addprofile.h \ + addstep.h \ + dbusutility.h \ + confmanager.h + +FORMS += mainwindow.ui \ + addprofile.ui \ + addstep.ui + +CONFIG += mobility +MOBILITY = + +symbian { + TARGET.UID3 = 0xea1d6940 + # TARGET.CAPABILITY += + TARGET.EPOCSTACKSIZE = 0x14000 + TARGET.EPOCHEAPSIZE = 0x020000 0x800000 +} + +OTHER_FILES += \ + config.xml + +unix { + #VARIABLES + isEmpty(PREFIX) { + PREFIX = /usr/local + } + BINDIR = $$PREFIX/bin + DATADIR =$$PREFIX/share + + DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\" + + #MAKE INSTALL + + INSTALLS += target desktop service iconxpm icon26 icon48 icon64 + + target.path =$$BINDIR + + desktop.path = $$DATADIR/applications/hildon + desktop.files += $${TARGET}.desktop + + service.path = $$DATADIR/dbus-1/services + service.files += $${TARGET}.service + + iconxpm.path = $$DATADIR/pixmap + iconxpm.files += ../data/maemo/$${TARGET}.xpm + + icon26.path = $$DATADIR/icons/hicolor/26x26/apps + icon26.files += ../data/26x26/$${TARGET}.png + + icon48.path = $$DATADIR/icons/hicolor/48x48/apps + icon48.files += ../data/48x48/$${TARGET}.png + + icon64.path = $$DATADIR/icons/hicolor/64x64/apps + icon64.files += ../data/64x64/$${TARGET}.png +} + diff --git a/src/xmlutil.cpp b/src/xmlutil.cpp new file mode 100644 index 0000000..e090c66 --- /dev/null +++ b/src/xmlutil.cpp @@ -0,0 +1,136 @@ +#include "xmlutil.h" +#include + +Xmlutil::Xmlutil(QObject *parent) : + QObject(parent) +{ +} + +QDomElement Xmlutil::addElement(QDomDocument &doc, QDomNode &node, + const QString &tag, const QString &value) +{ + QDomElement element = doc.createElement(tag); + node.appendChild(element); + if(!value.isNull()) + { + QDomText text = doc.createTextNode(value); + element.appendChild(text); + } + return element; +} + +/* +// Unit test from main + + Steps step("+4670", 1); + int error = 0; + + Profile p; + p.mName = "Diva"; + p.mNoOfSteps = 2; + p.mSteps.append(step); + step.setDelay(2); + step.setValue("+4788"); + p.mSteps.append(step); + + qDebug() << p.generateProfileXML(p, error); + +*/ +QString Xmlutil::generateProfileXML(const Profile &profile, int *error, + QDomDocument *doc, QDomElement *elem) +{ + QDomDocument *pDoc = NULL; + if(0 == doc) + pDoc = new QDomDocument; + else + pDoc = doc; + + QDomElement domElement; + + if(0 == elem) + domElement = Xmlutil::addElement(*pDoc, *pDoc, PROFILE_ELEM_TAG); + else + domElement = Xmlutil::addElement(*pDoc, *elem, PROFILE_ELEM_TAG); + + domElement.setAttribute(NAME_ATTR, profile.mName); + domElement.setAttribute(NO_OF_STEPS_ATTR, profile.mNoOfSteps); + + if(profile.mNoOfSteps > 0) + { + for(unsigned int i = 0; i < profile.mNoOfSteps; i++) + { + QDomElement stepEl = Xmlutil::addElement(*pDoc, domElement, STEP_TAG); + Steps step = profile.mSteps.at(i); + stepEl.setAttribute(VALUE_ATTR, step.value()); + stepEl.setAttribute(DELAY_ATTR, step.delay()); + } + } + + QString xmlString = pDoc->toString(); + + if(0 == doc) + delete pDoc; + + return xmlString; +} + +/* +QString generateXML() +{ + Steps step("+4670", 1); + Profile p; + p.mName = "Diva"; + p.mNoOfSteps = 2; + p.mSteps.append(step); + step.setDelay(2); + step.setValue("+4788"); + p.mSteps.append(step); + + return xmlutil::generateProfileXML(p); +} + +// Unit test from main... + + QString xmlString = generateXML(); + Profile p; + + int e = xmlutil::degenerateProfileXML(xmlString, p); +*/ + +int Xmlutil::degenerateProfileXML(const QString xmlString, Profile &profile, + QDomElement *pElem) +{ + QDomDocument doc; + Steps step; + QDomElement *elem = NULL; + if(0 == pElem && !xmlString.isNull()) + { + doc.setContent(xmlString); + *elem = doc.namedItem(PROFILE_ELEM_TAG).toElement(); + } + else + { + elem = pElem; + } + + if(elem->isNull()) + return -1; + + profile.mName = elem->attribute(NAME_ATTR); + profile.mNoOfSteps = elem->attribute(NO_OF_STEPS_ATTR).toInt(); + + qDebug() << profile.mName << ":" << profile.mNoOfSteps; + QDomElement child = elem->firstChild().toElement(); + + profile.mSteps.clear(); + + for(unsigned int i = 0; i < profile.mNoOfSteps ; i++) + { + step.setDelay(child.attribute(DELAY_ATTR).toInt()); + step.setValue(child.attribute(VALUE_ATTR)); + profile.mSteps.append(step); + qDebug() << step.value() << ":" << step.delay(); + child = child.nextSiblingElement(); + } + return 0; +} diff --git a/src/xmlutil.h b/src/xmlutil.h new file mode 100644 index 0000000..f51518e --- /dev/null +++ b/src/xmlutil.h @@ -0,0 +1,79 @@ +#ifndef XMLUTIL_H +#define XMLUTIL_H + +#include +#include +#include "profile.h" + +#define NO_OF_PROFILE_ATTR "NoOfProfiles" +#define PROFILE_TAG "Profiles" +#define PROFILE_ELEM_TAG "Profile" +#define NAME_ATTR "Name" +#define NO_OF_STEPS_ATTR "NoOfSteps" +#define STEP_TAG "Step" +#define VALUE_ATTR "Value" +#define DELAY_ATTR "Delay" + +class Xmlutil : public QObject +{ + Q_OBJECT +public: + explicit Xmlutil(QObject *parent = 0); + + static QDomElement addElement(QDomDocument &doc, QDomNode &node, + const QString &tag, + const QString &value = QString::null); + + static QString generateProfileXML(const Profile &profile, int *error = 0, + QDomDocument *doc = 0, QDomElement *elem = 0); + // returns non-zero on error + static int degenerateProfileXML(const QString xmlString, Profile &profile, + QDomElement *pElem = 0); + +// QDomElement removeElement +signals: + +public slots: + +}; + +/* + QDomDocument doc("mydocument"); + QFile file(argv[1]); + if (!file.open(QIODevice::ReadOnly)) + return -1; + if (!doc.setContent(&file)) { + file.close(); + return -1; + } + file.close(); + +// print out the element names of all elements that are direct children +// of the outermost element. + QDomElement docElem = doc.namedItem("Profiles").toElement(); + qDebug() << "Main Tag: " << docElem.attribute("NoOfProfiles") << endl; + + QDomNode n = docElem.firstChild(); + while(!n.isNull()) { + QDomElement e = n.toElement(); // try to convert the node to an element. + if(!e.isNull()) { + qDebug() << "Name" << qPrintable(e.tagName()) << e.attribute("Name") << endl; // the node really is an element. + qDebug() << "NoOfSteps" << qPrintable(e.tagName()) << e.attribute("NoOfSteps") << endl; // the node really is an element. + } + QDomNode node = n.firstChild(); + for(int i = 0; i < e.attribute("NoOfSteps").toInt(); i++) + { + QDomElement elem = node.toElement(); + if(!elem.isNull()) + { + qDebug() << "Value" << qPrintable(elem.tagName()) << elem.attribute("Value") << endl; // the node really is an element. + qDebug() << "Delay" << qPrintable(elem.tagName()) << elem.attribute("Delay") << endl; // the node really is an element. + } + node = node.nextSibling(); + } + n = n.nextSibling(); + } + + */ + +#endif // XMLUTIL_H diff --git a/xmlutil.cpp b/xmlutil.cpp new file mode 100644 index 0000000..e090c66 --- /dev/null +++ b/xmlutil.cpp @@ -0,0 +1,136 @@ +#include "xmlutil.h" +#include + +Xmlutil::Xmlutil(QObject *parent) : + QObject(parent) +{ +} + +QDomElement Xmlutil::addElement(QDomDocument &doc, QDomNode &node, + const QString &tag, const QString &value) +{ + QDomElement element = doc.createElement(tag); + node.appendChild(element); + if(!value.isNull()) + { + QDomText text = doc.createTextNode(value); + element.appendChild(text); + } + return element; +} + +/* +// Unit test from main + + Steps step("+4670", 1); + int error = 0; + + Profile p; + p.mName = "Diva"; + p.mNoOfSteps = 2; + p.mSteps.append(step); + step.setDelay(2); + step.setValue("+4788"); + p.mSteps.append(step); + + qDebug() << p.generateProfileXML(p, error); + +*/ +QString Xmlutil::generateProfileXML(const Profile &profile, int *error, + QDomDocument *doc, QDomElement *elem) +{ + QDomDocument *pDoc = NULL; + if(0 == doc) + pDoc = new QDomDocument; + else + pDoc = doc; + + QDomElement domElement; + + if(0 == elem) + domElement = Xmlutil::addElement(*pDoc, *pDoc, PROFILE_ELEM_TAG); + else + domElement = Xmlutil::addElement(*pDoc, *elem, PROFILE_ELEM_TAG); + + domElement.setAttribute(NAME_ATTR, profile.mName); + domElement.setAttribute(NO_OF_STEPS_ATTR, profile.mNoOfSteps); + + if(profile.mNoOfSteps > 0) + { + for(unsigned int i = 0; i < profile.mNoOfSteps; i++) + { + QDomElement stepEl = Xmlutil::addElement(*pDoc, domElement, STEP_TAG); + Steps step = profile.mSteps.at(i); + stepEl.setAttribute(VALUE_ATTR, step.value()); + stepEl.setAttribute(DELAY_ATTR, step.delay()); + } + } + + QString xmlString = pDoc->toString(); + + if(0 == doc) + delete pDoc; + + return xmlString; +} + +/* +QString generateXML() +{ + Steps step("+4670", 1); + Profile p; + p.mName = "Diva"; + p.mNoOfSteps = 2; + p.mSteps.append(step); + step.setDelay(2); + step.setValue("+4788"); + p.mSteps.append(step); + + return xmlutil::generateProfileXML(p); +} + +// Unit test from main... + + QString xmlString = generateXML(); + Profile p; + + int e = xmlutil::degenerateProfileXML(xmlString, p); +*/ + +int Xmlutil::degenerateProfileXML(const QString xmlString, Profile &profile, + QDomElement *pElem) +{ + QDomDocument doc; + Steps step; + QDomElement *elem = NULL; + if(0 == pElem && !xmlString.isNull()) + { + doc.setContent(xmlString); + *elem = doc.namedItem(PROFILE_ELEM_TAG).toElement(); + } + else + { + elem = pElem; + } + + if(elem->isNull()) + return -1; + + profile.mName = elem->attribute(NAME_ATTR); + profile.mNoOfSteps = elem->attribute(NO_OF_STEPS_ATTR).toInt(); + + qDebug() << profile.mName << ":" << profile.mNoOfSteps; + QDomElement child = elem->firstChild().toElement(); + + profile.mSteps.clear(); + + for(unsigned int i = 0; i < profile.mNoOfSteps ; i++) + { + step.setDelay(child.attribute(DELAY_ATTR).toInt()); + step.setValue(child.attribute(VALUE_ATTR)); + profile.mSteps.append(step); + qDebug() << step.value() << ":" << step.delay(); + child = child.nextSiblingElement(); + } + return 0; +} diff --git a/xmlutil.h b/xmlutil.h new file mode 100644 index 0000000..f51518e --- /dev/null +++ b/xmlutil.h @@ -0,0 +1,79 @@ +#ifndef XMLUTIL_H +#define XMLUTIL_H + +#include +#include +#include "profile.h" + +#define NO_OF_PROFILE_ATTR "NoOfProfiles" +#define PROFILE_TAG "Profiles" +#define PROFILE_ELEM_TAG "Profile" +#define NAME_ATTR "Name" +#define NO_OF_STEPS_ATTR "NoOfSteps" +#define STEP_TAG "Step" +#define VALUE_ATTR "Value" +#define DELAY_ATTR "Delay" + +class Xmlutil : public QObject +{ + Q_OBJECT +public: + explicit Xmlutil(QObject *parent = 0); + + static QDomElement addElement(QDomDocument &doc, QDomNode &node, + const QString &tag, + const QString &value = QString::null); + + static QString generateProfileXML(const Profile &profile, int *error = 0, + QDomDocument *doc = 0, QDomElement *elem = 0); + // returns non-zero on error + static int degenerateProfileXML(const QString xmlString, Profile &profile, + QDomElement *pElem = 0); + +// QDomElement removeElement +signals: + +public slots: + +}; + +/* + QDomDocument doc("mydocument"); + QFile file(argv[1]); + if (!file.open(QIODevice::ReadOnly)) + return -1; + if (!doc.setContent(&file)) { + file.close(); + return -1; + } + file.close(); + +// print out the element names of all elements that are direct children +// of the outermost element. + QDomElement docElem = doc.namedItem("Profiles").toElement(); + qDebug() << "Main Tag: " << docElem.attribute("NoOfProfiles") << endl; + + QDomNode n = docElem.firstChild(); + while(!n.isNull()) { + QDomElement e = n.toElement(); // try to convert the node to an element. + if(!e.isNull()) { + qDebug() << "Name" << qPrintable(e.tagName()) << e.attribute("Name") << endl; // the node really is an element. + qDebug() << "NoOfSteps" << qPrintable(e.tagName()) << e.attribute("NoOfSteps") << endl; // the node really is an element. + } + QDomNode node = n.firstChild(); + for(int i = 0; i < e.attribute("NoOfSteps").toInt(); i++) + { + QDomElement elem = node.toElement(); + if(!elem.isNull()) + { + qDebug() << "Value" << qPrintable(elem.tagName()) << elem.attribute("Value") << endl; // the node really is an element. + qDebug() << "Delay" << qPrintable(elem.tagName()) << elem.attribute("Delay") << endl; // the node really is an element. + } + node = node.nextSibling(); + } + n = n.nextSibling(); + } + + */ + +#endif // XMLUTIL_H -- 1.7.9.5